diff options
| -rw-r--r-- | kbc.c | 128 |
1 files changed, 81 insertions, 47 deletions
@@ -13,14 +13,14 @@ #endif /* port B RJ45 * 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 * 4 (SDA) * 5 (SCL) * port D @@ -35,32 +35,38 @@ #define D_DATA (1 << 0) #define D_CLK (1 << 4) #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, STATE_POWERUP, STATE_INITRESET, STATE_CONFIG, STATE_IDLE, STATE_IDLEBLINK, 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() { DDRD = D_PWR; PORTD = D_DATA | D_CLK; } @@ -323,46 +329,56 @@ static uint8_t wait_byte(void) #define WAIT_INIT 3 #define WAIT_IDLE 3 #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 static const EEMEM uint8_t passwd[sizeof(PIN) - 1] = PIN; static uint8_t code[sizeof(PIN)]; 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; if (send_byte(0x00) != 0xfa) break; /* identify */ @@ -382,102 +398,105 @@ static void state_enter(void) if (send_byte(0xf9) != 0xfa) break; #endif 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) break; if (send_byte(0x00) != 0xfa) break; nextstate = STATE_NONE; break; case STATE_IDLEBLINK: + toutstate = STATE_IDLE; statecntr = WAIT_IDLEBLINK; nextstate = STATE_FAILURE; if (send_byte(0xed) != 0xfa) break; if (send_byte(KBLED_STATE) != 0xfa) break; nextstate = STATE_NONE; cntr = CNTR_BLINK; break; case STATE_INPUT: + toutstate = STATE_IDLE; statecntr = WAIT_INPUT; if (send_byte(0xed) != 0xfa) break; if (send_byte(KBLED_STATE) != 0xfa) break; break; case STATE_ACCEPT: + toutstate = close_try ? STATE_KEYMATIC_RECHECK : STATE_IDLE; statecntr = WAIT_ACCEPT; if (send_byte(0xed) != 0xfa) break; if (send_byte(KBLED_OK) != 0xfa) 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; if (send_byte(0xed) != 0xfa) break; if (send_byte(error) != 0xfa) break; break; #endif } } -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--; } } #define ESC 0x1b @@ -546,13 +565,13 @@ static void handle_keypress(uint8_t data) dbg_wr(0x80 | (ascii >> 4)); lock = ascii == ESC; 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 */ if (code[0]) @@ -566,27 +585,37 @@ static void handle_keypress(uint8_t data) #endif for (pos = 1; pos < sizeof(code); pos++) if (code[pos] != eeprom_read_byte(passwd + pos - 1)) 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)); return; } for (c = 0; c < sizeof(code) - 1; c++) code[c] = code[c + 1]; code[c] = ascii; - statecntr = WAIT_INPUT; + PORTB &= ~B_BEEP; + cntr = CNTR_BEEP; nextstate = STATE_INPUT; } ISR(SIG_USART_RECV) { uint8_t data = UDR0; @@ -610,12 +639,15 @@ ISR(SIG_USART_RECV) } 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 */ TCCR0A = 0; TIMSK0 = (1 << TOIE0); TCCR0B = (1 << CS02); @@ -637,11 +669,13 @@ int main() while (1) { if (nextstate != STATE_NONE) { state = nextstate; nextstate = STATE_NONE; state_enter(); } else if (!statecntr) { - state_timeout(); + state = toutstate; + nextstate = STATE_NONE; + state_enter(); } } } |
