aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortmk <nobody@nowhere>2013-11-28 14:20:00 +0900
committertmk <nobody@nowhere>2013-11-28 14:20:00 +0900
commit4eb27ee89038e934dcb498df7508199efd9c93f1 (patch)
tree48da6b3a1e09d4ecbcab7c7b32977ae561a3bd6f
parent532e100450615ef1e63e2eed548c38d0c4fa688b (diff)
downloadqmk_firmware-4eb27ee89038e934dcb498df7508199efd9c93f1.tar.gz
qmk_firmware-4eb27ee89038e934dcb498df7508199efd9c93f1.zip
Add ps2_interrupt.c
-rw-r--r--protocol.mk2
-rw-r--r--protocol/ps2_busywait.c51
-rw-r--r--protocol/ps2_interrupt.c (renamed from protocol/ps2.c)354
-rw-r--r--protocol/ps2_usart.c23
4 files changed, 122 insertions, 308 deletions
diff --git a/protocol.mk b/protocol.mk
index e33200873..7f561e62d 100644
--- a/protocol.mk
+++ b/protocol.mk
@@ -13,7 +13,7 @@ ifdef PS2_USE_BUSYWAIT
13endif 13endif
14 14
15ifdef PS2_USE_INT 15ifdef PS2_USE_INT
16 SRC += protocol/ps2.c 16 SRC += protocol/ps2_interrupt.c
17 OPT_DEFS += -DPS2_USE_INT 17 OPT_DEFS += -DPS2_USE_INT
18endif 18endif
19 19
diff --git a/protocol/ps2_busywait.c b/protocol/ps2_busywait.c
index 5ab377877..05dd7b27e 100644
--- a/protocol/ps2_busywait.c
+++ b/protocol/ps2_busywait.c
@@ -35,16 +35,16 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE. 35POSSIBILITY OF SUCH DAMAGE.
36*/ 36*/
37 37
38/*
39 * PS/2 protocol busywait version
40 */
41
38#include <stdbool.h> 42#include <stdbool.h>
39#include <util/delay.h> 43#include <util/delay.h>
40#include "ps2.h" 44#include "ps2.h"
41#include "debug.h" 45#include "debug.h"
42 46
43 47
44/*
45 * PS/2 protocol busywait version
46 */
47
48#define WAIT(stat, us, err) do { \ 48#define WAIT(stat, us, err) do { \
49 if (!wait_##stat(us)) { \ 49 if (!wait_##stat(us)) { \
50 ps2_error = err; \ 50 ps2_error = err; \
@@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE.
52 } \ 52 } \
53} while (0) 53} while (0)
54 54
55
55uint8_t ps2_error = PS2_ERR_NONE; 56uint8_t ps2_error = PS2_ERR_NONE;
56 57
57 58
@@ -65,18 +66,19 @@ void ps2_host_init(void)
65 66
66uint8_t ps2_host_send(uint8_t data) 67uint8_t ps2_host_send(uint8_t data)
67{ 68{
68 uint8_t res = 0;
69 bool parity = true; 69 bool parity = true;
70 ps2_error = PS2_ERR_NONE; 70 ps2_error = PS2_ERR_NONE;
71
71 /* terminate a transmission if we have */ 72 /* terminate a transmission if we have */
72 inhibit(); 73 inhibit();
73 _delay_us(200); // at least 100us 74 _delay_us(100); // 100us [4]p.13, [5]p.50
74 75
75 /* start bit [1] */ 76 /* 'Request to Send' and Start bit */
76 data_lo(); 77 data_lo();
77 clock_hi(); 78 clock_hi();
78 WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking 79 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
79 /* data [2-9] */ 80
81 /* Data bit */
80 for (uint8_t i = 0; i < 8; i++) { 82 for (uint8_t i = 0; i < 8; i++) {
81 _delay_us(15); 83 _delay_us(15);
82 if (data&(1<<i)) { 84 if (data&(1<<i)) {
@@ -88,15 +90,18 @@ uint8_t ps2_host_send(uint8_t data)
88 WAIT(clock_hi, 50, 2); 90 WAIT(clock_hi, 50, 2);
89 WAIT(clock_lo, 50, 3); 91 WAIT(clock_lo, 50, 3);
90 } 92 }
91 /* parity [10] */ 93
94 /* Parity bit */
92 _delay_us(15); 95 _delay_us(15);
93 if (parity) { data_hi(); } else { data_lo(); } 96 if (parity) { data_hi(); } else { data_lo(); }
94 WAIT(clock_hi, 50, 4); 97 WAIT(clock_hi, 50, 4);
95 WAIT(clock_lo, 50, 5); 98 WAIT(clock_lo, 50, 5);
96 /* stop bit [11] */ 99
100 /* Stop bit */
97 _delay_us(15); 101 _delay_us(15);
98 data_hi(); 102 data_hi();
99 /* ack [12] */ 103
104 /* Ack */
100 WAIT(data_lo, 50, 6); 105 WAIT(data_lo, 50, 6);
101 WAIT(clock_lo, 50, 7); 106 WAIT(clock_lo, 50, 7);
102 107
@@ -105,17 +110,16 @@ uint8_t ps2_host_send(uint8_t data)
105 WAIT(data_hi, 50, 9); 110 WAIT(data_hi, 50, 9);
106 111
107 inhibit(); 112 inhibit();
108 res = ps2_host_recv_response(); 113 return ps2_host_recv_response();
109ERROR: 114ERROR:
110 inhibit(); 115 inhibit();
111 return res; 116 return 0;
112} 117}
113 118
114/* receive data when host want else inhibit communication */ 119/* receive data when host want else inhibit communication */
115uint8_t ps2_host_recv_response(void) 120uint8_t ps2_host_recv_response(void)
116{ 121{
117 // Command might take 20ms to response([3]p.21) 122 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
118 // TrackPoint might take 25ms ([5]2.7)
119 // 250 * 100us(wait for start bit in ps2_host_recv) 123 // 250 * 100us(wait for start bit in ps2_host_recv)
120 uint8_t data = 0; 124 uint8_t data = 0;
121 uint8_t try = 250; 125 uint8_t try = 250;
@@ -125,14 +129,6 @@ uint8_t ps2_host_recv_response(void)
125 return data; 129 return data;
126} 130}
127 131
128/* send LED state to keyboard */
129void ps2_host_set_led(uint8_t led)
130{
131 ps2_host_send(0xED);
132 ps2_host_send(led);
133}
134
135
136/* called after start bit comes */ 132/* called after start bit comes */
137uint8_t ps2_host_recv(void) 133uint8_t ps2_host_recv(void)
138{ 134{
@@ -180,3 +176,10 @@ ERROR:
180 inhibit(); 176 inhibit();
181 return 0; 177 return 0;
182} 178}
179
180/* send LED state to keyboard */
181void ps2_host_set_led(uint8_t led)
182{
183 ps2_host_send(0xED);
184 ps2_host_send(led);
185}
diff --git a/protocol/ps2.c b/protocol/ps2_interrupt.c
index 4886b16d0..355d4e825 100644
--- a/protocol/ps2.c
+++ b/protocol/ps2_interrupt.c
@@ -35,49 +35,16 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE. 35POSSIBILITY OF SUCH DAMAGE.
36*/ 36*/
37 37
38/*
39 * PS/2 protocol Pin interrupt version
40 */
41
38#include <stdbool.h> 42#include <stdbool.h>
39#include <avr/io.h>
40#include <avr/interrupt.h>
41#include <util/delay.h> 43#include <util/delay.h>
42#include "ps2.h" 44#include "ps2.h"
43#include "debug.h" 45#include "debug.h"
44 46
45 47
46#ifndef PS2_USE_INT
47static uint8_t recv_data(void);
48#endif
49static inline void clock_lo(void);
50static inline void clock_hi(void);
51static inline bool clock_in(void);
52static inline void data_lo(void);
53static inline void data_hi(void);
54static inline bool data_in(void);
55static inline uint16_t wait_clock_lo(uint16_t us);
56static inline uint16_t wait_clock_hi(uint16_t us);
57static inline uint16_t wait_data_lo(uint16_t us);
58static inline uint16_t wait_data_hi(uint16_t us);
59static inline void idle(void);
60static inline void inhibit(void);
61
62
63/*
64Primitive PS/2 Library for AVR
65==============================
66Host side is only supported now.
67
68
69I/O control
70-----------
71High state is asserted by input with pull up.
72
73
74PS/2 References
75---------------
76http://www.computer-engineering.org/ps2protocol/
77http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
78*/
79
80
81#define WAIT(stat, us, err) do { \ 48#define WAIT(stat, us, err) do { \
82 if (!wait_##stat(us)) { \ 49 if (!wait_##stat(us)) { \
83 ps2_error = err; \ 50 ps2_error = err; \
@@ -89,38 +56,38 @@ http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
89uint8_t ps2_error = PS2_ERR_NONE; 56uint8_t ps2_error = PS2_ERR_NONE;
90 57
91 58
59static inline uint8_t pbuf_dequeue(void);
60static inline void pbuf_enqueue(uint8_t data);
61static inline bool pbuf_has_data(void);
62static inline void pbuf_clear(void);
63
64
92void ps2_host_init(void) 65void ps2_host_init(void)
93{ 66{
94 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) 67 idle();
95 _delay_ms(2500);
96
97#ifdef PS2_USE_INT
98 PS2_INT_INIT(); 68 PS2_INT_INIT();
99 PS2_INT_ON(); 69 PS2_INT_ON();
100 idle(); 70 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
101#else 71 //_delay_ms(2500);
102 inhibit();
103#endif
104} 72}
105 73
106// TODO: send using interrupt if available
107uint8_t ps2_host_send(uint8_t data) 74uint8_t ps2_host_send(uint8_t data)
108{ 75{
109 uint8_t res = 0;
110 bool parity = true; 76 bool parity = true;
111 ps2_error = PS2_ERR_NONE; 77 ps2_error = PS2_ERR_NONE;
112#ifdef PS2_USE_INT 78
113 PS2_INT_OFF(); 79 PS2_INT_OFF();
114#endif 80
115 /* terminate a transmission if we have */ 81 /* terminate a transmission if we have */
116 inhibit(); 82 inhibit();
117 _delay_us(200); // at least 100us 83 _delay_us(100); // 100us [4]p.13, [5]p.50
118 84
119 /* start bit [1] */ 85 /* 'Request to Send' and Start bit */
120 data_lo(); 86 data_lo();
121 clock_hi(); 87 clock_hi();
122 WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking 88 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
123 /* data [2-9] */ 89
90 /* Data bit[2-9] */
124 for (uint8_t i = 0; i < 8; i++) { 91 for (uint8_t i = 0; i < 8; i++) {
125 _delay_us(15); 92 _delay_us(15);
126 if (data&(1<<i)) { 93 if (data&(1<<i)) {
@@ -132,15 +99,18 @@ uint8_t ps2_host_send(uint8_t data)
132 WAIT(clock_hi, 50, 2); 99 WAIT(clock_hi, 50, 2);
133 WAIT(clock_lo, 50, 3); 100 WAIT(clock_lo, 50, 3);
134 } 101 }
135 /* parity [10] */ 102
103 /* Parity bit */
136 _delay_us(15); 104 _delay_us(15);
137 if (parity) { data_hi(); } else { data_lo(); } 105 if (parity) { data_hi(); } else { data_lo(); }
138 WAIT(clock_hi, 50, 4); 106 WAIT(clock_hi, 50, 4);
139 WAIT(clock_lo, 50, 5); 107 WAIT(clock_lo, 50, 5);
140 /* stop bit [11] */ 108
109 /* Stop bit */
141 _delay_us(15); 110 _delay_us(15);
142 data_hi(); 111 data_hi();
143 /* ack [12] */ 112
113 /* Ack */
144 WAIT(data_lo, 50, 6); 114 WAIT(data_lo, 50, 6);
145 WAIT(clock_lo, 50, 7); 115 WAIT(clock_lo, 50, 7);
146 116
@@ -148,107 +118,35 @@ uint8_t ps2_host_send(uint8_t data)
148 WAIT(clock_hi, 50, 8); 118 WAIT(clock_hi, 50, 8);
149 WAIT(data_hi, 50, 9); 119 WAIT(data_hi, 50, 9);
150 120
151#ifdef PS2_USE_INT 121 idle();
152 PS2_INT_ON(); 122 PS2_INT_ON();
153#endif 123 return ps2_host_recv_response();
154 res = ps2_host_recv_response();
155ERROR: 124ERROR:
156#ifdef PS2_USE_INT
157 PS2_INT_ON();
158 idle(); 125 idle();
159#else 126 PS2_INT_ON();
160 inhibit(); 127 return 0;
161#endif
162 return res;
163} 128}
164 129
165#ifndef PS2_USE_INT
166/* receive data when host want else inhibit communication */
167uint8_t ps2_host_recv_response(void) 130uint8_t ps2_host_recv_response(void)
168{ 131{
169 // Command might take 20ms to response([3]p.21) 132 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
170 // TrackPoint might take 25ms ([5]2.7) 133 uint8_t retry = 25;
171 uint8_t data = 0; 134 while (retry-- && !pbuf_has_data()) {
172 uint8_t try = 200; 135 _delay_ms(1);
173 while (try-- && (data = ps2_host_recv())) ;
174 return data;
175}
176#endif
177
178#ifndef PS2_USE_INT
179uint8_t ps2_host_recv(void)
180{
181 uint8_t data = 0;
182
183 /* release lines(idle state) */
184 idle();
185
186 /* wait start bit */
187 wait_clock_lo(100); // TODO: this is enough?
188 data = recv_data();
189
190 inhibit();
191 return data;
192}
193#else
194/* ring buffer to store ps/2 key data */
195#define PBUF_SIZE 32
196static uint8_t pbuf[PBUF_SIZE];
197static uint8_t pbuf_head = 0;
198static uint8_t pbuf_tail = 0;
199static inline void pbuf_enqueue(uint8_t data)
200{
201 uint8_t sreg = SREG;
202 cli();
203 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
204 if (next != pbuf_tail) {
205 pbuf[pbuf_head] = data;
206 pbuf_head = next;
207 } else {
208 debug("pbuf: full\n");
209 } 136 }
210 SREG = sreg; 137 return pbuf_dequeue();
211}
212static inline uint8_t pbuf_dequeue(void)
213{
214 uint8_t val = 0;
215
216 uint8_t sreg = SREG;
217 cli();
218 if (pbuf_head != pbuf_tail) {
219 val = pbuf[pbuf_tail];
220 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
221 }
222 SREG = sreg;
223
224 return val;
225}
226static inline bool pbuf_has_data(void)
227{
228 uint8_t sreg = SREG;
229 cli();
230 bool has_data = (pbuf_head != pbuf_tail);
231 SREG = sreg;
232 return has_data;
233}
234static inline void pbuf_clear(void)
235{
236 uint8_t sreg = SREG;
237 cli();
238 pbuf_head = pbuf_tail = 0;
239 SREG = sreg;
240} 138}
241 139
242/* get data received by interrupt */ 140/* get data received by interrupt */
243uint8_t ps2_host_recv(void) 141uint8_t ps2_host_recv(void)
244{ 142{
245 return pbuf_dequeue(); 143 if (pbuf_has_data()) {
246} 144 ps2_error = PS2_ERR_NONE;
247 145 return pbuf_dequeue();
248uint8_t ps2_host_recv_response(void) 146 } else {
249{ 147 ps2_error = PS2_ERR_NODATA;
250 while (!pbuf_has_data()) ; 148 return 0;
251 return pbuf_dequeue(); 149 }
252} 150}
253 151
254ISR(PS2_INT_VECT) 152ISR(PS2_INT_VECT)
@@ -303,7 +201,6 @@ ISR(PS2_INT_VECT)
303 if (!data_in()) 201 if (!data_in())
304 goto ERROR; 202 goto ERROR;
305 pbuf_enqueue(data); 203 pbuf_enqueue(data);
306//phex(data);
307 goto DONE; 204 goto DONE;
308 break; 205 break;
309 default: 206 default:
@@ -311,7 +208,6 @@ ISR(PS2_INT_VECT)
311 } 208 }
312 goto RETURN; 209 goto RETURN;
313ERROR: 210ERROR:
314 inhibit();
315 ps2_error = state; 211 ps2_error = state;
316DONE: 212DONE:
317 state = INIT; 213 state = INIT;
@@ -320,8 +216,6 @@ DONE:
320RETURN: 216RETURN:
321 return; 217 return;
322} 218}
323#endif
324
325 219
326/* send LED state to keyboard */ 220/* send LED state to keyboard */
327void ps2_host_set_led(uint8_t led) 221void ps2_host_set_led(uint8_t led)
@@ -331,139 +225,53 @@ void ps2_host_set_led(uint8_t led)
331} 225}
332 226
333 227
334#ifndef PS2_USE_INT 228/*--------------------------------------------------------------------
335/* called after start bit comes */ 229 * Ring buffer to store scan codes from keyboard
336static uint8_t recv_data(void) 230 *------------------------------------------------------------------*/
231#define PBUF_SIZE 32
232static uint8_t pbuf[PBUF_SIZE];
233static uint8_t pbuf_head = 0;
234static uint8_t pbuf_tail = 0;
235static inline void pbuf_enqueue(uint8_t data)
337{ 236{
338 uint8_t data = 0; 237 uint8_t sreg = SREG;
339 bool parity = true; 238 cli();
340 ps2_error = PS2_ERR_NONE; 239 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
341 240 if (next != pbuf_tail) {
342 /* start bit [1] */ 241 pbuf[pbuf_head] = data;
343 WAIT(clock_lo, 1, 1); 242 pbuf_head = next;
344 WAIT(data_lo, 1, 2); 243 } else {
345 WAIT(clock_hi, 50, 3); 244 debug("pbuf: full\n");
346
347 /* data [2-9] */
348 for (uint8_t i = 0; i < 8; i++) {
349 WAIT(clock_lo, 50, 4);
350 if (data_in()) {
351 parity = !parity;
352 data |= (1<<i);
353 }
354 WAIT(clock_hi, 50, 5);
355 }
356
357 /* parity [10] */
358 WAIT(clock_lo, 50, 6);
359 if (data_in() != parity) {
360 ps2_error = PS2_ERR_PARITY;
361 goto ERROR;
362 } 245 }
363 WAIT(clock_hi, 50, 7); 246 SREG = sreg;
364
365 /* stop bit [11] */
366 WAIT(clock_lo, 50, 8);
367 WAIT(data_hi, 1, 9);
368 WAIT(clock_hi, 50, 10);
369
370 return data;
371ERROR:
372 return 0;
373}
374#endif
375
376static inline void clock_lo()
377{
378 PS2_CLOCK_PORT &= ~(1<<PS2_CLOCK_BIT);
379 PS2_CLOCK_DDR |= (1<<PS2_CLOCK_BIT);
380}
381static inline void clock_hi()
382{
383 /* input with pull up */
384 PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
385 PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
386}
387static inline bool clock_in()
388{
389 PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT);
390 PS2_CLOCK_PORT |= (1<<PS2_CLOCK_BIT);
391 _delay_us(1);
392 return PS2_CLOCK_PIN&(1<<PS2_CLOCK_BIT);
393}
394static inline void data_lo()
395{
396 PS2_DATA_PORT &= ~(1<<PS2_DATA_BIT);
397 PS2_DATA_DDR |= (1<<PS2_DATA_BIT);
398}
399static inline void data_hi()
400{
401 /* input with pull up */
402 PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT);
403 PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
404} 247}
405static inline bool data_in() 248static inline uint8_t pbuf_dequeue(void)
406{ 249{
407 PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); 250 uint8_t val = 0;
408 PS2_DATA_PORT |= (1<<PS2_DATA_BIT);
409 _delay_us(1);
410 return PS2_DATA_PIN&(1<<PS2_DATA_BIT);
411}
412 251
413static inline uint16_t wait_clock_lo(uint16_t us) 252 uint8_t sreg = SREG;
414{ 253 cli();
415 while (clock_in() && us) { asm(""); _delay_us(1); us--; } 254 if (pbuf_head != pbuf_tail) {
416 return us; 255 val = pbuf[pbuf_tail];
417} 256 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
418static inline uint16_t wait_clock_hi(uint16_t us) 257 }
419{ 258 SREG = sreg;
420 while (!clock_in() && us) { asm(""); _delay_us(1); us--; }
421 return us;
422}
423static inline uint16_t wait_data_lo(uint16_t us)
424{
425 while (data_in() && us) { asm(""); _delay_us(1); us--; }
426 return us;
427}
428static inline uint16_t wait_data_hi(uint16_t us)
429{
430 while (!data_in() && us) { asm(""); _delay_us(1); us--; }
431 return us;
432}
433 259
434/* idle state that device can send */ 260 return val;
435static inline void idle(void) 261}
262static inline bool pbuf_has_data(void)
436{ 263{
437 clock_hi(); 264 uint8_t sreg = SREG;
438 data_hi(); 265 cli();
266 bool has_data = (pbuf_head != pbuf_tail);
267 SREG = sreg;
268 return has_data;
439} 269}
440 270static inline void pbuf_clear(void)
441/* inhibit device to send */
442static inline void inhibit(void)
443{ 271{
444 clock_lo(); 272 uint8_t sreg = SREG;
445 data_hi(); 273 cli();
274 pbuf_head = pbuf_tail = 0;
275 SREG = sreg;
446} 276}
447 277
448
449/* PS/2 Resources
450 *
451 * [1] The PS/2 Mouse/Keyboard Protocol
452 * http://www.computer-engineering.org/ps2protocol/
453 * Concise and thorough primer of PS/2 protocol.
454 *
455 * [2] Keyboard and Auxiliary Device Controller
456 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
457 * Signal Timing and Format
458 *
459 * [3] Keyboards(101- and 102-key)
460 * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
461 * Keyboard Layout, Scan Code Set, POR, and Commands.
462 *
463 * [4] PS/2 Reference Manuals
464 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
465 * Collection of IBM Personal System/2 documents.
466 *
467 * [5] TrackPoint Engineering Specifications for version 3E
468 * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
469 */
diff --git a/protocol/ps2_usart.c b/protocol/ps2_usart.c
index d49114286..27947143e 100644
--- a/protocol/ps2_usart.c
+++ b/protocol/ps2_usart.c
@@ -82,13 +82,14 @@ uint8_t ps2_host_send(uint8_t data)
82 82
83 /* terminate a transmission if we have */ 83 /* terminate a transmission if we have */
84 inhibit(); 84 inhibit();
85 _delay_us(100); 85 _delay_us(100); // [4]p.13
86 86
87 /* start bit [1] */ 87 /* 'Request to Send' and Start bit */
88 data_lo(); 88 data_lo();
89 clock_hi(); 89 clock_hi();
90 WAIT(clock_lo, 15000, 1); 90 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
91 /* data [2-9] */ 91
92 /* Data bit[2-9] */
92 for (uint8_t i = 0; i < 8; i++) { 93 for (uint8_t i = 0; i < 8; i++) {
93 _delay_us(15); 94 _delay_us(15);
94 if (data&(1<<i)) { 95 if (data&(1<<i)) {
@@ -100,15 +101,18 @@ uint8_t ps2_host_send(uint8_t data)
100 WAIT(clock_hi, 50, 2); 101 WAIT(clock_hi, 50, 2);
101 WAIT(clock_lo, 50, 3); 102 WAIT(clock_lo, 50, 3);
102 } 103 }
103 /* parity [10] */ 104
105 /* Parity bit */
104 _delay_us(15); 106 _delay_us(15);
105 if (parity) { data_hi(); } else { data_lo(); } 107 if (parity) { data_hi(); } else { data_lo(); }
106 WAIT(clock_hi, 50, 4); 108 WAIT(clock_hi, 50, 4);
107 WAIT(clock_lo, 50, 5); 109 WAIT(clock_lo, 50, 5);
108 /* stop bit [11] */ 110
111 /* Stop bit */
109 _delay_us(15); 112 _delay_us(15);
110 data_hi(); 113 data_hi();
111 /* ack [12] */ 114
115 /* Ack */
112 WAIT(data_lo, 50, 6); 116 WAIT(data_lo, 50, 6);
113 WAIT(clock_lo, 50, 7); 117 WAIT(clock_lo, 50, 7);
114 118
@@ -127,12 +131,12 @@ ERROR:
127 return 0; 131 return 0;
128} 132}
129 133
130// Do polling data from keyboard to get response to last command.
131uint8_t ps2_host_recv_response(void) 134uint8_t ps2_host_recv_response(void)
132{ 135{
136 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
133 uint8_t retry = 25; 137 uint8_t retry = 25;
134 while (retry-- && !pbuf_has_data()) { 138 while (retry-- && !pbuf_has_data()) {
135 _delay_ms(1); // without this delay it seems to fall into deadlock 139 _delay_ms(1);
136 } 140 }
137 return pbuf_dequeue(); 141 return pbuf_dequeue();
138} 142}
@@ -188,7 +192,6 @@ static inline void pbuf_enqueue(uint8_t data)
188 } 192 }
189 SREG = sreg; 193 SREG = sreg;
190} 194}
191
192static inline uint8_t pbuf_dequeue(void) 195static inline uint8_t pbuf_dequeue(void)
193{ 196{
194 uint8_t val = 0; 197 uint8_t val = 0;