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