diff options
| author | David Lamparter <equinox@diac24.net> | 2010-10-17 20:43:56 +0200 |
|---|---|---|
| committer | David Lamparter <equinox@diac24.net> | 2010-10-17 20:43:56 +0200 |
| commit | 71a40edcc08a468d4e661416b09882d339334ecd (patch) | |
| tree | 0245c7bd38a78a796fae20b41cc55686a372dbe2 | |
kbc: initial commit
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | Makefile | 38 | ||||
| -rw-r--r-- | kbc.c | 246 |
3 files changed, 287 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b31adb --- /dev/null +++ b/.gitignore | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | *.o | ||
| 2 | *.flash | ||
| 3 | *.eeprom | ||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..642202a --- /dev/null +++ b/Makefile | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | MCU=atmega48 | ||
| 2 | AVRDUDE=avrdude | ||
| 3 | ACC=avr-gcc | ||
| 4 | AOBJCOPY=avr-objcopy | ||
| 5 | ALD=avr-ld | ||
| 6 | CFLAGS=-Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 | ||
| 7 | ifdef PIN | ||
| 8 | DPIN=-DPIN=\"$(PIN)\" | ||
| 9 | endif | ||
| 10 | ACFLAGS=-g -mmcu=$(MCU) $(CFLAGS) $(DPIN) -Os -mcall-prologues | ||
| 11 | # ALDFLAGS=-L/usr/avr/lib/avr4 -L/usr/lib/binutils/avr/2.18 | ||
| 12 | LD=gcc | ||
| 13 | CC=gcc | ||
| 14 | CXX=g++ -g | ||
| 15 | LDXX=g++ -g | ||
| 16 | |||
| 17 | love: kbc.flash | ||
| 18 | |||
| 19 | %.flash: %.ld.o | ||
| 20 | $(AOBJCOPY) -O binary $< $@ | ||
| 21 | |||
| 22 | %.eeprom: %.ld.o | ||
| 23 | $(AOBJCOPY) -j .eeprom -O binary $^ $@ | ||
| 24 | |||
| 25 | %.ld.o: %.o | ||
| 26 | $(ACC) $(ACFLAGS) $(ALDFLAGS) -o $@ $< | ||
| 27 | |||
| 28 | %.o: %.c | ||
| 29 | $(ACC) $(ACFLAGS) -c -o $@ $< | ||
| 30 | |||
| 31 | flash: kbc.flash | ||
| 32 | $(AVRDUDE) -y -p m48 -E noreset -U $^ | ||
| 33 | |||
| 34 | clean: | ||
| 35 | rm -f *.flash *.eeprom *.o | ||
| 36 | |||
| 37 | .PHONY: love flash clean | ||
| 38 | |||
| @@ -0,0 +1,246 @@ | |||
| 1 | #include <stdint.h> | ||
| 2 | #include <string.h> | ||
| 3 | #include <avr/io.h> | ||
| 4 | #include <avr/interrupt.h> | ||
| 5 | #include <avr/sleep.h> | ||
| 6 | |||
| 7 | #ifndef PIN | ||
| 8 | #error need to define a PIN | ||
| 9 | #endif | ||
| 10 | |||
| 11 | #define B_RED (1 << 0) | ||
| 12 | #define B_YLW (1 << 1) | ||
| 13 | |||
| 14 | static void usart_rx() | ||
| 15 | { | ||
| 16 | UCSR0B = (1 << RXCIE0) /* recv int en */ | ||
| 17 | | (1 << RXEN0); /* do RX */ | ||
| 18 | } | ||
| 19 | |||
| 20 | static void usart_rxpoll() | ||
| 21 | { | ||
| 22 | UCSR0B = (1 << RXEN0); /* do RX*/ | ||
| 23 | } | ||
| 24 | |||
| 25 | static void usart_dis() | ||
| 26 | { | ||
| 27 | UCSR0B = 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | #define CLK (1 << 3) | ||
| 31 | #define DATA (1 << 1) | ||
| 32 | |||
| 33 | static uint8_t send_byte(uint8_t byte) | ||
| 34 | { | ||
| 35 | uint8_t cntr, bit, parity = 1, rv; | ||
| 36 | |||
| 37 | usart_dis(); | ||
| 38 | rv = UDR0; | ||
| 39 | |||
| 40 | /* make clock low, request clock from keyboard */ | ||
| 41 | PORTD = 0; | ||
| 42 | DDRD = CLK; | ||
| 43 | |||
| 44 | #define delay(x) for (cntr = 0; cntr < x; cntr++) __asm__ volatile ("nop\n") | ||
| 45 | |||
| 46 | delay(200); | ||
| 47 | |||
| 48 | DDRD = CLK | DATA; | ||
| 49 | |||
| 50 | delay(10); | ||
| 51 | |||
| 52 | DDRD = DATA; | ||
| 53 | PORTD = CLK; | ||
| 54 | |||
| 55 | #define wait_CLKlo while (PIND & CLK) __asm__ volatile ("nop\n") | ||
| 56 | #define wait_CLKhi while (!(PIND & CLK)) __asm__ volatile ("nop\n") | ||
| 57 | #define wait_CLK wait_CLKhi; wait_CLKlo; delay(3) | ||
| 58 | |||
| 59 | for (bit = 0; bit < 8; bit++) { | ||
| 60 | wait_CLK; | ||
| 61 | if (byte & 1) { | ||
| 62 | PORTD = CLK | DATA; | ||
| 63 | parity++; | ||
| 64 | } else { | ||
| 65 | PORTD = CLK; | ||
| 66 | } | ||
| 67 | byte >>= 1; | ||
| 68 | } | ||
| 69 | wait_CLK; | ||
| 70 | PORTD = (parity & 1) ? (CLK | DATA) : CLK; | ||
| 71 | wait_CLK; | ||
| 72 | |||
| 73 | PORTD = CLK | DATA; | ||
| 74 | wait_CLKhi; | ||
| 75 | |||
| 76 | DDRD = 0; | ||
| 77 | |||
| 78 | wait_CLKlo; | ||
| 79 | wait_CLKhi; | ||
| 80 | |||
| 81 | usart_rxpoll(); | ||
| 82 | |||
| 83 | while (!(UCSR0A & (1 << RXC0))) | ||
| 84 | __asm__ volatile("nop\n"); | ||
| 85 | |||
| 86 | rv = UDR0; | ||
| 87 | usart_rx(); | ||
| 88 | |||
| 89 | return rv; | ||
| 90 | } | ||
| 91 | |||
| 92 | uint8_t ext, brk, pressed, state; | ||
| 93 | const char passwd[4] = PIN; | ||
| 94 | char code[sizeof(passwd)]; | ||
| 95 | |||
| 96 | const char kbc_60[32] = { | ||
| 97 | '_', '_', '_', '_', '_', '_', '_', '_', /* 60 - 67 */ | ||
| 98 | '_', '1', '_', '4', '7', '_', '_', '_', /* 68 - 6f */ | ||
| 99 | '0', '.', '2', '5', '6', '8', '_', '_', /* 70 - 77 */ | ||
| 100 | '_', '+', '3', '-', '*', '9', '_', '_' /* 78 - 7f */ | ||
| 101 | }; | ||
| 102 | |||
| 103 | #define KBLED_STATE 0x02 | ||
| 104 | #define KBLED_ERROR 0x04 | ||
| 105 | #define KBLED_OK 0x01 | ||
| 106 | |||
| 107 | #define DDRD_BEEP 0x20 | ||
| 108 | #define DDRD_OPEN 0x40 | ||
| 109 | #define DDRD_CLOSE 0x80 | ||
| 110 | |||
| 111 | #define CNTRTOP 96 | ||
| 112 | #define CNTRERR 90 | ||
| 113 | #define CNTRKEYBEEPOFF 4 | ||
| 114 | #define CNTROK 88 /* regulates length of keymatic button press */ | ||
| 115 | #define CNTROK_BEEPOFF 90 | ||
| 116 | #define CNTROK_BEEPON2 94 | ||
| 117 | #define OK_WAIT 3 /* mult CNTRTOP */ | ||
| 118 | |||
| 119 | static uint8_t cntr = 0; | ||
| 120 | |||
| 121 | ISR(SIG_OVERFLOW0) | ||
| 122 | { | ||
| 123 | switch (cntr) { | ||
| 124 | case CNTRTOP: | ||
| 125 | DDRD = 0; | ||
| 126 | if (state > 1) { | ||
| 127 | state--; | ||
| 128 | } else if (state == 1) { | ||
| 129 | memset(&code, 0, sizeof(code)); | ||
| 130 | state = 0; | ||
| 131 | } else { | ||
| 132 | send_byte(0xed); | ||
| 133 | send_byte(KBLED_STATE); | ||
| 134 | } | ||
| 135 | cntr = 0; | ||
| 136 | return; | ||
| 137 | case CNTROK_BEEPOFF: | ||
| 138 | if (state > 1) | ||
| 139 | DDRD &= ~DDRD_BEEP; | ||
| 140 | break; | ||
| 141 | case CNTROK_BEEPON2: | ||
| 142 | if (state > 1) | ||
| 143 | DDRD |= DDRD_BEEP; | ||
| 144 | break; | ||
| 145 | case CNTRKEYBEEPOFF: | ||
| 146 | DDRD = 0; | ||
| 147 | break; | ||
| 148 | case 0x00: | ||
| 149 | if (state <= 1) { | ||
| 150 | send_byte(0xed); | ||
| 151 | send_byte(state ? KBLED_STATE : 0); | ||
| 152 | } | ||
| 153 | break; | ||
| 154 | } | ||
| 155 | cntr++; | ||
| 156 | } | ||
| 157 | |||
| 158 | ISR(SIG_USART_RECV) | ||
| 159 | { | ||
| 160 | uint8_t data = UDR0, now; | ||
| 161 | |||
| 162 | if (data == 0xe0) { | ||
| 163 | ext = 0x80; | ||
| 164 | return; | ||
| 165 | } | ||
| 166 | if (data == 0xf0) { | ||
| 167 | brk = 1; | ||
| 168 | return; | ||
| 169 | } | ||
| 170 | if (data < 0x80) { | ||
| 171 | if (brk) { | ||
| 172 | pressed = 0; | ||
| 173 | brk = 0; | ||
| 174 | ext = 0; | ||
| 175 | return; | ||
| 176 | } else { | ||
| 177 | now = (data | ext); | ||
| 178 | ext = 0; | ||
| 179 | if (pressed == now) | ||
| 180 | return; | ||
| 181 | pressed = now; | ||
| 182 | |||
| 183 | if (pressed > 0x60 && pressed < 0x80 && pressed != 0x76 && pressed != 0x77) { | ||
| 184 | uint8_t c; | ||
| 185 | for (c = 1; c < sizeof(code); c++) | ||
| 186 | code[c - 1] = code[c]; | ||
| 187 | code[sizeof(code) - 1] = kbc_60[pressed - 0x60]; | ||
| 188 | |||
| 189 | TCNT0 = 0; | ||
| 190 | state = 1; | ||
| 191 | send_byte(0xed); | ||
| 192 | send_byte(0x00); | ||
| 193 | DDRD = DDRD_BEEP; | ||
| 194 | cntr = 0; | ||
| 195 | TIFR0 = (1 << TOV0); | ||
| 196 | }; | ||
| 197 | if (pressed == 0xda || pressed == 0x76 || pressed == 0x77) { | ||
| 198 | if (memcmp(passwd, code, sizeof(passwd))) { | ||
| 199 | TCNT0 = 0; | ||
| 200 | memset(&code, 0, sizeof(code)); | ||
| 201 | state = 0; | ||
| 202 | send_byte(0xed); | ||
| 203 | send_byte(KBLED_ERROR); | ||
| 204 | DDRD = DDRD_BEEP; | ||
| 205 | cntr = CNTRERR; | ||
| 206 | TIFR0 = (1 << TOV0); | ||
| 207 | return; | ||
| 208 | } | ||
| 209 | TCNT0 = 0; | ||
| 210 | send_byte(0xed); | ||
| 211 | send_byte(KBLED_OK); | ||
| 212 | state = OK_WAIT; | ||
| 213 | cntr = CNTROK; | ||
| 214 | TIFR0 = (1 << TOV0); | ||
| 215 | |||
| 216 | DDRD = DDRD_BEEP | ((pressed == 0xda) ? DDRD_OPEN : DDRD_CLOSE); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | return; | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | int main() | ||
| 224 | { | ||
| 225 | DDRB = (1 << 4) | B_RED | B_YLW; | ||
| 226 | PORTB = (1 << 4) | B_RED | B_YLW; | ||
| 227 | |||
| 228 | DDRD = 0; | ||
| 229 | PORTD = 0x3f; | ||
| 230 | |||
| 231 | TCCR0A = 0; | ||
| 232 | TIMSK0 = (1 << TOIE0); | ||
| 233 | TCCR0B = (1 << CS02); | ||
| 234 | |||
| 235 | UCSR0C = (1 << UMSEL00) /* synch mode */ | ||
| 236 | | (1 << UPM01) | (1 << UPM00) /* odd parity */ | ||
| 237 | | (1 << UCSZ01) | (1 << UCSZ00) /* 8-bit chars */ | ||
| 238 | | (0 << UCPOL0); /* polarity: sample on falling */ | ||
| 239 | |||
| 240 | usart_rx(); | ||
| 241 | |||
| 242 | sei(); | ||
| 243 | while (1) | ||
| 244 | ; | ||
| 245 | } | ||
| 246 | |||
