a500kbd

view src/main.c @ 1:3228a731d4db

translate scancodes
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Oct 2017 07:23:47 +0300
parents 8e8e17a0f88e
children a4fd9c5a6655
line source
1 #define F_CPU XTAL
2 #include <stdio.h>
3 #include <ctype.h>
4 #include <avr/io.h>
5 #include <avr/interrupt.h>
6 #include <util/delay.h>
7 #include <util/parity.h>
8 #include "serial.h"
9 #include "scantbl.h"
11 /* pin assignments:
12 * B0 PS/2 data
13 * D2 PS/2 clock (INT0)
14 * B1 KBD data
15 * D3 KBD clock (INT1)
16 */
18 #define BIT_DATA 1
19 #define BIT_CLK 2
21 #define PS2LOW(bit) do { DDRB |= (bit); PORTB &= ~(bit); } while(0)
22 #define PS2HIGH(bit) do { DDRB |= (bit); PORTB |= (bit); } while(0)
23 #define PS2REL(bit) do { DDRB &= ~(bit); PORTB &= ~(bit); } while(0)
25 void ps2write(unsigned char c);
26 unsigned char ps2read(void);
27 int ps2pending(void);
29 #define BUF_SZ 16
30 #define BUF_IDX_MASK (BUF_SZ - 1)
31 #define NEXT_IDX(x) (((x) + 1) & BUF_IDX_MASK)
32 static volatile unsigned char keybuf[BUF_SZ];
33 static volatile unsigned char key_rd, key_wr;
35 static volatile int sending;
37 enum {
38 KF_BRK = 1,
39 KF_EXT = 2,
40 KF_EXT1 = 4,
41 };
43 int main(void)
44 {
45 unsigned int keyflags = 0;
46 int keycode;
48 DDRB = 0;
49 DDRD = 0;
50 PORTB = 0;
51 PORTD = 0;
52 EIMSK = 0; /* mask external interrupts */
53 EICRA = (1 << ISC11) | (1 << ISC01); /* falling edge interrupts */
55 /* initialize the UART and enable interrupts */
56 init_serial(9600);
57 sei();
59 printf("PS/2 keyboard controller - John Tsiombikas <nuclear@member.fsf.org>\r\n");
61 EIMSK = (1 << INT0); /* enable ps/2 clock interrupt */
63 for(;;) {
64 unsigned char c = ps2read();
65 switch(c) {
66 case 0xe0: /* extended */
67 keyflags |= KF_EXT;
68 break;
70 case 0xe1: /* extended */
71 keyflags |= KF_EXT1;
72 break;
74 case 0xf0: /* break code */
75 keyflags |= KF_BRK;
76 break;
78 default:
79 keycode = 0;
80 if(keyflags & KF_EXT) {
81 printf("ext ");
82 if(c < KEYMAP_EXT_SIZE) {
83 keycode = keymap_ext[(int)c];
84 }
85 } else if(keyflags & KF_EXT1) {
86 printf("ext1 ");
87 } else {
88 if(c < KEYMAP_NORMAL_SIZE) {
89 keycode = keymap_normal[(int)c];
90 }
91 }
93 if(keycode >= 256) {
94 /*printf("%s: %s (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", skeystr[keycode - 256], (unsigned int)c);*/
95 printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c);
96 } else if(isprint(keycode)) {
97 printf("%s: %c (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", (char)keycode, (unsigned int)c);
98 } else if(keycode > 0) {
99 printf("%s: key %xh (scancode: %x)\r\n", keyflags & KF_BRK ? "release" : "press", keycode, (unsigned int)c);
100 } else {
101 printf("%s: %x\r\n", keyflags & KF_BRK ? "release" : "press", (unsigned int)c);
102 }
103 keyflags = 0;
104 }
105 }
106 return 0;
107 }
109 void ps2write(unsigned char c)
110 {
111 int i;
112 unsigned short out = (unsigned short)c | ((unsigned short)(parity_even_bit(c) & 1) << 8);
114 /* pull clock low for >60us */
115 PS2LOW(BIT_CLK);
116 _delay_us(60);
118 /* then pull data low and release clock */
119 PS2LOW(BIT_DATA);
120 PS2REL(BIT_CLK);
122 for(i=0; i<9; i++) {
123 while(PINB & BIT_CLK); /* wait for kbd to drive the clock low */
124 PORTB |= out & 1;
125 out >>= 1;
126 while(!(PINB & BIT_CLK)); /* wait for kbd to drive the clock high */
127 }
129 PS2REL(BIT_DATA);
130 /* wait for ack */
131 while(PINB & BIT_DATA);
132 while(!(PINB & BIT_DATA));
133 }
135 unsigned char ps2read(void)
136 {
137 unsigned char key;
139 while(key_rd == key_wr) {
140 }
142 cli();
143 key = keybuf[key_rd];
144 key_rd = NEXT_IDX(key_rd);
145 sei();
147 return key;
148 }
150 int ps2pending(void)
151 {
152 return key_rd != key_wr;
153 }
155 ISR(INT0_vect)
156 {
157 static unsigned char value, valp, parity;
158 static int nbits;
160 if(sending) {
161 } else {
162 if(nbits > 0 && nbits < 9) {
163 value >>= 1;
164 if(PINB & 1) {
165 value |= 0x80;
166 parity ^= 1;
167 }
168 }/* else if(nbits == 9) {
169 valp = PINB & 1;
170 }*/
171 if(++nbits >= 11) {
172 nbits = 0;
174 /* check parity */
175 /*if((parity & 1) == (valp & 1)) {}*/
176 keybuf[key_wr] = (unsigned char)value;
177 key_wr = NEXT_IDX(key_wr);
179 value = 0;
180 parity = 0;
181 }
182 }
183 }