Wed, 09 Feb 2011 15:43:48 +0000
fix stupid mistakes in keyboard code (i broke the build, w00t...)
1 #include <stdbool.h>
2 #include "SDL.h"
3 #include "keyboard.h"
5 /**
6 * Key map -- a mapping from SDLK_xxx constants to scancodes and vice versa.
7 */
8 struct {
9 SDLKey key; ///< SDLK_xxx key code constant
10 int extended; ///< 1 if this is an extended keycode
11 unsigned char scancode; ///< Keyboard scan code
12 } keymap[] = {
13 { SDLK_UP, 0, 0x01 }, // ROLL/Up [UpArrow]
14 { SDLK_KP2, 0, 0x01 }, // ROLL/Up [Keypad 2]
15 // { SDLK_, 1, 0x02 }, // Clear Line
16 // { SDLK_, 1, 0x03 }, // Rstrt / Ref
17 // { SDLK_, 1, 0x04 }, // Exit
18 { SDLK_KP1, 0, 0x05 }, // PREV [Keypad 1]
19 // { SDLK_, 1, 0x06 }, // Msg
20 // { SDLK_, 1, 0x07 }, // Cancl
21 { SDLK_BACKSPACE, 0, 0x08 }, // Backspace
22 { SDLK_TAB, 0, 0x09 }, // Tab
23 // { SDLK_RETURN, 1, 0x0a }, // ENTER
24 { SDLK_DOWN, 0, 0x0b }, // ROLL/Down [DownArrow]
25 { SDLK_KP0, 0, 0x0b }, // ROLL/Down [Keypad 0]
26 { SDLK_KP3, 0, 0x0c }, // NEXT [Keypad 3]
27 { SDLK_RETURN, 0, 0x0d }, // RETURN [Return]
28 { SDLK_LEFT, 0, 0x0e }, // <-- [LeftArrow]
29 { SDLK_KP_MINUS, 0, 0x0e }, // <-- [Keypad -]
30 { SDLK_RIGHT, 0, 0x0f }, // --> [RightArrow]
31 { SDLK_KP_PERIOD, 0, 0x0f }, // --> [Keypad .]
32 // { SDLK_, 1, 0x10 }, // Creat
33 // { SDLK_, 1, 0x11 }, // Save
34 // { SDLK_, 1, 0x12 }, // Move
35 // { SDLK_, 1, 0x13 }, // Ops
36 // { SDLK_, 1, 0x14 }, // Copy
37 { SDLK_F1, 0, 0x15 }, // F1
38 { SDLK_F2, 0, 0x16 }, // F2
39 { SDLK_F3, 0, 0x17 }, // F3
40 { SDLK_F4, 0, 0x18 }, // F4
41 { SDLK_F5, 0, 0x19 }, // F5
42 { SDLK_F6, 0, 0x1a }, // F6
43 { SDLK_ESCAPE, 0, 0x1b }, // ESC/DEL [Escape]
44 { SDLK_F7, 0, 0x1c }, // F7
45 { SDLK_F8, 0, 0x1d }, // F8
46 // { SDLK_, 1, 0x1e }, // Suspd
47 // { SDLK_, 1, 0x1f }, // Rsume
48 { SDLK_SPACE, 0, 0x20 }, // SPACE [Spacebar]
49 // { SDLK_, 1, 0x21 }, // Undo
50 // { SDLK_, 1, 0x22 }, // Redo
51 // { SDLK_, 1, 0x23 }, // FIND
52 // { SDLK_, 1, 0x24 }, // RPLAC
53 { SDLK_BREAK, 0, 0x25 }, // RESET/BREAK [Pause/Break]
54 // { SDLK_, 1, 0x26 }, // DleteChar
55 { SDLK_QUOTE, 0, 0x27 }, // ' (single-quote)
56 // { SDLK_, 1, 0x28 }, // SLCT/MARK
57 // { SDLK_, 1, 0x29 }, // INPUT/MODE
58 // { SDLK_, 1, 0x2a }, // HELP
59 // Keycode 2B not used
60 { SDLK_COMMA, 0, 0x2c }, // , [Comma]
61 { SDLK_MINUS, 0, 0x2d }, // - [Dash]
62 { SDLK_PERIOD, 0, 0x2e }, // . [Period]
63 { SDLK_SLASH, 0, 0x2f }, // / [Forward-slash]
64 { SDLK_0, 0, 0x30 }, // 0
65 { SDLK_1, 0, 0x31 }, // 1
66 { SDLK_2, 0, 0x32 }, // 2
67 { SDLK_3, 0, 0x33 }, // 3
68 { SDLK_4, 0, 0x34 }, // 4
69 { SDLK_5, 0, 0x35 }, // 5
70 { SDLK_6, 0, 0x36 }, // 6
71 { SDLK_7, 0, 0x37 }, // 7
72 { SDLK_8, 0, 0x38 }, // 8
73 { SDLK_9, 0, 0x39 }, // 9
74 // Keycode 3A not used
75 { SDLK_SEMICOLON, 0, 0x3b }, // ; [Semicolon]
76 // Keycode 3C not used
77 { SDLK_EQUALS, 0, 0x3d }, // = [Equals]
78 // Keycodes 3E, 3F, 40 not used
79 // { SDLK_, 1, 0x41 }, // CMD
80 // { SDLK_, 1, 0x42 }, // CLOSE/OPEN
81 { SDLK_KP7, 0, 0x43 }, // PRINT
82 { SDLK_KP8, 0, 0x44 }, // CLEAR/RFRSH
83 { SDLK_CAPSLOCK, 0, 0x45 }, // Caps Lock
84 { SDLK_KP9, 0, 0x46 }, // PAGE
85 { SDLK_KP4, 0, 0x47 }, // BEG
86 { SDLK_LSHIFT, 0, 0x48 }, // Left Shift
87 { SDLK_RSHIFT, 0, 0x49 }, // Right Shift
88 { SDLK_HOME, 0, 0x4a }, // Home
89 { SDLK_KP5, 0, 0x4a }, // Home [Keypad 5]
90 { SDLK_END, 0, 0x4b }, // End
91 { SDLK_KP6, 0, 0x4b }, // End [Keypad 6]
92 { SDLK_LCTRL, 0, 0x4c }, // Left Ctrl? \___ not sure which is left and which is right...
93 { SDLK_RCTRL, 0, 0x4d }, // Right Ctrl? /
94 // Keycodes 4E thru 5A not used
95 { SDLK_LEFTBRACKET, 0, 0x5b }, // [
96 { SDLK_BACKSLASH, 0, 0x5c }, // \ (backslash)
97 { SDLK_RIGHTBRACKET, 0, 0x5d }, // ]
98 // Keycodes 5E, 5F not used
99 { SDLK_BACKQUOTE, 0, 0x60 }, // `
100 { SDLK_a, 0, 0x61 }, // A
101 { SDLK_b, 0, 0x62 }, // B
102 { SDLK_c, 0, 0x63 }, // C
103 { SDLK_d, 0, 0x64 }, // D
104 { SDLK_e, 0, 0x65 }, // E
105 { SDLK_f, 0, 0x66 }, // F
106 { SDLK_g, 0, 0x67 }, // G
107 { SDLK_h, 0, 0x68 }, // H
108 { SDLK_i, 0, 0x69 }, // I
109 { SDLK_j, 0, 0x6a }, // J
110 { SDLK_k, 0, 0x6b }, // K
111 { SDLK_l, 0, 0x6c }, // L
112 { SDLK_m, 0, 0x6d }, // M
113 { SDLK_n, 0, 0x6e }, // N
114 { SDLK_o, 0, 0x6f }, // O
115 { SDLK_p, 0, 0x70 }, // P
116 { SDLK_q, 0, 0x71 }, // Q
117 { SDLK_r, 0, 0x72 }, // R
118 { SDLK_s, 0, 0x73 }, // S
119 { SDLK_t, 0, 0x74 }, // T
120 { SDLK_u, 0, 0x75 }, // U
121 { SDLK_v, 0, 0x76 }, // V
122 { SDLK_w, 0, 0x77 }, // W
123 { SDLK_x, 0, 0x78 }, // X
124 { SDLK_y, 0, 0x79 }, // Y
125 { SDLK_z, 0, 0x7a }, // Z
126 // Keycodes 7B, 7C, 7D not used
127 { SDLK_NUMLOCK, 0, 0x7e }, // Numlock
128 { SDLK_DELETE, 0, 0x7f } // Dlete
129 };
131 void keyboard_init(KEYBOARD_STATE *ks)
132 {
133 // Set all key states to "not pressed"
134 for (int i=0; i<(sizeof(ks->keystate)/sizeof(ks->keystate[0])); i++) {
135 ks->keystate[i] = 0;
136 }
138 // Reset the R/W pointers and length
139 ks->readp = ks->writep = ks->buflen = 0;
140 }
142 void keyboard_event(KEYBOARD_STATE *ks, SDL_Event *ev)
143 {
144 // Ignore non-keyboard events
145 if ((ev->type != SDL_KEYDOWN) && (ev->type != SDL_KEYUP)) return;
147 // scan the keymap
148 int keyidx = 0;
149 for (keyidx=0; keyidx < sizeof(keymap)/sizeof(keymap[0]); keyidx++) {
150 if (keymap[keyidx].key == ev->key.keysym.sym) break;
151 }
153 switch (ev->type) {
154 // key pressed
155 case SDL_KEYDOWN:
156 ks->keystate[keymap[keyidx].scancode] = 1;
157 break;
158 // key released
159 case SDL_KEYUP:
160 ks->keystate[keymap[keyidx].scancode] = 1;
161 break;
162 }
163 }
165 void keyboard_scan(KEYBOARD_STATE *ks)
166 {
167 // if buffer empty, do a keyboard scan
168 if (ks->buflen == 0) {
169 // TODO: inject "keyboard data follows" chunk header
170 for (int i=0; i<(sizeof(ks->keystate)/sizeof(ks->keystate[0])); i++) {
171 if (ks->keystate[i]) {
172 ks->buffer[ks->writep] = i;
173 ks->writep = (ks->writep + 1) % KEYBOARD_BUFFER_SIZE;
174 }
175 }
176 // TODO: inject "mouse data follows" chunk header and mouse movement info
177 }
178 }
180 bool keyboard_get_irq(KEYBOARD_STATE *ks)
181 {
182 bool irq_status = false;
184 // Conditions which may cause an IRQ :-
185 // Read Data Reg has data and RxIRQ enabled
186 if (ks->rxie)
187 if (ks->buflen > 0) irq_status = true;
189 // Transmit Data Reg empty and TxIRQ enabled
190 // if (ks->txie)
192 // DCD set and RxIRQ enabled
193 //
195 // returns interrupt status -- i.e. is there data in the buffer?
196 return irq_status;
197 }
199 uint8_t keyboard_read(KEYBOARD_STATE *ks, uint8_t addr)
200 {
201 if ((addr & 1) == 0) {
202 // Status register -- RS=0, read
203 return
204 (ks->buflen > 0) ? 1 : 0 + // SR0: a new character has been received
205 0 + // SR1: Transmitter Data Register Empty
206 0 + // SR2: Data Carrier Detect
207 0 + // SR3: Clear To Send
208 0 + // SR4: Framing Error
209 0 + // SR5: Receiver Overrun
210 0 + // SR6: Parity Error
211 (keyboard_get_irq(ks)) ? 0x80 : 0; // SR7: IRQ status
212 } else {
213 // return data, pop off the fifo
214 uint8_t x = ks->buffer[ks->readp];
215 ks->readp = (ks->readp + 1) % KEYBOARD_BUFFER_SIZE;
216 return x;
217 }
218 }
220 void keyboard_write(KEYBOARD_STATE *ks, uint8_t addr, uint8_t val)
221 {
222 if ((addr & 1) == 0) {
223 // write to control register
224 // transmit intr enabled when CR6,5 = 01
225 // receive intr enabled when CR7 = 1
227 // CR0,1 = divider registers. When =11, do a software reset
228 if ((val & 3) == 3) {
229 ks->readp = ks->writep = ks->buflen = 0;
230 }
232 // Ignore CR2,3,4 (word length)...
234 // CR5,6 = Transmit Mode
235 ks->txie = (val & 0x60)==0x20;
237 // CR7 = Receive Interrupt Enable
238 ks->rxie = (val & 0x80)==0x80;
239 } else {
240 // Write command to KBC -- TODO!
241 }
242 }