aboutsummaryrefslogtreecommitdiff
path: root/protocol/ps2.c
diff options
context:
space:
mode:
Diffstat (limited to 'protocol/ps2.c')
-rw-r--r--protocol/ps2.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/protocol/ps2.c b/protocol/ps2.c
index ed4560910..e5873a9bf 100644
--- a/protocol/ps2.c
+++ b/protocol/ps2.c
@@ -1,5 +1,5 @@
1/* 1/*
2Copyright 2010,2011 Jun WAKO <wakojun@gmail.com> 2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3 3
4This software is licensed with a Modified BSD License. 4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free, 5All of this is supposed to be Free Software, Open Source, DFSG-free,
@@ -43,7 +43,9 @@ POSSIBILITY OF SUCH DAMAGE.
43#include "debug.h" 43#include "debug.h"
44 44
45 45
46#ifndef PS2_USE_INT
46static uint8_t recv_data(void); 47static uint8_t recv_data(void);
48#endif
47static inline void clock_lo(void); 49static inline void clock_lo(void);
48static inline void clock_hi(void); 50static inline void clock_hi(void);
49static inline bool clock_in(void); 51static inline bool clock_in(void);
@@ -109,12 +111,12 @@ uint8_t ps2_host_send(uint8_t data)
109#endif 111#endif
110 /* terminate a transmission if we have */ 112 /* terminate a transmission if we have */
111 inhibit(); 113 inhibit();
112 _delay_us(100); 114 _delay_us(200); // at least 100us
113 115
114 /* start bit [1] */ 116 /* start bit [1] */
115 data_lo(); 117 data_lo();
116 clock_hi(); 118 clock_hi();
117 WAIT(clock_lo, 15000, 1); 119 WAIT(clock_lo, 20000, 10); // may take 15ms at most until device starts clocking
118 /* data [2-9] */ 120 /* data [2-9] */
119 for (uint8_t i = 0; i < 8; i++) { 121 for (uint8_t i = 0; i < 8; i++) {
120 _delay_us(15); 122 _delay_us(15);
@@ -143,6 +145,9 @@ uint8_t ps2_host_send(uint8_t data)
143 WAIT(clock_hi, 50, 8); 145 WAIT(clock_hi, 50, 8);
144 WAIT(data_hi, 50, 9); 146 WAIT(data_hi, 50, 9);
145 147
148#ifdef PS2_USE_INT
149 PS2_INT_ON();
150#endif
146 res = ps2_host_recv_response(); 151 res = ps2_host_recv_response();
147ERROR: 152ERROR:
148#ifdef PS2_USE_INT 153#ifdef PS2_USE_INT
@@ -154,11 +159,15 @@ ERROR:
154 return res; 159 return res;
155} 160}
156 161
162#ifndef PS2_USE_INT
157/* receive data when host want else inhibit communication */ 163/* receive data when host want else inhibit communication */
158uint8_t ps2_host_recv_response(void) 164uint8_t ps2_host_recv_response(void)
159{ 165{
160 uint8_t data = 0; 166 uint8_t data = 0;
161 167
168#ifdef PS2_USE_INT
169 PS2_INT_OFF();
170#endif
162 /* terminate a transmission if we have */ 171 /* terminate a transmission if we have */
163 inhibit(); 172 inhibit();
164 _delay_us(100); 173 _delay_us(100);
@@ -167,12 +176,13 @@ uint8_t ps2_host_recv_response(void)
167 idle(); 176 idle();
168 177
169 /* wait start bit */ 178 /* wait start bit */
170 wait_clock_lo(2000); 179 wait_clock_lo(25000); // command response may take 20 ms at most
171 data = recv_data(); 180 data = recv_data();
172 181
173 inhibit(); 182 inhibit();
174 return data; 183 return data;
175} 184}
185#endif
176 186
177#ifndef PS2_USE_INT 187#ifndef PS2_USE_INT
178uint8_t ps2_host_recv(void) 188uint8_t ps2_host_recv(void)
@@ -187,9 +197,6 @@ static uint8_t pbuf_head = 0;
187static uint8_t pbuf_tail = 0; 197static uint8_t pbuf_tail = 0;
188static inline void pbuf_enqueue(uint8_t data) 198static inline void pbuf_enqueue(uint8_t data)
189{ 199{
190 if (!data)
191 return;
192
193 uint8_t sreg = SREG; 200 uint8_t sreg = SREG;
194 cli(); 201 cli();
195 uint8_t next = (pbuf_head + 1) % PBUF_SIZE; 202 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
@@ -215,6 +222,21 @@ static inline uint8_t pbuf_dequeue(void)
215 222
216 return val; 223 return val;
217} 224}
225static inline bool pbuf_has_data(void)
226{
227 uint8_t sreg = SREG;
228 cli();
229 bool has_data = (pbuf_head != pbuf_tail);
230 SREG = sreg;
231 return has_data;
232}
233static inline void pbuf_clear(void)
234{
235 uint8_t sreg = SREG;
236 cli();
237 pbuf_head = pbuf_tail = 0;
238 SREG = sreg;
239}
218 240
219/* get data received by interrupt */ 241/* get data received by interrupt */
220uint8_t ps2_host_recv(void) 242uint8_t ps2_host_recv(void)
@@ -229,13 +251,12 @@ uint8_t ps2_host_recv(void)
229 return pbuf_dequeue(); 251 return pbuf_dequeue();
230} 252}
231 253
232#if 0 254uint8_t ps2_host_recv_response(void)
233#define DEBUGP_INIT() do { DDRC = 0xFF; } while (0) 255{
234#define DEBUGP(x) do { PORTC = x; } while (0) 256 while (!pbuf_has_data()) ;
235#else 257 return pbuf_dequeue();
236#define DEBUGP_INIT() 258}
237#define DEBUGP(x) 259
238#endif
239ISR(PS2_INT_VECT) 260ISR(PS2_INT_VECT)
240{ 261{
241 static enum { 262 static enum {
@@ -256,7 +277,6 @@ ISR(PS2_INT_VECT)
256 } 277 }
257 278
258 state++; 279 state++;
259 DEBUGP(state);
260 switch (state) { 280 switch (state) {
261 case START: 281 case START:
262 if (data_in()) 282 if (data_in())
@@ -289,6 +309,7 @@ ISR(PS2_INT_VECT)
289 if (!data_in()) 309 if (!data_in())
290 goto ERROR; 310 goto ERROR;
291 pbuf_enqueue(data); 311 pbuf_enqueue(data);
312//phex(data);
292 goto DONE; 313 goto DONE;
293 break; 314 break;
294 default: 315 default:
@@ -296,7 +317,6 @@ ISR(PS2_INT_VECT)
296 } 317 }
297 goto RETURN; 318 goto RETURN;
298ERROR: 319ERROR:
299 DEBUGP(0x0F);
300 inhibit(); 320 inhibit();
301 ps2_error = state; 321 ps2_error = state;
302DONE: 322DONE:
@@ -309,11 +329,6 @@ RETURN:
309#endif 329#endif
310 330
311 331
312static void ps2_reset(void)
313{
314 ps2_host_send(0xFF);
315}
316
317/* send LED state to keyboard */ 332/* send LED state to keyboard */
318void ps2_host_set_led(uint8_t led) 333void ps2_host_set_led(uint8_t led)
319{ 334{
@@ -322,6 +337,7 @@ void ps2_host_set_led(uint8_t led)
322} 337}
323 338
324 339
340#ifndef PS2_USE_INT
325/* called after start bit comes */ 341/* called after start bit comes */
326static uint8_t recv_data(void) 342static uint8_t recv_data(void)
327{ 343{
@@ -361,6 +377,7 @@ static uint8_t recv_data(void)
361ERROR: 377ERROR:
362 return 0; 378 return 0;
363} 379}
380#endif
364 381
365static inline void clock_lo() 382static inline void clock_lo()
366{ 383{