diff options
| author | David Lamparter <equinox@diac24.net> | 2012-01-15 19:42:35 +0100 |
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2012-01-15 19:42:35 +0100 |
| commit | 79c414c4cfebf56edff8fdc4e4b234bbe0d623e5 (patch) | |
| tree | 58ca05a0914558e72fc49790534df79528275ad9 | |
| parent | 73d3b9faf1d0ac88c52f4c7c2853da8d870f2581 (diff) | |
metal sensor feedback + proper timeout handling
| -rw-r--r-- | kbc.c | 128 |
1 files changed, 81 insertions, 47 deletions
| @@ -16,8 +16,8 @@ | |||
| 16 | * 0 | 16 | * 0 |
| 17 | * 1 BEEP (OC1A) | 17 | * 1 BEEP (OC1A) |
| 18 | * 2 SS up:8 | 18 | * 2 SS up:8 |
| 19 | * 3 MOSI up:2 | 19 | * 3 MOSI up:2 LOCK |
| 20 | * 4 MISO up:4 | 20 | * 4 MISO up:4 UNLOCK |
| 21 | * 5 SCK up:7 | 21 | * 5 SCK up:7 |
| 22 | * port C | 22 | * port C |
| 23 | * 0-3 | 23 | * 0-3 |
| @@ -38,10 +38,14 @@ | |||
| 38 | #define D_PWR (1 << 5) | 38 | #define D_PWR (1 << 5) |
| 39 | 39 | ||
| 40 | #define B_BEEP (1 << 1) | 40 | #define B_BEEP (1 << 1) |
| 41 | #define B_OPEN 0 | 41 | #define B_FEEDBACK (1 << 2) |
| 42 | #define B_CLOSE 0 | 42 | #define B_CLOSE (1 << 3) |
| 43 | #define B_OPEN (1 << 4) | ||
| 44 | |||
| 43 | #define B_MISO (1 << 4) | 45 | #define B_MISO (1 << 4) |
| 44 | 46 | ||
| 47 | #define MAXTRIES 3 | ||
| 48 | |||
| 45 | enum state { | 49 | enum state { |
| 46 | STATE_NONE = 0, | 50 | STATE_NONE = 0, |
| 47 | STATE_FAILURE, | 51 | STATE_FAILURE, |
| @@ -53,11 +57,13 @@ enum state { | |||
| 53 | STATE_INPUT, | 57 | STATE_INPUT, |
| 54 | STATE_ACCEPT, | 58 | STATE_ACCEPT, |
| 55 | STATE_REJECT, | 59 | STATE_REJECT, |
| 60 | STATE_KEYMATIC_RECHECK, | ||
| 61 | STATE_KEYMATIC_RECLOSE, | ||
| 56 | #ifdef KILLSWITCH | 62 | #ifdef KILLSWITCH |
| 57 | STATE_ERROR, | 63 | STATE_ERROR, |
| 58 | #endif | 64 | #endif |
| 59 | }; | 65 | }; |
| 60 | static volatile enum state state, nextstate; | 66 | static volatile enum state state, nextstate, toutstate; |
| 61 | 67 | ||
| 62 | static void power_up() | 68 | static void power_up() |
| 63 | { | 69 | { |
| @@ -326,13 +332,19 @@ static uint8_t wait_byte(void) | |||
| 326 | #define WAIT_IDLEBLINK 1 /* no full cycle */ | 332 | #define WAIT_IDLEBLINK 1 /* no full cycle */ |
| 327 | #define CNTR_BLINK 6 | 333 | #define CNTR_BLINK 6 |
| 328 | #define CNTR_ERROR 61 | 334 | #define CNTR_ERROR 61 |
| 335 | #define CNTR_BEEP 10 | ||
| 336 | #define CNTR_BEEP_REJ 92 | ||
| 329 | 337 | ||
| 330 | #define WAIT_INPUT 5 | 338 | #define WAIT_INPUT 6 |
| 331 | #define WAIT_ACCEPT 5 | 339 | #define WAIT_ACCEPT 8 |
| 332 | #define WAIT_REJECT 10 | 340 | #define WAIT_REJECT 8 |
| 341 | #define WAIT_KEYMATIC_RETRY 9 | ||
| 333 | 342 | ||
| 334 | static uint8_t cntr = 0; | 343 | #define CNTR_KEYMATIC 30 |
| 344 | /* CNTR_BEEP_ACC == CNTR_KEYMATIC */ | ||
| 335 | 345 | ||
| 346 | static uint8_t cntr = 0; | ||
| 347 | static uint8_t close_try = 0; | ||
| 336 | #ifdef KILLSWITCH | 348 | #ifdef KILLSWITCH |
| 337 | static uint8_t error; | 349 | static uint8_t error; |
| 338 | #endif | 350 | #endif |
| @@ -345,21 +357,25 @@ static void state_enter(void) | |||
| 345 | switch (state) { | 357 | switch (state) { |
| 346 | case STATE_NONE: | 358 | case STATE_NONE: |
| 347 | case STATE_FAILURE: | 359 | case STATE_FAILURE: |
| 360 | toutstate = STATE_POWERUP; | ||
| 348 | statecntr = WAIT_FAIL; | 361 | statecntr = WAIT_FAIL; |
| 349 | usart_dis(); | 362 | usart_dis(); |
| 350 | power_down(); | 363 | power_down(); |
| 351 | break; | 364 | break; |
| 352 | case STATE_POWERUP: | 365 | case STATE_POWERUP: |
| 366 | toutstate = STATE_INITRESET; | ||
| 353 | statecntr = WAIT_POWERUP; | 367 | statecntr = WAIT_POWERUP; |
| 354 | power_up(); | 368 | power_up(); |
| 355 | usart_rx(); | 369 | usart_rx(); |
| 356 | break; | 370 | break; |
| 357 | case STATE_INITRESET: | 371 | case STATE_INITRESET: |
| 372 | toutstate = STATE_FAILURE; | ||
| 358 | statecntr = WAIT_INIT; | 373 | statecntr = WAIT_INIT; |
| 359 | send_byte(0xff); | 374 | send_byte(0xff); |
| 360 | break; | 375 | break; |
| 361 | case STATE_CONFIG: | 376 | case STATE_CONFIG: |
| 362 | /* statecntr not used */ | 377 | /* statecntr not used */ |
| 378 | toutstate = STATE_FAILURE; | ||
| 363 | nextstate = STATE_FAILURE; | 379 | nextstate = STATE_FAILURE; |
| 364 | if (send_byte(0xed) != 0xfa) | 380 | if (send_byte(0xed) != 0xfa) |
| 365 | break; | 381 | break; |
| @@ -385,6 +401,8 @@ static void state_enter(void) | |||
| 385 | nextstate = STATE_IDLE; | 401 | nextstate = STATE_IDLE; |
| 386 | break; | 402 | break; |
| 387 | case STATE_IDLE: | 403 | case STATE_IDLE: |
| 404 | memset(&code, 0, sizeof(code)); | ||
| 405 | toutstate = STATE_IDLEBLINK; | ||
| 388 | statecntr = WAIT_IDLE; | 406 | statecntr = WAIT_IDLE; |
| 389 | nextstate = STATE_FAILURE; | 407 | nextstate = STATE_FAILURE; |
| 390 | if (send_byte(0xed) != 0xfa) | 408 | if (send_byte(0xed) != 0xfa) |
| @@ -394,6 +412,7 @@ static void state_enter(void) | |||
| 394 | nextstate = STATE_NONE; | 412 | nextstate = STATE_NONE; |
| 395 | break; | 413 | break; |
| 396 | case STATE_IDLEBLINK: | 414 | case STATE_IDLEBLINK: |
| 415 | toutstate = STATE_IDLE; | ||
| 397 | statecntr = WAIT_IDLEBLINK; | 416 | statecntr = WAIT_IDLEBLINK; |
| 398 | nextstate = STATE_FAILURE; | 417 | nextstate = STATE_FAILURE; |
| 399 | if (send_byte(0xed) != 0xfa) | 418 | if (send_byte(0xed) != 0xfa) |
| @@ -404,6 +423,7 @@ static void state_enter(void) | |||
| 404 | cntr = CNTR_BLINK; | 423 | cntr = CNTR_BLINK; |
| 405 | break; | 424 | break; |
| 406 | case STATE_INPUT: | 425 | case STATE_INPUT: |
| 426 | toutstate = STATE_IDLE; | ||
| 407 | statecntr = WAIT_INPUT; | 427 | statecntr = WAIT_INPUT; |
| 408 | if (send_byte(0xed) != 0xfa) | 428 | if (send_byte(0xed) != 0xfa) |
| 409 | break; | 429 | break; |
| @@ -411,6 +431,7 @@ static void state_enter(void) | |||
| 411 | break; | 431 | break; |
| 412 | break; | 432 | break; |
| 413 | case STATE_ACCEPT: | 433 | case STATE_ACCEPT: |
| 434 | toutstate = close_try ? STATE_KEYMATIC_RECHECK : STATE_IDLE; | ||
| 414 | statecntr = WAIT_ACCEPT; | 435 | statecntr = WAIT_ACCEPT; |
| 415 | if (send_byte(0xed) != 0xfa) | 436 | if (send_byte(0xed) != 0xfa) |
| 416 | break; | 437 | break; |
| @@ -418,14 +439,42 @@ static void state_enter(void) | |||
| 418 | break; | 439 | break; |
| 419 | break; | 440 | break; |
| 420 | case STATE_REJECT: | 441 | case STATE_REJECT: |
| 442 | toutstate = STATE_IDLE; | ||
| 421 | statecntr = WAIT_REJECT; | 443 | statecntr = WAIT_REJECT; |
| 422 | if (send_byte(0xed) != 0xfa) | 444 | if (send_byte(0xed) != 0xfa) |
| 423 | break; | 445 | break; |
| 424 | if (send_byte(KBLED_ERROR) != 0xfa) | 446 | if (send_byte(KBLED_ERROR) != 0xfa) |
| 425 | break; | 447 | break; |
| 426 | break; | 448 | break; |
| 449 | case STATE_KEYMATIC_RECHECK: | ||
| 450 | if (!close_try || !(PINB & B_FEEDBACK)) { | ||
| 451 | close_try = 0; | ||
| 452 | nextstate = STATE_IDLE; | ||
| 453 | return; | ||
| 454 | } | ||
| 455 | if (send_byte(0xed) != 0xfa) | ||
| 456 | break; | ||
| 457 | if (send_byte(KBLED_OK | KBLED_ERROR) != 0xfa) | ||
| 458 | break; | ||
| 459 | |||
| 460 | close_try--; | ||
| 461 | |||
| 462 | cntr = CNTR_KEYMATIC; | ||
| 463 | statecntr = WAIT_KEYMATIC_RETRY; | ||
| 464 | toutstate = STATE_KEYMATIC_RECLOSE; | ||
| 465 | |||
| 466 | PORTB &= ~(B_OPEN | B_BEEP); | ||
| 467 | break; | ||
| 468 | case STATE_KEYMATIC_RECLOSE: | ||
| 469 | cntr = CNTR_KEYMATIC; | ||
| 470 | statecntr = WAIT_KEYMATIC_RETRY; | ||
| 471 | toutstate = STATE_KEYMATIC_RECHECK; | ||
| 472 | |||
| 473 | PORTB &= ~(B_CLOSE | B_BEEP); | ||
| 474 | break; | ||
| 427 | #ifdef KILLSWITCH | 475 | #ifdef KILLSWITCH |
| 428 | case STATE_ERROR: | 476 | case STATE_ERROR: |
| 477 | toutstate = STATE_ERROR; | ||
| 429 | statecntr = 1; | 478 | statecntr = 1; |
| 430 | cntr = CNTR_ERROR; | 479 | cntr = CNTR_ERROR; |
| 431 | error ^= KBLED_ERROR; | 480 | error ^= KBLED_ERROR; |
| @@ -438,43 +487,13 @@ static void state_enter(void) | |||
| 438 | } | 487 | } |
| 439 | } | 488 | } |
| 440 | 489 | ||
| 441 | static void state_timeout(void) | ||
| 442 | { | ||
| 443 | switch (state) { | ||
| 444 | case STATE_NONE: | ||
| 445 | case STATE_FAILURE: | ||
| 446 | state = STATE_POWERUP; | ||
| 447 | break; | ||
| 448 | case STATE_POWERUP: | ||
| 449 | state = STATE_INITRESET; | ||
| 450 | break; | ||
| 451 | case STATE_INITRESET: | ||
| 452 | case STATE_CONFIG: | ||
| 453 | state = STATE_FAILURE; | ||
| 454 | break; | ||
| 455 | case STATE_IDLE: | ||
| 456 | state = STATE_IDLEBLINK; | ||
| 457 | break; | ||
| 458 | case STATE_INPUT: | ||
| 459 | memset(&code, 0, sizeof(code)); | ||
| 460 | case STATE_IDLEBLINK: | ||
| 461 | case STATE_ACCEPT: | ||
| 462 | case STATE_REJECT: | ||
| 463 | state = STATE_IDLE; | ||
| 464 | break; | ||
| 465 | #ifdef KILLSWITCH | ||
| 466 | case STATE_ERROR: | ||
| 467 | state = STATE_ERROR; | ||
| 468 | break; | ||
| 469 | #endif | ||
| 470 | } | ||
| 471 | state_enter(); | ||
| 472 | } | ||
| 473 | |||
| 474 | ISR(SIG_OVERFLOW0) | 490 | ISR(SIG_OVERFLOW0) |
| 475 | { | 491 | { |
| 476 | if (!--cntr) { | 492 | if (!--cntr) { |
| 477 | cntr = CNTRTOP; | 493 | cntr = CNTRTOP; |
| 494 | |||
| 495 | PORTB = B_OPEN | B_CLOSE | B_BEEP; | ||
| 496 | |||
| 478 | if (statecntr) | 497 | if (statecntr) |
| 479 | statecntr--; | 498 | statecntr--; |
| 480 | } | 499 | } |
| @@ -549,7 +568,7 @@ static void handle_keypress(uint8_t data) | |||
| 549 | unlock = ascii == ENT || data == NUMPAD_ENTER; | 568 | unlock = ascii == ENT || data == NUMPAD_ENTER; |
| 550 | 569 | ||
| 551 | if (lock || unlock) { | 570 | if (lock || unlock) { |
| 552 | uint8_t eebyte, pos, ok = 1; | 571 | uint8_t pos, ok = 1; |
| 553 | 572 | ||
| 554 | /* passwd: a b c d | 573 | /* passwd: a b c d |
| 555 | * code: \0 a b c d | 574 | * code: \0 a b c d |
| @@ -569,10 +588,19 @@ static void handle_keypress(uint8_t data) | |||
| 569 | ok = 0; | 588 | ok = 0; |
| 570 | 589 | ||
| 571 | if (!ok) { | 590 | if (!ok) { |
| 572 | dbg_wr(0x20); | 591 | PORTB &= ~B_BEEP; |
| 592 | |||
| 593 | cntr = CNTR_BEEP_REJ; | ||
| 573 | nextstate = STATE_REJECT; | 594 | nextstate = STATE_REJECT; |
| 574 | } else { | 595 | } else { |
| 575 | dbg_wr(lock ? 0x21 : 0x22); | 596 | if (lock) { |
| 597 | PORTB &= ~(B_CLOSE | B_BEEP); | ||
| 598 | close_try = MAXTRIES; | ||
| 599 | } else { | ||
| 600 | PORTB &= ~(B_OPEN | B_BEEP); | ||
| 601 | } | ||
| 602 | |||
| 603 | cntr = CNTR_KEYMATIC; | ||
| 576 | nextstate = STATE_ACCEPT; | 604 | nextstate = STATE_ACCEPT; |
| 577 | } | 605 | } |
| 578 | memset(&code, 0, sizeof(code)); | 606 | memset(&code, 0, sizeof(code)); |
| @@ -583,7 +611,8 @@ static void handle_keypress(uint8_t data) | |||
| 583 | code[c] = code[c + 1]; | 611 | code[c] = code[c + 1]; |
| 584 | code[c] = ascii; | 612 | code[c] = ascii; |
| 585 | 613 | ||
| 586 | statecntr = WAIT_INPUT; | 614 | PORTB &= ~B_BEEP; |
| 615 | cntr = CNTR_BEEP; | ||
| 587 | nextstate = STATE_INPUT; | 616 | nextstate = STATE_INPUT; |
| 588 | } | 617 | } |
| 589 | 618 | ||
| @@ -613,6 +642,9 @@ int main() | |||
| 613 | { | 642 | { |
| 614 | dbg_init(); | 643 | dbg_init(); |
| 615 | 644 | ||
| 645 | PORTB = B_OPEN | B_CLOSE | B_BEEP; | ||
| 646 | DDRB = B_OPEN | B_CLOSE | B_BEEP; | ||
| 647 | |||
| 616 | /* /256 = 31'250 Hz = 32 µs per 1 unit | 648 | /* /256 = 31'250 Hz = 32 µs per 1 unit |
| 617 | * /256 = 122 Hz = 8'192 µs per for overflow | 649 | * /256 = 122 Hz = 8'192 µs per for overflow |
| 618 | * /122 = 1,0006 Hz = 1 s per CNTRTOP */ | 650 | * /122 = 1,0006 Hz = 1 s per CNTRTOP */ |
| @@ -640,7 +672,9 @@ int main() | |||
| 640 | nextstate = STATE_NONE; | 672 | nextstate = STATE_NONE; |
| 641 | state_enter(); | 673 | state_enter(); |
| 642 | } else if (!statecntr) { | 674 | } else if (!statecntr) { |
| 643 | state_timeout(); | 675 | state = toutstate; |
| 676 | nextstate = STATE_NONE; | ||
| 677 | state_enter(); | ||
| 644 | } | 678 | } |
| 645 | } | 679 | } |
| 646 | } | 680 | } |
