From 79c414c4cfebf56edff8fdc4e4b234bbe0d623e5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 15 Jan 2012 19:42:35 +0100 Subject: metal sensor feedback + proper timeout handling --- kbc.c | 128 ++++++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 81 insertions(+), 47 deletions(-) diff --git a/kbc.c b/kbc.c index 3568eda..45e3308 100644 --- a/kbc.c +++ b/kbc.c @@ -16,8 +16,8 @@ * 0 * 1 BEEP (OC1A) * 2 SS up:8 - * 3 MOSI up:2 - * 4 MISO up:4 + * 3 MOSI up:2 LOCK + * 4 MISO up:4 UNLOCK * 5 SCK up:7 * port C * 0-3 @@ -38,10 +38,14 @@ #define D_PWR (1 << 5) #define B_BEEP (1 << 1) -#define B_OPEN 0 -#define B_CLOSE 0 +#define B_FEEDBACK (1 << 2) +#define B_CLOSE (1 << 3) +#define B_OPEN (1 << 4) + #define B_MISO (1 << 4) +#define MAXTRIES 3 + enum state { STATE_NONE = 0, STATE_FAILURE, @@ -53,11 +57,13 @@ enum state { STATE_INPUT, STATE_ACCEPT, STATE_REJECT, + STATE_KEYMATIC_RECHECK, + STATE_KEYMATIC_RECLOSE, #ifdef KILLSWITCH STATE_ERROR, #endif }; -static volatile enum state state, nextstate; +static volatile enum state state, nextstate, toutstate; static void power_up() { @@ -326,13 +332,19 @@ static uint8_t wait_byte(void) #define WAIT_IDLEBLINK 1 /* no full cycle */ #define CNTR_BLINK 6 #define CNTR_ERROR 61 +#define CNTR_BEEP 10 +#define CNTR_BEEP_REJ 92 -#define WAIT_INPUT 5 -#define WAIT_ACCEPT 5 -#define WAIT_REJECT 10 +#define WAIT_INPUT 6 +#define WAIT_ACCEPT 8 +#define WAIT_REJECT 8 +#define WAIT_KEYMATIC_RETRY 9 -static uint8_t cntr = 0; +#define CNTR_KEYMATIC 30 +/* CNTR_BEEP_ACC == CNTR_KEYMATIC */ +static uint8_t cntr = 0; +static uint8_t close_try = 0; #ifdef KILLSWITCH static uint8_t error; #endif @@ -345,21 +357,25 @@ static void state_enter(void) switch (state) { case STATE_NONE: case STATE_FAILURE: + toutstate = STATE_POWERUP; statecntr = WAIT_FAIL; usart_dis(); power_down(); break; case STATE_POWERUP: + toutstate = STATE_INITRESET; statecntr = WAIT_POWERUP; power_up(); usart_rx(); break; case STATE_INITRESET: + toutstate = STATE_FAILURE; statecntr = WAIT_INIT; send_byte(0xff); break; case STATE_CONFIG: /* statecntr not used */ + toutstate = STATE_FAILURE; nextstate = STATE_FAILURE; if (send_byte(0xed) != 0xfa) break; @@ -385,6 +401,8 @@ static void state_enter(void) nextstate = STATE_IDLE; break; case STATE_IDLE: + memset(&code, 0, sizeof(code)); + toutstate = STATE_IDLEBLINK; statecntr = WAIT_IDLE; nextstate = STATE_FAILURE; if (send_byte(0xed) != 0xfa) @@ -394,6 +412,7 @@ static void state_enter(void) nextstate = STATE_NONE; break; case STATE_IDLEBLINK: + toutstate = STATE_IDLE; statecntr = WAIT_IDLEBLINK; nextstate = STATE_FAILURE; if (send_byte(0xed) != 0xfa) @@ -404,6 +423,7 @@ static void state_enter(void) cntr = CNTR_BLINK; break; case STATE_INPUT: + toutstate = STATE_IDLE; statecntr = WAIT_INPUT; if (send_byte(0xed) != 0xfa) break; @@ -411,6 +431,7 @@ static void state_enter(void) break; break; case STATE_ACCEPT: + toutstate = close_try ? STATE_KEYMATIC_RECHECK : STATE_IDLE; statecntr = WAIT_ACCEPT; if (send_byte(0xed) != 0xfa) break; @@ -418,14 +439,42 @@ static void state_enter(void) break; break; case STATE_REJECT: + toutstate = STATE_IDLE; statecntr = WAIT_REJECT; if (send_byte(0xed) != 0xfa) break; if (send_byte(KBLED_ERROR) != 0xfa) break; break; + case STATE_KEYMATIC_RECHECK: + if (!close_try || !(PINB & B_FEEDBACK)) { + close_try = 0; + nextstate = STATE_IDLE; + return; + } + if (send_byte(0xed) != 0xfa) + break; + if (send_byte(KBLED_OK | KBLED_ERROR) != 0xfa) + break; + + close_try--; + + cntr = CNTR_KEYMATIC; + statecntr = WAIT_KEYMATIC_RETRY; + toutstate = STATE_KEYMATIC_RECLOSE; + + PORTB &= ~(B_OPEN | B_BEEP); + break; + case STATE_KEYMATIC_RECLOSE: + cntr = CNTR_KEYMATIC; + statecntr = WAIT_KEYMATIC_RETRY; + toutstate = STATE_KEYMATIC_RECHECK; + + PORTB &= ~(B_CLOSE | B_BEEP); + break; #ifdef KILLSWITCH case STATE_ERROR: + toutstate = STATE_ERROR; statecntr = 1; cntr = CNTR_ERROR; error ^= KBLED_ERROR; @@ -438,43 +487,13 @@ static void state_enter(void) } } -static void state_timeout(void) -{ - switch (state) { - case STATE_NONE: - case STATE_FAILURE: - state = STATE_POWERUP; - break; - case STATE_POWERUP: - state = STATE_INITRESET; - break; - case STATE_INITRESET: - case STATE_CONFIG: - state = STATE_FAILURE; - break; - case STATE_IDLE: - state = STATE_IDLEBLINK; - break; - case STATE_INPUT: - memset(&code, 0, sizeof(code)); - case STATE_IDLEBLINK: - case STATE_ACCEPT: - case STATE_REJECT: - state = STATE_IDLE; - break; -#ifdef KILLSWITCH - case STATE_ERROR: - state = STATE_ERROR; - break; -#endif - } - state_enter(); -} - ISR(SIG_OVERFLOW0) { if (!--cntr) { cntr = CNTRTOP; + + PORTB = B_OPEN | B_CLOSE | B_BEEP; + if (statecntr) statecntr--; } @@ -549,7 +568,7 @@ static void handle_keypress(uint8_t data) unlock = ascii == ENT || data == NUMPAD_ENTER; if (lock || unlock) { - uint8_t eebyte, pos, ok = 1; + uint8_t pos, ok = 1; /* passwd: a b c d * code: \0 a b c d @@ -569,10 +588,19 @@ static void handle_keypress(uint8_t data) ok = 0; if (!ok) { - dbg_wr(0x20); + PORTB &= ~B_BEEP; + + cntr = CNTR_BEEP_REJ; nextstate = STATE_REJECT; } else { - dbg_wr(lock ? 0x21 : 0x22); + if (lock) { + PORTB &= ~(B_CLOSE | B_BEEP); + close_try = MAXTRIES; + } else { + PORTB &= ~(B_OPEN | B_BEEP); + } + + cntr = CNTR_KEYMATIC; nextstate = STATE_ACCEPT; } memset(&code, 0, sizeof(code)); @@ -583,7 +611,8 @@ static void handle_keypress(uint8_t data) code[c] = code[c + 1]; code[c] = ascii; - statecntr = WAIT_INPUT; + PORTB &= ~B_BEEP; + cntr = CNTR_BEEP; nextstate = STATE_INPUT; } @@ -613,6 +642,9 @@ int main() { dbg_init(); + PORTB = B_OPEN | B_CLOSE | B_BEEP; + DDRB = B_OPEN | B_CLOSE | B_BEEP; + /* /256 = 31'250 Hz = 32 µs per 1 unit * /256 = 122 Hz = 8'192 µs per for overflow * /122 = 1,0006 Hz = 1 s per CNTRTOP */ @@ -640,7 +672,9 @@ int main() nextstate = STATE_NONE; state_enter(); } else if (!statecntr) { - state_timeout(); + state = toutstate; + nextstate = STATE_NONE; + state_enter(); } } } -- cgit v1.2.1