summaryrefslogtreecommitdiff
path: root/kbc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbc.c')
-rw-r--r--kbc.c166
1 files changed, 126 insertions, 40 deletions
diff --git a/kbc.c b/kbc.c
index b7bce72..c560326 100644
--- a/kbc.c
+++ b/kbc.c
@@ -48,6 +48,9 @@ enum state {
48 STATE_CONFIG, 48 STATE_CONFIG,
49 STATE_IDLE, 49 STATE_IDLE,
50 STATE_IDLEBLINK, 50 STATE_IDLEBLINK,
51 STATE_INPUT,
52 STATE_ACCEPT,
53 STATE_REJECT
51}; 54};
52static volatile enum state state, nextstate; 55static volatile enum state state, nextstate;
53 56
@@ -114,47 +117,72 @@ static void dbg_init(void)
114 SPCR = (1 << SPIE) | (1 << SPE); 117 SPCR = (1 << SPIE) | (1 << SPE);
115} 118}
116 119
117
118
119
120static volatile uint8_t statecntr = 0; 120static volatile uint8_t statecntr = 0;
121 121
122#define mayabort if (TIFR0 & (1 << TOV0)) return 0; 122#define mayabort if (TIFR0 & (1 << TOV0)) return bit;
123#define wait_CLKlo while (PIND & D_CLK) { __asm__ volatile ("nop\n"); mayabort; } 123#if 0
124#define wait_CLKhi while (!(PIND & D_CLK)) { __asm__ volatile ("nop\n"); mayabort; } 124#define _wait_CLK(cond) do { \
125#define wait_CLK wait_CLKhi; wait_CLKlo; _delay_us(5) 125 p2 = p1 = p0 = PIND; \
126 while (cond) { \
127 p2 = p1; p1 = p0; p0 = PIND; \
128 __asm__ volatile ("nop\n"); \
129 mayabort; \
130 } \
131 } while (0)
132#else
133#define _wait_CLK(cond) while(cond) { mayabort; }
134#endif
135#define wait_CLKlo _wait_CLK( PIND /* & p0 & p1 & p2 */ & D_CLK)
136#define wait_CLKhi _wait_CLK(!(PIND /* & p0 & p1 & p2 */ & D_CLK))
137#define wait_CLK wait_CLKhi; wait_CLKlo; _delay_us(15)
138#define wait_CLKb
139
140#define wait_CLK_set wait_CLKlo
141#define wait_CLK_samp wait_CLKhi
126 142
127static void timer_return(void) 143static void timer_return(void)
128{ 144{
129 TCNT0 = 0; 145 TCNT0 = 0;
130 TIFR0 |= (1 << TOV0); 146 TIFR0 = (1 << TOV0);
131 __asm__ volatile("nop\n"); 147 __asm__ volatile("nop\n");
132 TIMSK0 = (1 << TOIE0); 148 TIMSK0 = (1 << TOIE0);
133} 149}
134 150
135static uint8_t do_send_byte(uint8_t byte) 151static void timer_clear(void)
152{
153 TCNT0 = 0;
154 __asm__ volatile("nop\n");
155 TIFR0 = (1 << TOV0);
156}
157
158static uint16_t do_send_byte(uint8_t byte)
136{ 159{
137 uint8_t bit = 0, parity = 1, rv, usarts; 160 uint8_t bit = 0, parity = 1, rv, usarts;
161 uint8_t p2, p1, p0;
138 162
139 usart_dis(); 163 usart_dis();
140 164
165 _delay_us(5);
166
141 /* make clock low, request clock from keyboard */ 167 /* make clock low, request clock from keyboard */
142 PORTD &= ~D_CLK; 168 PORTD &= ~D_CLK;
143 DDRD |= D_CLK; 169 DDRD |= D_CLK;
144 170
145 _delay_us(250); 171 _delay_us(166);
146 172
147 PORTD &= ~D_DATA; 173 PORTD &= ~D_DATA;
148 DDRD |= D_DATA; 174 DDRD |= D_DATA;
149 175
150 _delay_us(25); 176 // _delay_us(3);
151 177
152 DDRD &= ~D_CLK; 178 DDRD &= ~D_CLK;
153 PORTD |= D_CLK; 179 PORTD |= D_CLK;
154 180
181 wait_CLK_samp;
182
155 /* data bits */ 183 /* data bits */
156 for (bit = 0; bit < 8; bit++) { 184 for (bit = 0; bit < 8; bit++) {
157 wait_CLK; 185 wait_CLK_set;
158 if (byte & 1) { 186 if (byte & 1) {
159 PORTD |= D_DATA; 187 PORTD |= D_DATA;
160 parity ^= 1; 188 parity ^= 1;
@@ -162,64 +190,95 @@ static uint8_t do_send_byte(uint8_t byte)
162 PORTD &= ~D_DATA; 190 PORTD &= ~D_DATA;
163 } 191 }
164 byte >>= 1; 192 byte >>= 1;
193 wait_CLK_samp;
165 } 194 }
195
196 timer_clear();
197
198 bit = 0x10;
166 /* parity */ 199 /* parity */
167 wait_CLK; 200 wait_CLK_set;
168 if (parity) 201 if (parity)
169 PORTD |= D_DATA; 202 PORTD |= D_DATA;
170 else 203 else
171 PORTD &= ~D_DATA; 204 PORTD &= ~D_DATA;
205 wait_CLK_samp;
172 206
207 bit = 0x11;
173 /* stop bit */ 208 /* stop bit */
174 wait_CLK; 209 wait_CLK_set;
175 PORTD |= D_DATA; 210 PORTD |= D_DATA;
211 wait_CLK_samp;
212 DDRD &= ~D_DATA;
176 213
214#if 0
215 bit = 0x12;
177 /* ACK from keyboard */ 216 /* ACK from keyboard */
178 wait_CLKhi; 217 wait_CLK_set;
179 DDRD &= ~D_DATA; 218 wait_CLK_samp;
219#endif
220
221 bit = 0x14;
222 while (PIND & D_DATA) { mayabort; }
223 bit = 0x15;
224 while (!(PIND & D_DATA)) { mayabort; }
180 225
181 wait_CLKlo;
182 wait_CLKhi; 226 wait_CLKhi;
183 while (!(PIND & D_DATA)) { __asm__ volatile ("nop\n"); mayabort; }
184 227
185 /* response from keyboard */ 228 /* response from keyboard */
186 229
230 timer_clear();
231 bit = 0x16;
187 usart_rxpoll(); 232 usart_rxpoll();
188 233
189 usarts = 0; 234 usarts = 0;
190 while (!(usarts & ((1 << RXC0) | (1 << UPE0) | (1 << FE0)))) { 235 while (!(usarts & ((1 << RXC0) | (1 << UPE0) | (1 << FE0)))) {
191 __asm__ volatile("nop\nnop\n"); 236 __asm__ volatile("nop\nnop\n");
192 usarts = UCSR0A; 237 usarts = UCSR0A;
193 mayabort; 238 if (TIFR0 & (1 << TOV0)) {
239 TIFR0 = (1 << TOV0);
240 if (++bit == 0x27)
241 return bit;
242 };
194 } 243 }
195 244
196 rv = UDR0; 245 rv = UDR0;
197 return rv; 246 return rv | 0x100;
198} 247}
199 248
200static uint8_t send_byte(uint8_t byte) 249static uint8_t send_byte(uint8_t byte)
201{ 250{
202 uint8_t rv, attempts; 251 uint16_t rv;
252 uint8_t attempts;
203 253
204 /* stop timer, use for ourselves to enforce 8 ms timeout */ 254 /* stop timer, use for ourselves to enforce 8 ms timeout */
205 TIMSK0 = 0; 255 TIMSK0 = 0;
206 256
207 for (attempts = 5; attempts; attempts--) { 257 for (attempts = 5; attempts; attempts--) {
208 TCNT0 = 0; 258 TCNT0 = 0;
209 TIFR0 |= (1 << TOV0); 259 __asm__ volatile("nop\n");
260 TIFR0 = (1 << TOV0);
210 261
211 if ((rv = do_send_byte(byte)) == 0xfa) { 262 rv = do_send_byte(byte);
263 if (rv == 0x1fa) {
212 dbg_wr(0x14); 264 dbg_wr(0x14);
213 dbg_wr(0x80 | (byte & 0x0f)); 265 dbg_wr(0x80 | (byte & 0x0f));
214 dbg_wr(0x80 | (byte >> 4)); 266 dbg_wr(0x80 | (byte >> 4));
215 dbg_wr(0x80 | attempts); 267 dbg_wr(0x80 | attempts);
216 goto out; 268 goto out;
217 } 269 }
218
219 /* clear state, wait, retry */ 270 /* clear state, wait, retry */
220 DDRD &= ~(D_DATA | D_CLK); 271 DDRD &= ~(D_DATA | D_CLK);
221 PORTD |= D_DATA | D_CLK; 272 PORTD |= D_DATA | D_CLK;
222 _delay_us(50); 273
274 if (rv == 0x1fe) {
275 dbg_wr(0xfe);
276 _delay_ms(33);
277 } else {
278 dbg_wr(0x08);
279 dbg_wr(0x80 | (rv & 0x7f));
280 dbg_wr(0x80 | (rv >> 7));
281 }
223 } 282 }
224 283
225 dbg_wr(0x01); 284 dbg_wr(0x01);
@@ -287,7 +346,9 @@ static uint8_t wait_byte(void)
287#define WAIT_IDLEBLINK 1 /* no full cycle */ 346#define WAIT_IDLEBLINK 1 /* no full cycle */
288#define CNTR_BLINK 6 347#define CNTR_BLINK 6
289 348
290#define WAIT_ENTRY 15 349#define WAIT_INPUT 5
350#define WAIT_ACCEPT 5
351#define WAIT_REJECT 10
291 352
292static uint8_t cntr = 0; 353static uint8_t cntr = 0;
293 354
@@ -353,11 +414,32 @@ static void state_enter(void)
353 nextstate = STATE_FAILURE; 414 nextstate = STATE_FAILURE;
354 if (send_byte(0xed) != 0xfa) 415 if (send_byte(0xed) != 0xfa)
355 break; 416 break;
356 if (send_byte(0x01) != 0xfa) 417 if (send_byte(KBLED_STATE) != 0xfa)
357 break; 418 break;
358 nextstate = STATE_NONE; 419 nextstate = STATE_NONE;
359 cntr = CNTR_BLINK; 420 cntr = CNTR_BLINK;
360 break; 421 break;
422 case STATE_INPUT:
423 statecntr = WAIT_INPUT;
424 if (send_byte(0xed) != 0xfa)
425 break;
426 if (send_byte(KBLED_STATE) != 0xfa)
427 break;
428 break;
429 case STATE_ACCEPT:
430 statecntr = WAIT_ACCEPT;
431 if (send_byte(0xed) != 0xfa)
432 break;
433 if (send_byte(KBLED_OK) != 0xfa)
434 break;
435 break;
436 case STATE_REJECT:
437 statecntr = WAIT_REJECT;
438 if (send_byte(0xed) != 0xfa)
439 break;
440 if (send_byte(KBLED_ERROR) != 0xfa)
441 break;
442 break;
361 } 443 }
362} 444}
363 445
@@ -378,7 +460,11 @@ static void state_timeout(void)
378 case STATE_IDLE: 460 case STATE_IDLE:
379 state = STATE_IDLEBLINK; 461 state = STATE_IDLEBLINK;
380 break; 462 break;
463 case STATE_INPUT:
464 memset(&code, 0, sizeof(code));
381 case STATE_IDLEBLINK: 465 case STATE_IDLEBLINK:
466 case STATE_ACCEPT:
467 case STATE_REJECT:
382 state = STATE_IDLE; 468 state = STATE_IDLE;
383 break; 469 break;
384 } 470 }
@@ -394,8 +480,7 @@ ISR(SIG_OVERFLOW0)
394 } 480 }
395} 481}
396 482
397static const char kbc_60[48] = { 483static const char kbc_60[24] = {
398 '_', '_', '_', '_', '_', '_', '_', '_', /* 60 - 67 */
399 '_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */ 484 '_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */
400 '0', '.', '2', '5', '6', '8', '_', '/', /* 70 - 77 */ 485 '0', '.', '2', '5', '6', '8', '_', '/', /* 70 - 77 */
401 '_', '_', '3', '_', '+', '9', '*', '_' /* 78 - 7f */ 486 '_', '_', '3', '_', '+', '9', '*', '_' /* 78 - 7f */
@@ -419,25 +504,25 @@ static void handle_keypress(uint8_t data)
419 * code: \0 a b c d 504 * code: \0 a b c d
420 */ 505 */
421 if (code[0] || memcmp(passwd, code + 1, sizeof(passwd) - 1)) { 506 if (code[0] || memcmp(passwd, code + 1, sizeof(passwd) - 1)) {
422
423 dbg_wr(0x20); 507 dbg_wr(0x20);
424 /* state = BLOCK; */ 508 nextstate = STATE_REJECT;
425 } else { 509 } else {
426 dbg_wr(lock ? 0x21 : 0x22); 510 dbg_wr(lock ? 0x21 : 0x22);
427 /* state = OPENING; */ 511 nextstate = STATE_ACCEPT;
428 } 512 }
429 memset(&code, 0, sizeof(code)); 513 memset(&code, 0, sizeof(code));
430 return; 514 return;
431 } 515 }
432 516
433 if (data >= 0x60 && data < 0x80) 517 if (data >= 0x68 && data < 0x80)
434 ascii = kbc_60[data - 0x60]; 518 ascii = kbc_60[data - 0x68];
435 519
436 for (c = 0; c < sizeof(code) - 1; c++) 520 for (c = 0; c < sizeof(code) - 1; c++)
437 code[c] = code[c + 1]; 521 code[c] = code[c + 1];
438 code[c] = ascii; 522 code[c] = ascii;
439 523
440 /* statecntr = WAIT_ENTRY; */ 524 statecntr = WAIT_INPUT;
525 nextstate = STATE_INPUT;
441 526
442#if 0 527#if 0
443 TCNT0 = 0; 528 TCNT0 = 0;
@@ -465,6 +550,7 @@ ISR(SIG_USART_RECV)
465 break; 550 break;
466 case STATE_IDLE: 551 case STATE_IDLE:
467 case STATE_IDLEBLINK: 552 case STATE_IDLEBLINK:
553 case STATE_INPUT:
468 if (data < 0x90) 554 if (data < 0x90)
469 handle_keypress(data); 555 handle_keypress(data);
470 default: 556 default:
@@ -481,7 +567,7 @@ int main()
481 * /122 = 1,0006 Hz = 1 s per CNTRTOP */ 567 * /122 = 1,0006 Hz = 1 s per CNTRTOP */
482 TCCR0A = 0; 568 TCCR0A = 0;
483 TIMSK0 = (1 << TOIE0); 569 TIMSK0 = (1 << TOIE0);
484 TCCR0B = (1 << CS02); 570 TCCR0B = (1 << CS02);
485 571
486 UCSR0C = (1 << UMSEL00) /* synch mode */ 572 UCSR0C = (1 << UMSEL00) /* synch mode */
487 | (1 << UPM01) | (1 << UPM00) /* odd parity */ 573 | (1 << UPM01) | (1 << UPM00) /* odd parity */
@@ -492,18 +578,18 @@ int main()
492 nextstate = STATE_NONE; 578 nextstate = STATE_NONE;
493 state_enter(); 579 state_enter();
494 580
581 for (int i = 0; i < 5000; i++) {
582 __asm__ volatile("nop\nnop\n");
583 }
584
495 sei(); 585 sei();
496 while (1) { 586 while (1) {
497 if (nextstate != STATE_NONE) { 587 if (nextstate != STATE_NONE) {
498 state = nextstate; 588 state = nextstate;
499 nextstate = STATE_NONE; 589 nextstate = STATE_NONE;
500 state_enter(); 590 state_enter();
501
502 dbg_wr(0x0e);
503 } else if (!statecntr) { 591 } else if (!statecntr) {
504 state_timeout(); 592 state_timeout();
505
506 dbg_wr(0x0e);
507 } 593 }
508 } 594 }
509} 595}