diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 10 | ||||
| -rw-r--r-- | door_ps2.brd | bin | 0 -> 19306 bytes | |||
| -rw-r--r-- | door_ps2.sch | bin | 0 -> 195453 bytes | |||
| -rw-r--r-- | kbc.c | 129 |
5 files changed, 125 insertions, 15 deletions
@@ -3,3 +3,4 @@ *.eeprom *.map *.orig +*.?#? @@ -1,4 +1,4 @@ -MCU=atmega48 +MCU=atmega88 AVRDUDE=avrdude ACC=avr-gcc AOBJCOPY=avr-objcopy @@ -8,6 +8,10 @@ CFLAGS=-Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 ifdef PIN DPIN=-DPIN=\"$(PIN)\" endif + +ifdef MASTER_PIN +DPIN+=-DMASTER_PIN=\"$(MASTER_PIN)\" +endif ACFLAGS=-g -mmcu=$(MCU) $(CFLAGS) $(DPIN) -Os -mcall-prologues # ALDFLAGS=-L/usr/avr/lib/avr4 -L/usr/lib/binutils/avr/2.18 LD=gcc @@ -31,9 +35,9 @@ love: kbc.flash kbc.eeprom $(ACC) $(ACFLAGS) -c -o $@ $< flash: kbc.flash - $(AVRDUDE) -y -p m48 -E noreset -U flash:w:$<:r + $(AVRDUDE) -y -p m88 -E noreset -U flash:w:$<:r eeprom: kbc.eeprom - $(AVRDUDE) -y -p m48 -E noreset -U eeprom:w:$<:r + $(AVRDUDE) -y -p m88 -E noreset -U eeprom:w:$<:r clean: rm -f *.flash *.eeprom *.o diff --git a/door_ps2.brd b/door_ps2.brd Binary files differnew file mode 100644 index 0000000..fe5fd9c --- /dev/null +++ b/door_ps2.brd diff --git a/door_ps2.sch b/door_ps2.sch Binary files differnew file mode 100644 index 0000000..ad5ba9b --- /dev/null +++ b/door_ps2.sch @@ -12,6 +12,10 @@ #error need to define a PIN #endif +#ifndef MASTER_PIN +#error need to define a MASTER_PIN +#endif + /* port B RJ45 * 0 * 1 BEEP (OC1A) @@ -54,6 +58,8 @@ enum state { STATE_CONFIG, STATE_IDLE, STATE_IDLEBLINK, + STATE_PASSWORD, + STATE_PASSWORD2, STATE_INPUT, STATE_ACCEPT, STATE_REJECT, @@ -63,7 +69,15 @@ enum state { STATE_ERROR, #endif }; -static volatile enum state state, nextstate, toutstate; + +/* state is the current system state */ +static volatile enum state state; + +/* system will advance to nextstate on return to main, if nextstate is != STATE_NONE */ +static volatile enum state nextstate; + +/* system will advance to toutstate on timeout. */ +static volatile enum state toutstate; static void power_up() { @@ -109,7 +123,7 @@ static void dbg_wr(uint8_t what) sei(); } -ISR(SIG_SPI) +ISR(SPI_STC_vect) { if (dbgpos) { SPDR = dbgtx[0]; @@ -333,6 +347,7 @@ static uint8_t wait_byte(void) #define CNTR_BLINK 6 #define CNTR_ERROR 61 #define CNTR_BEEP 10 +#define CNTR_BEEP_ACK 30 #define CNTR_BEEP_REJ 92 #define WAIT_INPUT 6 @@ -345,12 +360,15 @@ static uint8_t wait_byte(void) static uint8_t cntr = 0; static uint8_t close_try = 0; +static uint8_t idle_looped = 0; #ifdef KILLSWITCH static uint8_t error; #endif -static const EEMEM uint8_t passwd[sizeof(PIN) - 1] = PIN; +static EEMEM uint8_t passwd[sizeof(PIN) - 1] = PIN; +static EEMEM uint8_t mpasswd[sizeof(MASTER_PIN) - 1] = MASTER_PIN; static uint8_t code[sizeof(PIN)]; +static uint8_t new_code[sizeof(PIN)]; static void state_enter(void) { @@ -401,7 +419,7 @@ static void state_enter(void) nextstate = STATE_IDLE; break; case STATE_IDLE: - memset(&code, 0, sizeof(code)); + memset(code, 0, sizeof(code)); toutstate = STATE_IDLEBLINK; statecntr = WAIT_IDLE; nextstate = STATE_FAILURE; @@ -409,7 +427,13 @@ static void state_enter(void) break; if (send_byte(0x00) != 0xfa) break; - nextstate = STATE_NONE; + + /* We have some issues with the keyboard failing every + * now and then. Until we know more about the issue, + * reset it every 256th time we enter STATE_IDLE :/ */ + idle_looped += 1; + if (idle_looped != 0xff) + nextstate = STATE_NONE; break; case STATE_IDLEBLINK: toutstate = STATE_IDLE; @@ -424,12 +448,22 @@ static void state_enter(void) break; case STATE_INPUT: toutstate = STATE_IDLE; + idle_looped = 0; /* input still works, reset idle counter */ statecntr = WAIT_INPUT; if (send_byte(0xed) != 0xfa) break; if (send_byte(KBLED_STATE) != 0xfa) break; break; + case STATE_PASSWORD: + case STATE_PASSWORD2: + toutstate = STATE_IDLE; + statecntr = WAIT_INPUT; + if (send_byte(0xed) != 0xfa) + break; + if (send_byte(KBLED_STATE | KBLED_OK) != 0xfa) + break; + break; case STATE_ACCEPT: toutstate = close_try ? STATE_KEYMATIC_RECHECK : STATE_IDLE; statecntr = WAIT_ACCEPT; @@ -487,7 +521,7 @@ static void state_enter(void) } } -ISR(SIG_OVERFLOW0) +ISR(TIMER0_OVF_vect) { if (!--cntr) { cntr = CNTRTOP; @@ -524,18 +558,20 @@ const PROGMEM uint8_t kbc[] = { }; #define NUMPAD_ENTER 0xda /* e0 5a */ +#define F12 0x07 static uint8_t pressed = 0, e0 = 0, release = 0; static void handle_keypress(uint8_t data) { - uint8_t unlock, lock; + uint8_t unlock, lock, change_pass; uint8_t ascii = '_'; uint8_t c; if (release) { pressed = 0; release = 0; + e0 = 0; return; } if (data == pressed) @@ -564,8 +600,66 @@ static void handle_keypress(uint8_t data) dbg_wr(0x80 | (ascii & 0xf)); dbg_wr(0x80 | (ascii >> 4)); - lock = ascii == ESC; - unlock = ascii == ENT || data == NUMPAD_ENTER; + if (state != STATE_PASSWORD && state != STATE_PASSWORD2) { + lock = ascii == ESC; + unlock = ascii == ENT || data == NUMPAD_ENTER; + change_pass = data == F12; + } else { + lock = unlock = 0; + change_pass = ascii == ENT || data == NUMPAD_ENTER; + } + + if (change_pass) { + uint8_t pos, ok = 1; + switch(state) { + default: + /* Check master password, change state to password input */ + if (code[0]) + ok = 0; + + for (pos = 1; pos < sizeof(code); pos++) + if(code[pos] != eeprom_read_byte(mpasswd + pos - 1)) + ok = 0; + + if (ok) { + cntr = CNTR_BEEP_ACK; + nextstate = STATE_PASSWORD; + } + break; + case STATE_PASSWORD: + /* Check password and store it to buffer */ + if (code[0]) + ok = 0; + + if (ok) { + memcpy(new_code, code, sizeof(code)); + PORTB &= ~B_BEEP; + cntr = CNTR_BEEP_ACK; + nextstate = STATE_PASSWORD2; + } + break; + case STATE_PASSWORD2: + /* Compare password with buffer, write to eeprom */ + if (memcmp(new_code, code, sizeof(code))) + ok = 0; + if (ok) { + eeprom_update_block(new_code + 1, passwd, + sizeof(new_code) - 1); + PORTB &= ~B_BEEP; + cntr = CNTR_BEEP_REJ; + nextstate = STATE_ACCEPT; + } + break; + } + if (!ok) { + PORTB &= ~B_BEEP; + + cntr = CNTR_BEEP_REJ; + nextstate = STATE_REJECT; + } + memset(code, 0, sizeof(code)); + return; + } if (lock || unlock) { uint8_t pos, ok = 1; @@ -603,7 +697,7 @@ static void handle_keypress(uint8_t data) cntr = CNTR_KEYMATIC; nextstate = STATE_ACCEPT; } - memset(&code, 0, sizeof(code)); + memset(code, 0, sizeof(code)); return; } @@ -613,10 +707,19 @@ static void handle_keypress(uint8_t data) PORTB &= ~B_BEEP; cntr = CNTR_BEEP; - nextstate = STATE_INPUT; + switch (state) { + case STATE_PASSWORD: + nextstate = STATE_PASSWORD; + break; + case STATE_PASSWORD2: + nextstate = STATE_PASSWORD2; + break; + default: + nextstate = STATE_INPUT; + } } -ISR(SIG_USART_RECV) +ISR(USART_RX_vect) { uint8_t data = UDR0; @@ -631,6 +734,8 @@ ISR(SIG_USART_RECV) break; case STATE_IDLE: case STATE_IDLEBLINK: + case STATE_PASSWORD: + case STATE_PASSWORD2: case STATE_INPUT: handle_keypress(data); default: |
