diff options
Diffstat (limited to 'tmk_core/protocol/ps2_interrupt.c')
-rw-r--r-- | tmk_core/protocol/ps2_interrupt.c | 91 |
1 files changed, 80 insertions, 11 deletions
diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c index 5afc8a82e..780040d15 100644 --- a/tmk_core/protocol/ps2_interrupt.c +++ b/tmk_core/protocol/ps2_interrupt.c | |||
@@ -40,11 +40,19 @@ POSSIBILITY OF SUCH DAMAGE. | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | #include <stdbool.h> | 42 | #include <stdbool.h> |
43 | #include <avr/interrupt.h> | 43 | |
44 | #include <util/delay.h> | 44 | #if defined(__AVR__) |
45 | # include <avr/interrupt.h> | ||
46 | #elif defined(PROTOCOL_CHIBIOS) // TODO: or STM32 ? | ||
47 | // chibiOS headers | ||
48 | # include "ch.h" | ||
49 | # include "hal.h" | ||
50 | #endif | ||
51 | |||
45 | #include "ps2.h" | 52 | #include "ps2.h" |
46 | #include "ps2_io.h" | 53 | #include "ps2_io.h" |
47 | #include "print.h" | 54 | #include "print.h" |
55 | #include "wait.h" | ||
48 | 56 | ||
49 | #define WAIT(stat, us, err) \ | 57 | #define WAIT(stat, us, err) \ |
50 | do { \ | 58 | do { \ |
@@ -61,12 +69,30 @@ static inline void pbuf_enqueue(uint8_t data); | |||
61 | static inline bool pbuf_has_data(void); | 69 | static inline bool pbuf_has_data(void); |
62 | static inline void pbuf_clear(void); | 70 | static inline void pbuf_clear(void); |
63 | 71 | ||
72 | #if defined(PROTOCOL_CHIBIOS) | ||
73 | void ps2_interrupt_service_routine(void); | ||
74 | void palCallback(void *arg) { ps2_interrupt_service_routine(); } | ||
75 | |||
76 | # define PS2_INT_INIT() \ | ||
77 | { palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT); } \ | ||
78 | while (0) | ||
79 | # define PS2_INT_ON() \ | ||
80 | { \ | ||
81 | palEnableLineEvent(PS2_CLOCK, PAL_EVENT_MODE_FALLING_EDGE); \ | ||
82 | palSetLineCallback(PS2_CLOCK, palCallback, NULL); \ | ||
83 | } \ | ||
84 | while (0) | ||
85 | # define PS2_INT_OFF() \ | ||
86 | { palDisableLineEvent(PS2_CLOCK); } \ | ||
87 | while (0) | ||
88 | #endif // PROTOCOL_CHIBIOS | ||
89 | |||
64 | void ps2_host_init(void) { | 90 | void ps2_host_init(void) { |
65 | idle(); | 91 | idle(); |
66 | PS2_INT_INIT(); | 92 | PS2_INT_INIT(); |
67 | PS2_INT_ON(); | 93 | PS2_INT_ON(); |
68 | // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) | 94 | // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20) |
69 | //_delay_ms(2500); | 95 | // wait_ms(2500); |
70 | } | 96 | } |
71 | 97 | ||
72 | uint8_t ps2_host_send(uint8_t data) { | 98 | uint8_t ps2_host_send(uint8_t data) { |
@@ -77,7 +103,7 @@ uint8_t ps2_host_send(uint8_t data) { | |||
77 | 103 | ||
78 | /* terminate a transmission if we have */ | 104 | /* terminate a transmission if we have */ |
79 | inhibit(); | 105 | inhibit(); |
80 | _delay_us(100); // 100us [4]p.13, [5]p.50 | 106 | wait_us(100); // 100us [4]p.13, [5]p.50 |
81 | 107 | ||
82 | /* 'Request to Send' and Start bit */ | 108 | /* 'Request to Send' and Start bit */ |
83 | data_lo(); | 109 | data_lo(); |
@@ -86,7 +112,6 @@ uint8_t ps2_host_send(uint8_t data) { | |||
86 | 112 | ||
87 | /* Data bit[2-9] */ | 113 | /* Data bit[2-9] */ |
88 | for (uint8_t i = 0; i < 8; i++) { | 114 | for (uint8_t i = 0; i < 8; i++) { |
89 | _delay_us(15); | ||
90 | if (data & (1 << i)) { | 115 | if (data & (1 << i)) { |
91 | parity = !parity; | 116 | parity = !parity; |
92 | data_hi(); | 117 | data_hi(); |
@@ -98,7 +123,7 @@ uint8_t ps2_host_send(uint8_t data) { | |||
98 | } | 123 | } |
99 | 124 | ||
100 | /* Parity bit */ | 125 | /* Parity bit */ |
101 | _delay_us(15); | 126 | wait_us(15); |
102 | if (parity) { | 127 | if (parity) { |
103 | data_hi(); | 128 | data_hi(); |
104 | } else { | 129 | } else { |
@@ -108,7 +133,7 @@ uint8_t ps2_host_send(uint8_t data) { | |||
108 | WAIT(clock_lo, 50, 5); | 133 | WAIT(clock_lo, 50, 5); |
109 | 134 | ||
110 | /* Stop bit */ | 135 | /* Stop bit */ |
111 | _delay_us(15); | 136 | wait_us(15); |
112 | data_hi(); | 137 | data_hi(); |
113 | 138 | ||
114 | /* Ack */ | 139 | /* Ack */ |
@@ -132,7 +157,7 @@ uint8_t ps2_host_recv_response(void) { | |||
132 | // Command may take 25ms/20ms at most([5]p.46, [3]p.21) | 157 | // Command may take 25ms/20ms at most([5]p.46, [3]p.21) |
133 | uint8_t retry = 25; | 158 | uint8_t retry = 25; |
134 | while (retry-- && !pbuf_has_data()) { | 159 | while (retry-- && !pbuf_has_data()) { |
135 | _delay_ms(1); | 160 | wait_ms(1); |
136 | } | 161 | } |
137 | return pbuf_dequeue(); | 162 | return pbuf_dequeue(); |
138 | } | 163 | } |
@@ -148,7 +173,7 @@ uint8_t ps2_host_recv(void) { | |||
148 | } | 173 | } |
149 | } | 174 | } |
150 | 175 | ||
151 | ISR(PS2_INT_VECT) { | 176 | void ps2_interrupt_service_routine(void) { |
152 | static enum { | 177 | static enum { |
153 | INIT, | 178 | INIT, |
154 | START, | 179 | START, |
@@ -218,6 +243,10 @@ RETURN: | |||
218 | return; | 243 | return; |
219 | } | 244 | } |
220 | 245 | ||
246 | #if defined(__AVR__) | ||
247 | ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); } | ||
248 | #endif | ||
249 | |||
221 | /* send LED state to keyboard */ | 250 | /* send LED state to keyboard */ |
222 | void ps2_host_set_led(uint8_t led) { | 251 | void ps2_host_set_led(uint8_t led) { |
223 | ps2_host_send(0xED); | 252 | ps2_host_send(0xED); |
@@ -232,8 +261,13 @@ static uint8_t pbuf[PBUF_SIZE]; | |||
232 | static uint8_t pbuf_head = 0; | 261 | static uint8_t pbuf_head = 0; |
233 | static uint8_t pbuf_tail = 0; | 262 | static uint8_t pbuf_tail = 0; |
234 | static inline void pbuf_enqueue(uint8_t data) { | 263 | static inline void pbuf_enqueue(uint8_t data) { |
264 | #if defined(__AVR__) | ||
235 | uint8_t sreg = SREG; | 265 | uint8_t sreg = SREG; |
236 | cli(); | 266 | cli(); |
267 | #elif defined(PROTOCOL_CHIBIOS) | ||
268 | chSysLockFromISR(); | ||
269 | #endif | ||
270 | |||
237 | uint8_t next = (pbuf_head + 1) % PBUF_SIZE; | 271 | uint8_t next = (pbuf_head + 1) % PBUF_SIZE; |
238 | if (next != pbuf_tail) { | 272 | if (next != pbuf_tail) { |
239 | pbuf[pbuf_head] = data; | 273 | pbuf[pbuf_head] = data; |
@@ -241,31 +275,66 @@ static inline void pbuf_enqueue(uint8_t data) { | |||
241 | } else { | 275 | } else { |
242 | print("pbuf: full\n"); | 276 | print("pbuf: full\n"); |
243 | } | 277 | } |
278 | |||
279 | #if defined(__AVR__) | ||
244 | SREG = sreg; | 280 | SREG = sreg; |
281 | #elif defined(PROTOCOL_CHIBIOS) | ||
282 | chSysUnlockFromISR(); | ||
283 | #endif | ||
245 | } | 284 | } |
246 | static inline uint8_t pbuf_dequeue(void) { | 285 | static inline uint8_t pbuf_dequeue(void) { |
247 | uint8_t val = 0; | 286 | uint8_t val = 0; |
248 | 287 | ||
288 | #if defined(__AVR__) | ||
249 | uint8_t sreg = SREG; | 289 | uint8_t sreg = SREG; |
250 | cli(); | 290 | cli(); |
291 | #elif defined(PROTOCOL_CHIBIOS) | ||
292 | chSysLock(); | ||
293 | #endif | ||
294 | |||
251 | if (pbuf_head != pbuf_tail) { | 295 | if (pbuf_head != pbuf_tail) { |
252 | val = pbuf[pbuf_tail]; | 296 | val = pbuf[pbuf_tail]; |
253 | pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; | 297 | pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; |
254 | } | 298 | } |
299 | |||
300 | #if defined(__AVR__) | ||
255 | SREG = sreg; | 301 | SREG = sreg; |
302 | #elif defined(PROTOCOL_CHIBIOS) | ||
303 | chSysUnlock(); | ||
304 | #endif | ||
256 | 305 | ||
257 | return val; | 306 | return val; |
258 | } | 307 | } |
259 | static inline bool pbuf_has_data(void) { | 308 | static inline bool pbuf_has_data(void) { |
309 | #if defined(__AVR__) | ||
260 | uint8_t sreg = SREG; | 310 | uint8_t sreg = SREG; |
261 | cli(); | 311 | cli(); |
312 | #elif defined(PROTOCOL_CHIBIOS) | ||
313 | chSysLock(); | ||
314 | #endif | ||
315 | |||
262 | bool has_data = (pbuf_head != pbuf_tail); | 316 | bool has_data = (pbuf_head != pbuf_tail); |
263 | SREG = sreg; | 317 | |
318 | #if defined(__AVR__) | ||
319 | SREG = sreg; | ||
320 | #elif defined(PROTOCOL_CHIBIOS) | ||
321 | chSysUnlock(); | ||
322 | #endif | ||
264 | return has_data; | 323 | return has_data; |
265 | } | 324 | } |
266 | static inline void pbuf_clear(void) { | 325 | static inline void pbuf_clear(void) { |
326 | #if defined(__AVR__) | ||
267 | uint8_t sreg = SREG; | 327 | uint8_t sreg = SREG; |
268 | cli(); | 328 | cli(); |
329 | #elif defined(PROTOCOL_CHIBIOS) | ||
330 | chSysLock(); | ||
331 | #endif | ||
332 | |||
269 | pbuf_head = pbuf_tail = 0; | 333 | pbuf_head = pbuf_tail = 0; |
270 | SREG = sreg; | 334 | |
335 | #if defined(__AVR__) | ||
336 | SREG = sreg; | ||
337 | #elif defined(PROTOCOL_CHIBIOS) | ||
338 | chSysUnlock(); | ||
339 | #endif | ||
271 | } | 340 | } |