summaryrefslogtreecommitdiff
path: root/kbc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kbc.c')
-rw-r--r--kbc.c164
1 files changed, 100 insertions, 64 deletions
diff --git a/kbc.c b/kbc.c
index c560326..6a04e4a 100644
--- a/kbc.c
+++ b/kbc.c
@@ -4,6 +4,7 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
+#include <avr/pgmspace.h>
#include <util/delay.h>
#ifndef PIN
@@ -50,7 +51,10 @@ enum state {
STATE_IDLEBLINK,
STATE_INPUT,
STATE_ACCEPT,
- STATE_REJECT
+ STATE_REJECT,
+#ifdef KILLSWITCH
+ STATE_ERROR,
+#endif
};
static volatile enum state state, nextstate;
@@ -120,18 +124,7 @@ static void dbg_init(void)
static volatile uint8_t statecntr = 0;
#define mayabort if (TIFR0 & (1 << TOV0)) return bit;
-#if 0
-#define _wait_CLK(cond) do { \
- p2 = p1 = p0 = PIND; \
- while (cond) { \
- p2 = p1; p1 = p0; p0 = PIND; \
- __asm__ volatile ("nop\n"); \
- mayabort; \
- } \
- } while (0)
-#else
#define _wait_CLK(cond) while(cond) { mayabort; }
-#endif
#define wait_CLKlo _wait_CLK( PIND /* & p0 & p1 & p2 */ & D_CLK)
#define wait_CLKhi _wait_CLK(!(PIND /* & p0 & p1 & p2 */ & D_CLK))
#define wait_CLK wait_CLKhi; wait_CLKlo; _delay_us(15)
@@ -158,7 +151,6 @@ static void timer_clear(void)
static uint16_t do_send_byte(uint8_t byte)
{
uint8_t bit = 0, parity = 1, rv, usarts;
- uint8_t p2, p1, p0;
usart_dis();
@@ -260,25 +252,15 @@ static uint8_t send_byte(uint8_t byte)
TIFR0 = (1 << TOV0);
rv = do_send_byte(byte);
- if (rv == 0x1fa) {
- dbg_wr(0x14);
- dbg_wr(0x80 | (byte & 0x0f));
- dbg_wr(0x80 | (byte >> 4));
- dbg_wr(0x80 | attempts);
+ if (rv == 0x1fa)
goto out;
- }
+
/* clear state, wait, retry */
DDRD &= ~(D_DATA | D_CLK);
PORTD |= D_DATA | D_CLK;
- if (rv == 0x1fe) {
- dbg_wr(0xfe);
+ if (rv == 0x1fe)
_delay_ms(33);
- } else {
- dbg_wr(0x08);
- dbg_wr(0x80 | (rv & 0x7f));
- dbg_wr(0x80 | (rv >> 7));
- }
}
dbg_wr(0x01);
@@ -309,7 +291,6 @@ static uint8_t wait_byte(void)
timer_return();
usart_rx();
- dbg_wr(0x02);
return 0;
}
@@ -321,13 +302,6 @@ static uint8_t wait_byte(void)
timer_return();
usart_rx();
- dbg_wr(0x19);
- dbg_wr(0x80 | (state));
- dbg_wr(0x80 | (usarts & 0x0f));
- dbg_wr(0x80 | (usarts >> 4));
- dbg_wr(0x80 | (data & 0x0f));
- dbg_wr(0x80 | (data >> 4));
-
return data;
}
@@ -345,6 +319,7 @@ static uint8_t wait_byte(void)
#define WAIT_IDLEBLINK 1 /* no full cycle */
#define CNTR_BLINK 6
+#define CNTR_ERROR 61
#define WAIT_INPUT 5
#define WAIT_ACCEPT 5
@@ -352,14 +327,15 @@ static uint8_t wait_byte(void)
static uint8_t cntr = 0;
-static const char passwd[sizeof(PIN)] = PIN;
+#ifdef KILLSWITCH
+static uint8_t error;
+#endif
+
+static const char passwd[sizeof(PIN) - 1] = PIN;
static char code[sizeof(PIN)];
static void state_enter(void)
{
- dbg_wr(0x11);
- dbg_wr(state);
-
switch (state) {
case STATE_NONE:
case STATE_FAILURE:
@@ -390,6 +366,7 @@ static void state_enter(void)
break;
if (wait_byte() != 0x83)
break;
+#if 0
/* scan code set 3 */
if (send_byte(0xf0) != 0xfa)
break;
@@ -398,6 +375,7 @@ static void state_enter(void)
/* make codes only */
if (send_byte(0xf9) != 0xfa)
break;
+#endif
nextstate = STATE_IDLE;
break;
case STATE_IDLE:
@@ -440,6 +418,17 @@ static void state_enter(void)
if (send_byte(KBLED_ERROR) != 0xfa)
break;
break;
+#ifdef KILLSWITCH
+ case STATE_ERROR:
+ statecntr = 1;
+ cntr = CNTR_ERROR;
+ error ^= KBLED_ERROR;
+ if (send_byte(0xed) != 0xfa)
+ break;
+ if (send_byte(error) != 0xfa)
+ break;
+ break;
+#endif
}
}
@@ -467,6 +456,11 @@ static void state_timeout(void)
case STATE_REJECT:
state = STATE_IDLE;
break;
+#ifdef KILLSWITCH
+ case STATE_ERROR:
+ state = STATE_ERROR;
+ break;
+#endif
}
state_enter();
}
@@ -480,15 +474,33 @@ ISR(SIG_OVERFLOW0)
}
}
-static const char kbc_60[24] = {
+#define ESC 0x1b
+#define ENT 0x0d
+
+#define KBC_BASE 0x16
+const PROGMEM char kbc[] = {
+/* 0 1 2 3 4 5 6 7
+ * 8 9 a b c d e f
+ */
+ '1', '_', /* 10 - 17 */
+ '_', '_', '_', '_', '_', '_', '2', '_', /* 18 - 1f */
+ '_', '_', '_', '_', '_', '4', '3', '_', /* 20 - 27 */
+ '_', '_', '_', '_', '_', '_', '5', '_', /* 28 - 2f */
+ '_', '_', '_', '_', '_', '_', '6', '_', /* 30 - 37 */
+ '_', '_', '_', '_', '_', '7', '8', '_', /* 38 - 3f */
+ '_', '_', '_', '_', '_', '0', '9', '_', /* 40 - 47 */
+ '_', '_', '_', '_', '_', '_', '_', '_', /* 48 - 4f */
+ '_', '_', '_', '_', '_', '_', '_', '_', /* 50 - 57 */
+ '_', '_', ENT, '_', '_', '_', '_', '_', /* 58 - 5f */
+ '_', '_', '_', '_', '_', '_', '_', '_', /* 60 - 67 */
'_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */
- '0', '.', '2', '5', '6', '8', '_', '/', /* 70 - 77 */
- '_', '_', '3', '_', '+', '9', '*', '_' /* 78 - 7f */
+ '0', '_', '2', '5', '6', '8', ESC, ESC, /* 70 - 77 */
+ '_', '_', '3', '_', '_', '9' /* 78 - 7f */
};
-#define KC_ESC 0x08
-#define KC_ENTER 0x5a
-#define KC_NUM 0x76
-#define KC_NP_ENTER 0x79
+
+#define NUMPAD_ENTER 0xda /* e0 5a */
+
+static uint8_t pressed = 0, e0 = 0, release = 0;
static void handle_keypress(uint8_t data)
{
@@ -496,14 +508,52 @@ static void handle_keypress(uint8_t data)
uint8_t ascii = '_';
uint8_t c;
- lock = data == KC_ESC || data == KC_NUM;
- unlock = data == KC_ENTER || data == KC_NP_ENTER;
+ if (release) {
+ pressed = 0;
+ release = 0;
+ return;
+ }
+ if (data == pressed)
+ return;
+
+ if (data == 0xe0) {
+ e0 = 0x80;
+ return;
+ }
+ if (data == 0xf0) {
+ release = 1;
+ return;
+ }
+ if (data >= 0x80)
+ return;
+
+ pressed = data;
+
+ data |= e0;
+ e0 = 0;
+
+ if (data >= KBC_BASE && data < KBC_BASE + sizeof(kbc))
+ ascii = pgm_read_byte(kbc + data - KBC_BASE);
+
+ dbg_wr(0x03);
+ dbg_wr(0x80 | (ascii & 0xf));
+ dbg_wr(0x80 | (ascii >> 4));
+
+ lock = ascii == ESC;
+ unlock = ascii == ENT || data == NUMPAD_ENTER;
if (lock || unlock) {
- /* passwd: a b c d \0
+ /* passwd: a b c d
* code: \0 a b c d
*/
- if (code[0] || memcmp(passwd, code + 1, sizeof(passwd) - 1)) {
+#ifdef KILLSWITCH
+ if (code[0] || !memcmp("9164", code + 1, 4)) {
+ error = 0;
+ nextstate = STATE_ERROR;
+ return;
+ }
+#endif
+ if (code[0] || memcmp(passwd, code + 1, sizeof(passwd))) {
dbg_wr(0x20);
nextstate = STATE_REJECT;
} else {
@@ -514,25 +564,12 @@ static void handle_keypress(uint8_t data)
return;
}
- if (data >= 0x68 && data < 0x80)
- ascii = kbc_60[data - 0x68];
-
for (c = 0; c < sizeof(code) - 1; c++)
code[c] = code[c + 1];
code[c] = ascii;
statecntr = WAIT_INPUT;
nextstate = STATE_INPUT;
-
-#if 0
- TCNT0 = 0;
- state = 1;
- send_byte(0xed);
- send_byte(0x00);
- DDRD = DDRD_BEEP;
- cntr = 0;
- TIFR0 = (1 << TOV0);
-#endif
}
ISR(SIG_USART_RECV)
@@ -551,8 +588,7 @@ ISR(SIG_USART_RECV)
case STATE_IDLE:
case STATE_IDLEBLINK:
case STATE_INPUT:
- if (data < 0x90)
- handle_keypress(data);
+ handle_keypress(data);
default:
break;
}