diff options
Diffstat (limited to 'protocol/ps2.c')
| -rw-r--r-- | protocol/ps2.c | 59 |
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 | /* |
| 2 | Copyright 2010,2011 Jun WAKO <wakojun@gmail.com> | 2 | Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com> |
| 3 | 3 | ||
| 4 | This software is licensed with a Modified BSD License. | 4 | This software is licensed with a Modified BSD License. |
| 5 | All of this is supposed to be Free Software, Open Source, DFSG-free, | 5 | All 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 | ||
| 46 | static uint8_t recv_data(void); | 47 | static uint8_t recv_data(void); |
| 48 | #endif | ||
| 47 | static inline void clock_lo(void); | 49 | static inline void clock_lo(void); |
| 48 | static inline void clock_hi(void); | 50 | static inline void clock_hi(void); |
| 49 | static inline bool clock_in(void); | 51 | static 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(); |
| 147 | ERROR: | 152 | ERROR: |
| 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 */ |
| 158 | uint8_t ps2_host_recv_response(void) | 164 | uint8_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 |
| 178 | uint8_t ps2_host_recv(void) | 188 | uint8_t ps2_host_recv(void) |
| @@ -187,9 +197,6 @@ static uint8_t pbuf_head = 0; | |||
| 187 | static uint8_t pbuf_tail = 0; | 197 | static uint8_t pbuf_tail = 0; |
| 188 | static inline void pbuf_enqueue(uint8_t data) | 198 | static 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 | } |
| 225 | static 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 | } | ||
| 233 | static 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 */ |
| 220 | uint8_t ps2_host_recv(void) | 242 | uint8_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 | 254 | uint8_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 | ||
| 239 | ISR(PS2_INT_VECT) | 260 | ISR(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; |
| 298 | ERROR: | 319 | ERROR: |
| 299 | DEBUGP(0x0F); | ||
| 300 | inhibit(); | 320 | inhibit(); |
| 301 | ps2_error = state; | 321 | ps2_error = state; |
| 302 | DONE: | 322 | DONE: |
| @@ -309,11 +329,6 @@ RETURN: | |||
| 309 | #endif | 329 | #endif |
| 310 | 330 | ||
| 311 | 331 | ||
| 312 | static void ps2_reset(void) | ||
| 313 | { | ||
| 314 | ps2_host_send(0xFF); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* send LED state to keyboard */ | 332 | /* send LED state to keyboard */ |
| 318 | void ps2_host_set_led(uint8_t led) | 333 | void 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 */ |
| 326 | static uint8_t recv_data(void) | 342 | static uint8_t recv_data(void) |
| 327 | { | 343 | { |
| @@ -361,6 +377,7 @@ static uint8_t recv_data(void) | |||
| 361 | ERROR: | 377 | ERROR: |
| 362 | return 0; | 378 | return 0; |
| 363 | } | 379 | } |
| 380 | #endif | ||
| 364 | 381 | ||
| 365 | static inline void clock_lo() | 382 | static inline void clock_lo() |
| 366 | { | 383 | { |
