-
Notifications
You must be signed in to change notification settings - Fork 52
/
Copy pathappendix-keyboard.tex
332 lines (264 loc) · 18.5 KB
/
appendix-keyboard.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
\chapter{The MEGA65 Keyboard}
\label{cha:keyboard}
The MEGA65 has a full mechanical keyboard which is compatible with the C65 and C64 keyboards, and features four distinct cursor keys which work in both C64 and C65-mode, as well as eleven new C65 keys that normally work only in
C65-mode.
There are several ways to read the keyboard from programs. BASIC programs can use the {\bf GET} or {\bf GETKEY} commands, which read a PETSCII keycode into a variable, without or with waiting for a typing event. Machine language programs that keep the KERNAL active can use the KERNAL {\tt getin} routine at \$FFE4, which loads a PETSCII code into the accumulator. These routines have the advantage of supporting other features of the KERNAL input stream, such as function key macros and input redirection.
For a machine code program that doesn't use the KERNAL and wants to use the keyboard for standard typing applications (such as a word processor), the MEGA65 provides a {\em typing event queue} implemented directly in hardware. A {\em typing event} occurs when the user presses a non-modifier key, holding zero or more modifier keys down while doing so. The typing event queue remembers the key being pressed and the modifiers being held, for up to a certain number of events. The program is expected to dequeue each event as it is processed, making room in hardware memory for new events. A program can read typing events as either PETSCII or ASCII values directly from hardware registers. The modifier keys associated with the event are also readable from a register.
The MEGA65 KERNAL uses the typing event queue to power {\tt getin} and the BASIC {\bf GET} and {\bf GETKEY} commands. Reading a key using any of these methods dequeues a typing event from the queue.
The MEGA65 also provides direct hardware access to the matrix using dedicated registers, so MEGA65 programs can test for any combination of keys being pressed. This is useful for games that use the keyboard as a game controller.
Legacy C64 and C65 programs, including the original C65 ROM, use the CIA chips as the hardware interface to the keyboard. The MEGA65 keyboard implements the C65 keyboard matrix for the CIA chip. This interface has inherent shortcomings common to Commodore computers, including slower key response and ``ghosted'' keys in certain key combinations. MEGA65 programs will get better results using the KERNAL, typing event queue, or keyboard matrix register methods.
\section{Using the Typing Event Queue}
The status of the typing event queue is visible on these registers:
\begin{center}
\begin{tabular}{|p{5.5em}|p{6em}|p{22em}|}
\hline
\bf{Name} & \bf{I/O address} & \bf{Description} \\
\hline
ASCIIKEY & \$D610 & The top event as ASCII, \$FF if no interpretation, or \$00 if queue is empty \\
\hline
PETSCIIKEY & \$D619 & The top event as PETSCII, or \$FF if no interpretation \\
\hline
MODKEY & \$D60A[0:6] & Modifier keys held during the event \\
\hline
KEYQUEUE & \$D60A[7] & 1 if the queue is non-empty \\
\hline
\end{tabular}
\end{center}
The bits of MODKEY \$D60A correspond to these modifier keys. If a bit is set, then the key
was held during the event:
\nopagebreak
\begin{center}
{\renewcommand{\arraystretch}{1.7}
\begin{tabular}{|*{7}{>{\centering\arraybackslash}p{3em}|}}
\hline
\bf{Bit 6} & \bf{Bit 5} & \bf{Bit 4} & \bf{Bit 3} & \bf{Bit 2} & \bf{Bit 1} & \bf{Bit 0} \\
\hline
\specialkey{CAPS\\LOCK} & \specialkey{NO\\SCROLL} & \specialkey{ALT} & \megasymbolkey & \specialkey{CTRL} & \specialkey{SHIFT\\right} & \specialkey{SHIFT\\left} \\
\hline
\end{tabular}}
\end{center}
If ASCIIKEY (\$D610) reads as \$00, then the typing queue is empty. A program must test ASCIIKEY for \$00, or test KEYQUEUE (bit 7 of \$D60A), to determine if the queue is empty. The PETSCIIKEY register does not have a value that
represents the empty queue.
A given typing event may or may not have an ASCII or PETSCII interpretation. A typing event that has neither is not added to the queue. If an event has an ASCII interpretation but not a PETSCII interpretation, then ASCIIKEY will contain the ASCII value, and PETSCIIKEY will contain \$FF. Similarly, ASCIIKEY will contain \$FF for typing events without an ASCII interpretation. The program is expected to use the other registers to determine whether the queue is empty, and skip typing events that do not have an interpretation useful to the program.
\underline{NOTE}: ASCII also uses \$FF to represent the "umlaut-y" character (Alt+Y). In this case (and only in this case), PETSCIIKEY is \$59 (regular Y). If your program needs to distinguish between a non-ASCII typing event and Alt+Y, test whether PETSCIIKEY is \$59 when ASCIIKEY is \$FF.
To dequeue the top typing event, write any value to either ASCIIKEY (\$D610) or PETSCIIKEY (\$D619). If the queue has another event, it becomes visible on the registers. Otherwise, the registers go to their empty queue state.
\subsection{Interpreting ASCII Typing Events}
The ASCIIKEY register makes it possible to read entry of the ASCII symbols not available in PETSCII, including \{, \_ and |, which are not possible to type on a normal C64 and C128 keyboards. The keyboard and the ASCII interpretation supports most Latin-1 code-page characters, allowing the entry of many accented characters. These keys are entered by holding down \megasymbolkey and pressing other keys or key-combinations. The use of ASCII or Unicode basic-Latin symbols not present in the PETSCII character set requires the use of a font that contains these symbols, and software which supports them.
The following tables show the hex value and Unicode character that will be produced by each key combination on the ASCIIKEY register. One table is provided for pressing a key on its own, and one table for each of the \specialkey{SHIFT}, \specialkey{CTRL}, \megasymbolkey, and \specialkey{ALT} keys.
\begin{minipage}{\textwidth}
\bf{Keys pressed alone:}
\input{keymap_table_1}
\end{minipage}
\begin{minipage}{\textwidth}
\bf{Keys pressed with \specialkey{SHIFT}}
\input{keymap_table_2}
\end{minipage}
\begin{minipage}{\textwidth}
\bf{Keys pressed with \specialkey{CTRL}}
\input{keymap_table_3}
\end{minipage}
\begin{minipage}{\textwidth}
\bf{Keys pressed with \megasymbolkey}
\input{keymap_table_4}
\end{minipage}
\begin{minipage}{\textwidth}
\bf{Keys pressed with \specialkey{ALT}}
\input{keymap_table_5}
\end{minipage}
\subsection{Unicode Basic-Latin Keyboard Map}
The following tables are a convenient reference to help you find a key combination that will produce the desired ASCII/Unicode basic-Latin character code. Note that a few codes are difficult to type in practice, because they are mapped to key combinations that perform other functions. In particular, the combination of \megasymbol + \specialkey{TAB} is normally overridden by the Matrix Mode hardware debug feature.
\input{unicode_mapping}
\newpage
\section{Keyboard Theory of Operation}
The MEGA65 keyboard is a full mechanical keyboard, constructed as a matrix. Every key switch is fitted with a diode, which allows the keyboard hardware to detect when any combination of keys are pressed at the same time. This matrix is scanned by the firmware in the CPLD chip on the keyboard PCB many thousands of times per second.
The matrix arrangement of the MEGA65 keyboard does not use the C65 matrix layout. Instead, the CPLD sorts the natural matrix of the keyboard into the C65 keyboard matrix order, then transmits the C65 matrix coordinates serially via the keyboard cable to the MEGA65 mainboard. The MEGA65 core reads this serial data and uses it to reconstruct a C65-compatible virtual keyboard in the FPGA. This virtual keyboard can also accept input from the
on-screen-keyboard, the synthetic keyboard injection mechanism, and other keyboard input sources, depending on the MEGA65 model.
The end-to-end latency of the keyboard is less than one millisecond.
\section{C65 Keyboard Matrix}
The MEGA65 keyboard is designed to mimic the Commodore 65 keyboard matrix consisting of nine columns and eight rows. Legacy C65 software (such as the C65 ROM) uses the CIA chip to scan the first eight columns of the matrix, in the same arrangement as keys appear on a Commodore 64. Keys exclusive to the C65 (No Scroll, Tab, Alt, etc.) use an eighth column not accessible via the CIA. A legacy program can access the ninth column using bit 1 of I/O port E, with the data register at \$D607 and the data direction register at \$D608.
Programs written for the MEGA65 can use a dedicated set of registers capable of detecting any combination of keys being pressed at the same time:
\begin{itemize}
\item \$D614: C65 keyboard matrix column select; write integer 0 -- 8
\item \$D613: C65 keyboard matrix column data; bit for row is clear if key is pressed
\item \$D611[0:6]: Modifier key data; bit is set if modifier key is pressed
\item \$D604[0:1]: Disambiguation bits for cursor left and cursor up; bit is set if key is pressed
\end{itemize}
In the following C65 keyboard matrix, each non-modifier physical key appears in exactly once, in one of nine columns numbered 0 to 8, and in one of eight rows numbered 0 to 7.
\index{Keyboard!matrix}
{\ttfamily
{
\setlength{\def\arraystretch{1.5}\tabcolsep}{1mm}
\begin{center}
\begin{tabular}{|c*{9}{|C{1.02cm}}|}
\hline
& \bf{0} & \bf{1} & \bf{2} & \bf{3} & \bf{4} & \bf{5} & \bf{6} & \bf{7} & \bf{8} \\
\hline
\small \bf{0} & \specialkey{INST\\DEL} & 3 & 5 & 7 & 9 & + & \pounds & 1 & \specialkey{NO\\SCROLL} \\
\hline
\small \bf{1} & \specialkey{RETURN} & W & R & Y & I & P & * & \megakeywhite{$\leftarrow$} & \specialkey{TAB} \\
\hline
\small \bf{2} & \megakey{$\rightarrow$} & A & D & G & J & L & ; & \specialkey{CTRL} & \specialkey{ALT} \\
\hline
\small \bf{3} & \megakey{F7} & 4 & 6 & 8 & 0 & - & \specialkey{CLR\\HOME} & 2 & \specialkey{HELP} \\
\hline
\small \bf{4} & \megakey{F1} & Z & C & B & M & . & \specialkey{SHIFT\\right} & \megakey{SPC} & \megakey{F9} \\
\hline
\small \bf{5} & \megakey{F3} & S & F & H & K & : & = & \megasymbolkey & \megakey{F11} \\
\hline
\small \bf{6} & \megakey{F5} & E & T & U & O & @ & \megakeywhite{$\uparrow$} & Q & \megakey{F13} \\
\hline
\small \bf{7} & \megakey{$\downarrow$} & \specialkey{SHIFT\\left} & X & V & N & , & / & \specialkey{RUN\\STOP} & \specialkey{ESC} \\
\hline
\end{tabular}
\end{center}
}}
To test whether a key is being pressed, write the column number to register \$D614 (54804 decimal) as a binary-coded integer, then read the bit that corresponds to the row from register \$D613 (54803 decimal). If the bit is zero, then the key is pressed. (A bit value of one means the key is \emph{not} pressed.)
For example, to test whether the Help key is being pressed:
\begin{asmcode}
LDA #$08 ; column 8
STA $D614
LDA $D613
AND #%00001000 ; row 3
BEQ help_key_is_pressed ; unset = pressed
\end{asmcode}
Register \$D611 describes the current state of the modifier keys. If a bit is set, the key is pressed.
\begin{center}
{\renewcommand{\arraystretch}{1.7}
\begin{tabular}{|*{7}{>{\centering\arraybackslash}p{3em}|}}
\hline
\bf{Bit 6} & \bf{Bit 5} & \bf{Bit 4} & \bf{Bit 3} & \bf{Bit 2} & \bf{Bit 1} & \bf{Bit 0} \\
\hline
\specialkey{CAPS\\LOCK} & \specialkey{NO\\SCROLL} & \specialkey{ALT} & \megasymbolkey & \specialkey{CTRL} & \specialkey{SHIFT\\right} & \specialkey{SHIFT\\left} \\
\hline
\end{tabular}}
\end{center}
The original Commodore 64 keyboard had only two cursor keys, one for down/up and one for right/left, where the user would hold shift to select the opposite direction on the key. The Commodore 65 keyboard has separate cursor keys for all four directions. For compatibility, the C65 maintains the shifted representation in the keyboard matrix for cursor up and cursor left: cursor up is right-shift and cursor down, cursor left is right-shift and cursor right.
To make it possible to distinguish between all combinations of cursor keys being pressed simultaneously (such as cursor up and cursor down pressed together), the MEGA65 provides one more register, \$D604 bits 0 and 1. Bit 0 is set if cursor left is pressed, and bit 1 is set if cursor up is pressed.
All together, these registers make it possible for a program to scan for every combination of keys being pressed.
\section{Synthetic Key Events}
The MEGA65 keyboard interface logic allows the use of a variety of keyboard types and alternatives. This is partly
to cater for the early development on general purpose FPGA boards, the MEGAphone with its touch interface, and the
desktop versions of the MEGA65 architecture.
One possible keyboard input available on all models is the virtual keypress queue. A program or the serial debugger can simulate up to three physical keys being pressed by writing each key's scan code to the registers \$D615 -- \$D617.
The scan code for a physical key can be calculated from the C65 keyboard matrix. For the first eight columns, the scan code is the column number multiplied by eight, plus the row number. For example, the Home key is in column 6 and row 3, so the scan code is $6 \times 8 + 3 = 51$. Scan codes for the ninth column are 64 -- 71, assigned from top to bottom. For example, the Tab key is scan code 65.
A virtual key will be seen as held down until the next update to the register. To release a key, write \$7F to the register.
\widekey{RESTORE} exists outside of the keyboard matrix, as on the C64. To simulate holding \widekey{RESTORE} down, write \$52 (ASCII code for a capital R). To simulate a quick tap of the \widekey{RESTORE}, write \$72 (ASCII code for a lowercase R). Another value must be written after the \$72 value has been written, if you wish to simulate multiple presses of \widekey{RESTORE}.
The following is a demonstration of using the virtual key register from BASIC to simulate briefly pressing the \texttt{*} key:
\begin{basiccode}
POKE $D615, 6*8+1:FOR I = 1 TO 100:NEXT:POKE $D615, 127
\end{basiccode}
The FOR loop provides a suitable delay to simulate holding the key for a short time. All statements should be on a single line like this if entered directly into the BASIC interpreter, because otherwise the MEGA65 will continue to act as though the \texttt{*} key is being held down, making it rather difficult to enter the other commands!
\section{Keyboard LED Control}
The lights on the MEGA65's keyboard are normally controlled automatically by the system, such as to represent power status (left light) or disk activity (right light). It is also possible to control them from a program. Each of the two lights consists of two RGB LEDs. The intensity of the red, green, and blue components of each light can be assigned separately.
You can set the LED color values using two registers: the control register \$D61D (decimal 54813) and a value update register \$D61E.
Bit 7 of the control register \$D61D determines whether the lights are controlled by the system (clear) or a program (set). The lower bits select one of the twelve RGB channels (four LEDs, a red, green, and blue for each) to update.
\begin{adjustwidth}{}{-2cm}
\begin{description}[align=left,labelwidth=0.2cm]
\item[ 0] left-half of DRIVE LED, RED
\item[ 1] left-half of DRIVE LED, GREEN
\item[ 2] left-half of DRIVE LED, BLUE
\item[ 3] right-half of DRIVE LED, RED
\item[ 4] right-half of DRIVE LED, GREEN
\item[ 5] right-half of DRIVE LED, BLUE
\item[ 6] left-half of POWER LED, RED
\item[ 7] left-half of POWER LED, GREEN
\item[ 8] left-half of POWER LED, BLUE
\item[ 9] right-half of POWER LED, RED
\item[10] right-half of POWER LED, GREEN
\item[11] right-half of POWER LED, BLUE
\end{description}
\end{adjustwidth}
To set the intensity of an LED color component, write the component number and bit 7 high (+ 128) to \$D61D, then write the intensity value to \$D61E. The intensity is a value between 0 and 255.
The keyboard logic needs approximately one millisecond to update after writing. A best practice is to write \$FF (255 decimal) to \$D61D prior to setting the component number.
To return the keyboard LEDs to system control, clear bit 7 of \$D61D.
The following example pulses the keyboard LEDs between red and blue:
\input{examples/ledcycle}
\newpage
\section{Native Keyboard Matrix}
The native keyboard matrix is accessible only from the CPLD on the MEGA65's keyboard. If you are programming the MEGA65 computer, you should not need to use this. This is listed here for the convenience of the platform developers.
\begin{adjustwidth}{}{-2cm}
\begin{multicols}{2}
\begin{description}[align=left,labelwidth=0.2cm]
\item [0] \megakey{F5}
\item [1] 9
\item [2] I
\item [3] K
\item [4] <
\item [5] \specialkey{INST\\DEL}
\item [6] \specialkey{CLR\\HOME}
\item [7] O
\item [8] \megakey{F3}
\item [9] 8
\item [10] U
\item [11] J
\item [12] M
\item [13] \megakey{$\rightarrow$}
\item [14] \pounds
\item [15] =
\item [16] \megakey{F1}
\item [17] 7
\item [18] Y
\item [19] H
\item [20] N
\item [21] \megakey{$\downarrow$}
\item [22] -
\item [23] ;
\item [24] Reserved
\item [25] 6
\item [26] T
\item [27] G
\item [28] B
\item [29] \megakey{$\leftarrow$} (cursor left)
\item [30] +
\item [31] :
\item [32] \specialkey{NO\\SCROLL}
\item [33] 5
\item [34] R
\item [35] F
\item [36] V
\item [37] \megakey{SPACE}
\item [38] 0
\item [39] L
\item [40] \specialkey{CAPS\\LOCK}
\item [41] 4
\item [42] E
\item [43] D
\item [44] C
\item [45] Reserved
\item [46] \specialkey{HELP}
\item [47] \specialkey{RETURN}
\item [48] \specialkey{ALT}
\item [49] 3
\item [50] W
\item [51] S
\item [52] X
\item [53] \megakey{$\uparrow$} (cursor up)
\item [54] \megakey{F13}
\item [55] \megakeywhite{$\uparrow$} (next to \widekey{RESTORE})
\item [56] \specialkey{ESC}
\item [57] 2
\item [58] Q
\item [59] A
\item [60] Z
\item [61] right \specialkey{SHIFT}
\item [62] \megakey{F11}
\item [63] *
\item [64] Reserved
\item [65] 1
\item [66] Reserved
\item [67] Reserved
\item [68] left \specialkey{SHIFT} and \specialkey{SHIFT\\LOCK}
\item [69] /
\item [70] \megakey{F9}
\item [71] @
\item [72] \specialkey{RUN\\STOP}
\item [73] \megakeywhite{$\leftarrow$} (next to 1)
\item [74] \specialkey{TAB}
\item [75] \specialkey{CTRL}
\item [76] \megasymbolkey
\item [77] >
\item [78] \megakey{F7}
\item [79] P
\end{description}
\end{multicols}
\end{adjustwidth}