summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@diac24.net>2011-03-04 00:29:47 +0100
committerDavid Lamparter <equinox@diac24.net>2011-03-04 00:29:47 +0100
commitfb92f1bb096bdf7bddb6bb66c931d4212fbc5588 (patch)
tree6c77034c01482df832cff0bc10bfb6de73de9552
parentd6be96c302ea4ce09d5abc64242ea5329fd28e3b (diff)
intermediate version
-rw-r--r--kbc.c166
1 files changed, 126 insertions, 40 deletions
diff --git a/kbc.c b/kbc.c
index b7bce72..c560326 100644
--- a/kbc.c
+++ b/kbc.c
@@ -48,6 +48,9 @@ enum state {
STATE_CONFIG,
STATE_IDLE,
STATE_IDLEBLINK,
+ STATE_INPUT,
+ STATE_ACCEPT,
+ STATE_REJECT
};
static volatile enum state state, nextstate;
@@ -114,47 +117,72 @@ static void dbg_init(void)
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;
@@ -162,64 +190,95 @@ static uint8_t do_send_byte(uint8_t byte)
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);
@@ -287,7 +346,9 @@ static uint8_t wait_byte(void)
#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;
@@ -353,11 +414,32 @@ static void state_enter(void)
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;
}
}
@@ -378,7 +460,11 @@ static void state_timeout(void)
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;
}
@@ -394,8 +480,7 @@ ISR(SIG_OVERFLOW0)
}
}
-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 */
@@ -419,25 +504,25 @@ static void handle_keypress(uint8_t data)
* 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;
@@ -465,6 +550,7 @@ ISR(SIG_USART_RECV)
break;
case STATE_IDLE:
case STATE_IDLEBLINK:
+ case STATE_INPUT:
if (data < 0x90)
handle_keypress(data);
default:
@@ -481,7 +567,7 @@ int main()
* /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 */
@@ -492,18 +578,18 @@ int main()
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);
}
}
}