diff options
| author | David Lamparter <equinox@diac24.net> | 2011-03-04 00:29:47 +0100 |
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2011-03-04 00:29:47 +0100 |
| commit | fb92f1bb096bdf7bddb6bb66c931d4212fbc5588 (patch) | |
| tree | 6c77034c01482df832cff0bc10bfb6de73de9552 | |
| parent | d6be96c302ea4ce09d5abc64242ea5329fd28e3b (diff) | |
intermediate version
| -rw-r--r-- | kbc.c | 166 |
1 files changed, 126 insertions, 40 deletions
@@ -45,12 +45,15 @@ enum state { STATE_FAILURE, STATE_POWERUP, STATE_INITRESET, STATE_CONFIG, STATE_IDLE, STATE_IDLEBLINK, + STATE_INPUT, + STATE_ACCEPT, + STATE_REJECT }; static volatile enum state state, nextstate; static void power_up() { DDRD = D_PWR; @@ -111,118 +114,174 @@ static void dbg_init(void) { DDRB |= B_MISO; /* MSB first, cpol = rise,fall, cpha = sample(r),setup(f) */ SPCR = (1 << SPIE) | (1 << SPE); } - - - static volatile uint8_t statecntr = 0; -#define mayabort if (TIFR0 & (1 << TOV0)) return 0; -#define wait_CLKlo while (PIND & D_CLK) { __asm__ volatile ("nop\n"); mayabort; } -#define wait_CLKhi while (!(PIND & D_CLK)) { __asm__ volatile ("nop\n"); mayabort; } -#define wait_CLK wait_CLKhi; wait_CLKlo; _delay_us(5) +#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) +#define wait_CLKb + +#define wait_CLK_set wait_CLKlo +#define wait_CLK_samp wait_CLKhi static void timer_return(void) { TCNT0 = 0; - TIFR0 |= (1 << TOV0); + TIFR0 = (1 << TOV0); __asm__ volatile("nop\n"); TIMSK0 = (1 << TOIE0); } -static uint8_t do_send_byte(uint8_t byte) +static void timer_clear(void) +{ + TCNT0 = 0; + __asm__ volatile("nop\n"); + TIFR0 = (1 << TOV0); +} + +static uint16_t do_send_byte(uint8_t byte) { uint8_t bit = 0, parity = 1, rv, usarts; + uint8_t p2, p1, p0; usart_dis(); + _delay_us(5); + /* make clock low, request clock from keyboard */ PORTD &= ~D_CLK; DDRD |= D_CLK; - _delay_us(250); + _delay_us(166); PORTD &= ~D_DATA; DDRD |= D_DATA; - _delay_us(25); + // _delay_us(3); DDRD &= ~D_CLK; PORTD |= D_CLK; + wait_CLK_samp; + /* data bits */ for (bit = 0; bit < 8; bit++) { - wait_CLK; + wait_CLK_set; if (byte & 1) { PORTD |= D_DATA; parity ^= 1; } else { PORTD &= ~D_DATA; } byte >>= 1; + wait_CLK_samp; } + + timer_clear(); + + bit = 0x10; /* parity */ - wait_CLK; + wait_CLK_set; if (parity) PORTD |= D_DATA; else PORTD &= ~D_DATA; + wait_CLK_samp; + bit = 0x11; /* stop bit */ - wait_CLK; + wait_CLK_set; PORTD |= D_DATA; + wait_CLK_samp; + DDRD &= ~D_DATA; +#if 0 + bit = 0x12; /* ACK from keyboard */ - wait_CLKhi; - DDRD &= ~D_DATA; + wait_CLK_set; + wait_CLK_samp; +#endif + + bit = 0x14; + while (PIND & D_DATA) { mayabort; } + bit = 0x15; + while (!(PIND & D_DATA)) { mayabort; } - wait_CLKlo; wait_CLKhi; - while (!(PIND & D_DATA)) { __asm__ volatile ("nop\n"); mayabort; } /* response from keyboard */ + timer_clear(); + bit = 0x16; usart_rxpoll(); usarts = 0; while (!(usarts & ((1 << RXC0) | (1 << UPE0) | (1 << FE0)))) { __asm__ volatile("nop\nnop\n"); usarts = UCSR0A; - mayabort; + if (TIFR0 & (1 << TOV0)) { + TIFR0 = (1 << TOV0); + if (++bit == 0x27) + return bit; + }; } rv = UDR0; - return rv; + return rv | 0x100; } static uint8_t send_byte(uint8_t byte) { - uint8_t rv, attempts; + uint16_t rv; + uint8_t attempts; /* stop timer, use for ourselves to enforce 8 ms timeout */ TIMSK0 = 0; for (attempts = 5; attempts; attempts--) { TCNT0 = 0; - TIFR0 |= (1 << TOV0); + __asm__ volatile("nop\n"); + TIFR0 = (1 << TOV0); - if ((rv = do_send_byte(byte)) == 0xfa) { + 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); goto out; } - /* clear state, wait, retry */ DDRD &= ~(D_DATA | D_CLK); PORTD |= D_DATA | D_CLK; - _delay_us(50); + + if (rv == 0x1fe) { + dbg_wr(0xfe); + _delay_ms(33); + } else { + dbg_wr(0x08); + dbg_wr(0x80 | (rv & 0x7f)); + dbg_wr(0x80 | (rv >> 7)); + } } dbg_wr(0x01); dbg_wr(0x80 | (byte & 0x0f)); dbg_wr(0x80 | (byte >> 4)); @@ -284,13 +343,15 @@ 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 WAIT_ENTRY 15 +#define WAIT_INPUT 5 +#define WAIT_ACCEPT 5 +#define WAIT_REJECT 10 static uint8_t cntr = 0; static const char passwd[sizeof(PIN)] = PIN; static char code[sizeof(PIN)]; @@ -350,17 +411,38 @@ static void state_enter(void) break; case STATE_IDLEBLINK: statecntr = WAIT_IDLEBLINK; nextstate = STATE_FAILURE; if (send_byte(0xed) != 0xfa) break; - if (send_byte(0x01) != 0xfa) + if (send_byte(KBLED_STATE) != 0xfa) break; nextstate = STATE_NONE; cntr = CNTR_BLINK; break; + case STATE_INPUT: + statecntr = WAIT_INPUT; + if (send_byte(0xed) != 0xfa) + break; + if (send_byte(KBLED_STATE) != 0xfa) + break; + break; + case STATE_ACCEPT: + statecntr = WAIT_ACCEPT; + if (send_byte(0xed) != 0xfa) + break; + if (send_byte(KBLED_OK) != 0xfa) + break; + break; + case STATE_REJECT: + statecntr = WAIT_REJECT; + if (send_byte(0xed) != 0xfa) + break; + if (send_byte(KBLED_ERROR) != 0xfa) + break; + break; } } static void state_timeout(void) { switch (state) { @@ -375,13 +457,17 @@ static void state_timeout(void) 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; } state_enter(); } @@ -391,14 +477,13 @@ ISR(SIG_OVERFLOW0) cntr = CNTRTOP; if (statecntr) statecntr--; } } -static const char kbc_60[48] = { - '_', '_', '_', '_', '_', '_', '_', '_', /* 60 - 67 */ +static const char kbc_60[24] = { '_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */ '0', '.', '2', '5', '6', '8', '_', '/', /* 70 - 77 */ '_', '_', '3', '_', '+', '9', '*', '_' /* 78 - 7f */ }; #define KC_ESC 0x08 #define KC_ENTER 0x5a @@ -416,31 +501,31 @@ static void handle_keypress(uint8_t data) if (lock || unlock) { /* passwd: a b c d \0 * code: \0 a b c d */ if (code[0] || memcmp(passwd, code + 1, sizeof(passwd) - 1)) { - dbg_wr(0x20); - /* state = BLOCK; */ + nextstate = STATE_REJECT; } else { dbg_wr(lock ? 0x21 : 0x22); - /* state = OPENING; */ + nextstate = STATE_ACCEPT; } memset(&code, 0, sizeof(code)); return; } - if (data >= 0x60 && data < 0x80) - ascii = kbc_60[data - 0x60]; + 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_ENTRY; */ + statecntr = WAIT_INPUT; + nextstate = STATE_INPUT; #if 0 TCNT0 = 0; state = 1; send_byte(0xed); send_byte(0x00); @@ -462,12 +547,13 @@ ISR(SIG_USART_RECV) case STATE_INITRESET: if (data == 0xaa) nextstate = STATE_CONFIG; break; case STATE_IDLE: case STATE_IDLEBLINK: + case STATE_INPUT: if (data < 0x90) handle_keypress(data); default: break; } } @@ -478,33 +564,33 @@ int main() /* /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); + TCCR0B = (1 << CS02); UCSR0C = (1 << UMSEL00) /* synch mode */ | (1 << UPM01) | (1 << UPM00) /* odd parity */ | (1 << UCSZ01) | (1 << UCSZ00) /* 8-bit chars */ | (0 << UCPOL0); /* polarity: sample on falling */ state = STATE_FAILURE; nextstate = STATE_NONE; state_enter(); + for (int i = 0; i < 5000; i++) { + __asm__ volatile("nop\nnop\n"); + } + sei(); while (1) { if (nextstate != STATE_NONE) { state = nextstate; nextstate = STATE_NONE; state_enter(); - - dbg_wr(0x0e); } else if (!statecntr) { state_timeout(); - - dbg_wr(0x0e); } } } |
