diff options
Diffstat (limited to 'kbc.c')
| -rw-r--r-- | kbc.c | 164 |
1 files changed, 100 insertions, 64 deletions
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <avr/io.h> | 4 | #include <avr/io.h> |
| 5 | #include <avr/interrupt.h> | 5 | #include <avr/interrupt.h> |
| 6 | #include <avr/sleep.h> | 6 | #include <avr/sleep.h> |
| 7 | #include <avr/pgmspace.h> | ||
| 7 | #include <util/delay.h> | 8 | #include <util/delay.h> |
| 8 | 9 | ||
| 9 | #ifndef PIN | 10 | #ifndef PIN |
| @@ -50,7 +51,10 @@ enum state { | |||
| 50 | STATE_IDLEBLINK, | 51 | STATE_IDLEBLINK, |
| 51 | STATE_INPUT, | 52 | STATE_INPUT, |
| 52 | STATE_ACCEPT, | 53 | STATE_ACCEPT, |
| 53 | STATE_REJECT | 54 | STATE_REJECT, |
| 55 | #ifdef KILLSWITCH | ||
| 56 | STATE_ERROR, | ||
| 57 | #endif | ||
| 54 | }; | 58 | }; |
| 55 | static volatile enum state state, nextstate; | 59 | static volatile enum state state, nextstate; |
| 56 | 60 | ||
| @@ -120,18 +124,7 @@ static void dbg_init(void) | |||
| 120 | static volatile uint8_t statecntr = 0; | 124 | static volatile uint8_t statecntr = 0; |
| 121 | 125 | ||
| 122 | #define mayabort if (TIFR0 & (1 << TOV0)) return bit; | 126 | #define mayabort if (TIFR0 & (1 << TOV0)) return bit; |
| 123 | #if 0 | ||
| 124 | #define _wait_CLK(cond) do { \ | ||
| 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; } | 127 | #define _wait_CLK(cond) while(cond) { mayabort; } |
| 134 | #endif | ||
| 135 | #define wait_CLKlo _wait_CLK( PIND /* & p0 & p1 & p2 */ & D_CLK) | 128 | #define wait_CLKlo _wait_CLK( PIND /* & p0 & p1 & p2 */ & D_CLK) |
| 136 | #define wait_CLKhi _wait_CLK(!(PIND /* & p0 & p1 & p2 */ & D_CLK)) | 129 | #define wait_CLKhi _wait_CLK(!(PIND /* & p0 & p1 & p2 */ & D_CLK)) |
| 137 | #define wait_CLK wait_CLKhi; wait_CLKlo; _delay_us(15) | 130 | #define wait_CLK wait_CLKhi; wait_CLKlo; _delay_us(15) |
| @@ -158,7 +151,6 @@ static void timer_clear(void) | |||
| 158 | static uint16_t do_send_byte(uint8_t byte) | 151 | static uint16_t do_send_byte(uint8_t byte) |
| 159 | { | 152 | { |
| 160 | uint8_t bit = 0, parity = 1, rv, usarts; | 153 | uint8_t bit = 0, parity = 1, rv, usarts; |
| 161 | uint8_t p2, p1, p0; | ||
| 162 | 154 | ||
| 163 | usart_dis(); | 155 | usart_dis(); |
| 164 | 156 | ||
| @@ -260,25 +252,15 @@ static uint8_t send_byte(uint8_t byte) | |||
| 260 | TIFR0 = (1 << TOV0); | 252 | TIFR0 = (1 << TOV0); |
| 261 | 253 | ||
| 262 | rv = do_send_byte(byte); | 254 | rv = do_send_byte(byte); |
| 263 | if (rv == 0x1fa) { | 255 | if (rv == 0x1fa) |
| 264 | dbg_wr(0x14); | ||
| 265 | dbg_wr(0x80 | (byte & 0x0f)); | ||
| 266 | dbg_wr(0x80 | (byte >> 4)); | ||
| 267 | dbg_wr(0x80 | attempts); | ||
| 268 | goto out; | 256 | goto out; |
| 269 | } | 257 | |
| 270 | /* clear state, wait, retry */ | 258 | /* clear state, wait, retry */ |
| 271 | DDRD &= ~(D_DATA | D_CLK); | 259 | DDRD &= ~(D_DATA | D_CLK); |
| 272 | PORTD |= D_DATA | D_CLK; | 260 | PORTD |= D_DATA | D_CLK; |
| 273 | 261 | ||
| 274 | if (rv == 0x1fe) { | 262 | if (rv == 0x1fe) |
| 275 | dbg_wr(0xfe); | ||
| 276 | _delay_ms(33); | 263 | _delay_ms(33); |
| 277 | } else { | ||
| 278 | dbg_wr(0x08); | ||
| 279 | dbg_wr(0x80 | (rv & 0x7f)); | ||
| 280 | dbg_wr(0x80 | (rv >> 7)); | ||
| 281 | } | ||
| 282 | } | 264 | } |
| 283 | 265 | ||
| 284 | dbg_wr(0x01); | 266 | dbg_wr(0x01); |
| @@ -309,7 +291,6 @@ static uint8_t wait_byte(void) | |||
| 309 | timer_return(); | 291 | timer_return(); |
| 310 | usart_rx(); | 292 | usart_rx(); |
| 311 | 293 | ||
| 312 | dbg_wr(0x02); | ||
| 313 | return 0; | 294 | return 0; |
| 314 | } | 295 | } |
| 315 | 296 | ||
| @@ -321,13 +302,6 @@ static uint8_t wait_byte(void) | |||
| 321 | timer_return(); | 302 | timer_return(); |
| 322 | usart_rx(); | 303 | usart_rx(); |
| 323 | 304 | ||
| 324 | dbg_wr(0x19); | ||
| 325 | dbg_wr(0x80 | (state)); | ||
| 326 | dbg_wr(0x80 | (usarts & 0x0f)); | ||
| 327 | dbg_wr(0x80 | (usarts >> 4)); | ||
| 328 | dbg_wr(0x80 | (data & 0x0f)); | ||
| 329 | dbg_wr(0x80 | (data >> 4)); | ||
| 330 | |||
| 331 | return data; | 305 | return data; |
| 332 | } | 306 | } |
| 333 | 307 | ||
| @@ -345,6 +319,7 @@ static uint8_t wait_byte(void) | |||
| 345 | 319 | ||
| 346 | #define WAIT_IDLEBLINK 1 /* no full cycle */ | 320 | #define WAIT_IDLEBLINK 1 /* no full cycle */ |
| 347 | #define CNTR_BLINK 6 | 321 | #define CNTR_BLINK 6 |
| 322 | #define CNTR_ERROR 61 | ||
| 348 | 323 | ||
| 349 | #define WAIT_INPUT 5 | 324 | #define WAIT_INPUT 5 |
| 350 | #define WAIT_ACCEPT 5 | 325 | #define WAIT_ACCEPT 5 |
| @@ -352,14 +327,15 @@ static uint8_t wait_byte(void) | |||
| 352 | 327 | ||
| 353 | static uint8_t cntr = 0; | 328 | static uint8_t cntr = 0; |
| 354 | 329 | ||
| 355 | static const char passwd[sizeof(PIN)] = PIN; | 330 | #ifdef KILLSWITCH |
| 331 | static uint8_t error; | ||
| 332 | #endif | ||
| 333 | |||
| 334 | static const char passwd[sizeof(PIN) - 1] = PIN; | ||
| 356 | static char code[sizeof(PIN)]; | 335 | static char code[sizeof(PIN)]; |
| 357 | 336 | ||
| 358 | static void state_enter(void) | 337 | static void state_enter(void) |
| 359 | { | 338 | { |
| 360 | dbg_wr(0x11); | ||
| 361 | dbg_wr(state); | ||
| 362 | |||
| 363 | switch (state) { | 339 | switch (state) { |
| 364 | case STATE_NONE: | 340 | case STATE_NONE: |
| 365 | case STATE_FAILURE: | 341 | case STATE_FAILURE: |
| @@ -390,6 +366,7 @@ static void state_enter(void) | |||
| 390 | break; | 366 | break; |
| 391 | if (wait_byte() != 0x83) | 367 | if (wait_byte() != 0x83) |
| 392 | break; | 368 | break; |
| 369 | #if 0 | ||
| 393 | /* scan code set 3 */ | 370 | /* scan code set 3 */ |
| 394 | if (send_byte(0xf0) != 0xfa) | 371 | if (send_byte(0xf0) != 0xfa) |
| 395 | break; | 372 | break; |
| @@ -398,6 +375,7 @@ static void state_enter(void) | |||
| 398 | /* make codes only */ | 375 | /* make codes only */ |
| 399 | if (send_byte(0xf9) != 0xfa) | 376 | if (send_byte(0xf9) != 0xfa) |
| 400 | break; | 377 | break; |
| 378 | #endif | ||
| 401 | nextstate = STATE_IDLE; | 379 | nextstate = STATE_IDLE; |
| 402 | break; | 380 | break; |
| 403 | case STATE_IDLE: | 381 | case STATE_IDLE: |
| @@ -440,6 +418,17 @@ static void state_enter(void) | |||
| 440 | if (send_byte(KBLED_ERROR) != 0xfa) | 418 | if (send_byte(KBLED_ERROR) != 0xfa) |
| 441 | break; | 419 | break; |
| 442 | break; | 420 | break; |
| 421 | #ifdef KILLSWITCH | ||
| 422 | case STATE_ERROR: | ||
| 423 | statecntr = 1; | ||
| 424 | cntr = CNTR_ERROR; | ||
| 425 | error ^= KBLED_ERROR; | ||
| 426 | if (send_byte(0xed) != 0xfa) | ||
| 427 | break; | ||
| 428 | if (send_byte(error) != 0xfa) | ||
| 429 | break; | ||
| 430 | break; | ||
| 431 | #endif | ||
| 443 | } | 432 | } |
| 444 | } | 433 | } |
| 445 | 434 | ||
| @@ -467,6 +456,11 @@ static void state_timeout(void) | |||
| 467 | case STATE_REJECT: | 456 | case STATE_REJECT: |
| 468 | state = STATE_IDLE; | 457 | state = STATE_IDLE; |
| 469 | break; | 458 | break; |
| 459 | #ifdef KILLSWITCH | ||
| 460 | case STATE_ERROR: | ||
| 461 | state = STATE_ERROR; | ||
| 462 | break; | ||
| 463 | #endif | ||
| 470 | } | 464 | } |
| 471 | state_enter(); | 465 | state_enter(); |
| 472 | } | 466 | } |
| @@ -480,15 +474,33 @@ ISR(SIG_OVERFLOW0) | |||
| 480 | } | 474 | } |
| 481 | } | 475 | } |
| 482 | 476 | ||
| 483 | static const char kbc_60[24] = { | 477 | #define ESC 0x1b |
| 478 | #define ENT 0x0d | ||
| 479 | |||
| 480 | #define KBC_BASE 0x16 | ||
| 481 | const PROGMEM char kbc[] = { | ||
| 482 | /* 0 1 2 3 4 5 6 7 | ||
| 483 | * 8 9 a b c d e f | ||
| 484 | */ | ||
| 485 | '1', '_', /* 10 - 17 */ | ||
| 486 | '_', '_', '_', '_', '_', '_', '2', '_', /* 18 - 1f */ | ||
| 487 | '_', '_', '_', '_', '_', '4', '3', '_', /* 20 - 27 */ | ||
| 488 | '_', '_', '_', '_', '_', '_', '5', '_', /* 28 - 2f */ | ||
| 489 | '_', '_', '_', '_', '_', '_', '6', '_', /* 30 - 37 */ | ||
| 490 | '_', '_', '_', '_', '_', '7', '8', '_', /* 38 - 3f */ | ||
| 491 | '_', '_', '_', '_', '_', '0', '9', '_', /* 40 - 47 */ | ||
| 492 | '_', '_', '_', '_', '_', '_', '_', '_', /* 48 - 4f */ | ||
| 493 | '_', '_', '_', '_', '_', '_', '_', '_', /* 50 - 57 */ | ||
| 494 | '_', '_', ENT, '_', '_', '_', '_', '_', /* 58 - 5f */ | ||
| 495 | '_', '_', '_', '_', '_', '_', '_', '_', /* 60 - 67 */ | ||
| 484 | '_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */ | 496 | '_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */ |
| 485 | '0', '.', '2', '5', '6', '8', '_', '/', /* 70 - 77 */ | 497 | '0', '_', '2', '5', '6', '8', ESC, ESC, /* 70 - 77 */ |
| 486 | '_', '_', '3', '_', '+', '9', '*', '_' /* 78 - 7f */ | 498 | '_', '_', '3', '_', '_', '9' /* 78 - 7f */ |
| 487 | }; | 499 | }; |
| 488 | #define KC_ESC 0x08 | 500 | |
| 489 | #define KC_ENTER 0x5a | 501 | #define NUMPAD_ENTER 0xda /* e0 5a */ |
| 490 | #define KC_NUM 0x76 | 502 | |
| 491 | #define KC_NP_ENTER 0x79 | 503 | static uint8_t pressed = 0, e0 = 0, release = 0; |
| 492 | 504 | ||
| 493 | static void handle_keypress(uint8_t data) | 505 | static void handle_keypress(uint8_t data) |
| 494 | { | 506 | { |
| @@ -496,14 +508,52 @@ static void handle_keypress(uint8_t data) | |||
| 496 | uint8_t ascii = '_'; | 508 | uint8_t ascii = '_'; |
| 497 | uint8_t c; | 509 | uint8_t c; |
| 498 | 510 | ||
| 499 | lock = data == KC_ESC || data == KC_NUM; | 511 | if (release) { |
| 500 | unlock = data == KC_ENTER || data == KC_NP_ENTER; | 512 | pressed = 0; |
| 513 | release = 0; | ||
| 514 | return; | ||
| 515 | } | ||
| 516 | if (data == pressed) | ||
| 517 | return; | ||
| 518 | |||
| 519 | if (data == 0xe0) { | ||
| 520 | e0 = 0x80; | ||
| 521 | return; | ||
| 522 | } | ||
| 523 | if (data == 0xf0) { | ||
| 524 | release = 1; | ||
| 525 | return; | ||
| 526 | } | ||
| 527 | if (data >= 0x80) | ||
| 528 | return; | ||
| 529 | |||
| 530 | pressed = data; | ||
| 531 | |||
| 532 | data |= e0; | ||
| 533 | e0 = 0; | ||
| 534 | |||
| 535 | if (data >= KBC_BASE && data < KBC_BASE + sizeof(kbc)) | ||
| 536 | ascii = pgm_read_byte(kbc + data - KBC_BASE); | ||
| 537 | |||
| 538 | dbg_wr(0x03); | ||
| 539 | dbg_wr(0x80 | (ascii & 0xf)); | ||
| 540 | dbg_wr(0x80 | (ascii >> 4)); | ||
| 541 | |||
| 542 | lock = ascii == ESC; | ||
| 543 | unlock = ascii == ENT || data == NUMPAD_ENTER; | ||
| 501 | 544 | ||
| 502 | if (lock || unlock) { | 545 | if (lock || unlock) { |
| 503 | /* passwd: a b c d \0 | 546 | /* passwd: a b c d |
| 504 | * code: \0 a b c d | 547 | * code: \0 a b c d |
| 505 | */ | 548 | */ |
| 506 | if (code[0] || memcmp(passwd, code + 1, sizeof(passwd) - 1)) { | 549 | #ifdef KILLSWITCH |
| 550 | if (code[0] || !memcmp("9164", code + 1, 4)) { | ||
| 551 | error = 0; | ||
| 552 | nextstate = STATE_ERROR; | ||
| 553 | return; | ||
| 554 | } | ||
| 555 | #endif | ||
| 556 | if (code[0] || memcmp(passwd, code + 1, sizeof(passwd))) { | ||
| 507 | dbg_wr(0x20); | 557 | dbg_wr(0x20); |
| 508 | nextstate = STATE_REJECT; | 558 | nextstate = STATE_REJECT; |
| 509 | } else { | 559 | } else { |
| @@ -514,25 +564,12 @@ static void handle_keypress(uint8_t data) | |||
| 514 | return; | 564 | return; |
| 515 | } | 565 | } |
| 516 | 566 | ||
| 517 | if (data >= 0x68 && data < 0x80) | ||
| 518 | ascii = kbc_60[data - 0x68]; | ||
| 519 | |||
| 520 | for (c = 0; c < sizeof(code) - 1; c++) | 567 | for (c = 0; c < sizeof(code) - 1; c++) |
| 521 | code[c] = code[c + 1]; | 568 | code[c] = code[c + 1]; |
| 522 | code[c] = ascii; | 569 | code[c] = ascii; |
| 523 | 570 | ||
| 524 | statecntr = WAIT_INPUT; | 571 | statecntr = WAIT_INPUT; |
| 525 | nextstate = STATE_INPUT; | 572 | nextstate = STATE_INPUT; |
| 526 | |||
| 527 | #if 0 | ||
| 528 | TCNT0 = 0; | ||
| 529 | state = 1; | ||
| 530 | send_byte(0xed); | ||
| 531 | send_byte(0x00); | ||
| 532 | DDRD = DDRD_BEEP; | ||
| 533 | cntr = 0; | ||
| 534 | TIFR0 = (1 << TOV0); | ||
| 535 | #endif | ||
| 536 | } | 573 | } |
| 537 | 574 | ||
| 538 | ISR(SIG_USART_RECV) | 575 | ISR(SIG_USART_RECV) |
| @@ -551,8 +588,7 @@ ISR(SIG_USART_RECV) | |||
| 551 | case STATE_IDLE: | 588 | case STATE_IDLE: |
| 552 | case STATE_IDLEBLINK: | 589 | case STATE_IDLEBLINK: |
| 553 | case STATE_INPUT: | 590 | case STATE_INPUT: |
| 554 | if (data < 0x90) | 591 | handle_keypress(data); |
| 555 | handle_keypress(data); | ||
| 556 | default: | 592 | default: |
| 557 | break; | 593 | break; |
| 558 | } | 594 | } |
