aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/feature_ps2_mouse.md28
-rw-r--r--tmk_core/protocol.mk4
-rw-r--r--tmk_core/protocol/ps2_interrupt.c91
-rw-r--r--tmk_core/protocol/ps2_io_chibios.c55
-rw-r--r--tmk_core/protocol/ps2_mouse.c14
5 files changed, 172 insertions, 20 deletions
diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md
index 8e84e22d8..00c7ee72e 100644
--- a/docs/feature_ps2_mouse.md
+++ b/docs/feature_ps2_mouse.md
@@ -50,7 +50,7 @@ In your keyboard config.h:
50#endif 50#endif
51``` 51```
52 52
53## Interrupt Version :id=interrupt-version 53### Interrupt Version (AVR/ATMega32u4) :id=interrupt-version-avr
54 54
55The following example uses D2 for clock and D5 for data. You can use any INT or PCINT pin for clock, and any pin for data. 55The following example uses D2 for clock and D5 for data. You can use any INT or PCINT pin for clock, and any pin for data.
56 56
@@ -88,7 +88,31 @@ In your keyboard config.h:
88#endif 88#endif
89``` 89```
90 90
91## USART Version :id=usart-version 91### Interrupt Version (ARM chibios) :id=interrupt-version-chibios
92
93Pretty much any two pins can be used for the (software) interrupt variant on ARM cores. The example below uses A8 for clock, and A9 for data.
94
95In rules.mk:
96
97```
98PS2_MOUSE_ENABLE = yes
99PS2_USE_INT = yes
100```
101
102In your keyboard config.h:
103
104```c
105#define PS2_CLOCK A8
106#define PS2_DATA A9
107```
108
109And in the chibios specifig halconf.h:
110```c
111#define PAL_USE_CALLBACKS TRUE
112```
113
114
115### USART Version :id=usart-version
92 116
93To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version. 117To use USART on the ATMega32u4, you have to use PD5 for clock and PD2 for data. If one of those are unavailable, you need to use interrupt version.
94 118
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk
index cc87e8347..b61f2f546 100644
--- a/tmk_core/protocol.mk
+++ b/tmk_core/protocol.mk
@@ -14,13 +14,13 @@ endif
14 14
15ifeq ($(strip $(PS2_USE_INT)), yes) 15ifeq ($(strip $(PS2_USE_INT)), yes)
16 SRC += protocol/ps2_interrupt.c 16 SRC += protocol/ps2_interrupt.c
17 SRC += protocol/ps2_io_avr.c 17 SRC += protocol/ps2_io_$(PLATFORM_KEY).c
18 OPT_DEFS += -DPS2_USE_INT 18 OPT_DEFS += -DPS2_USE_INT
19endif 19endif
20 20
21ifeq ($(strip $(PS2_USE_USART)), yes) 21ifeq ($(strip $(PS2_USE_USART)), yes)
22 SRC += protocol/ps2_usart.c 22 SRC += protocol/ps2_usart.c
23 SRC += protocol/ps2_io_avr.c 23 SRC += protocol/ps2_io_$(PLATFORM_KEY).c
24 OPT_DEFS += -DPS2_USE_USART 24 OPT_DEFS += -DPS2_USE_USART
25endif 25endif
26 26
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);
61static inline bool pbuf_has_data(void); 69static inline bool pbuf_has_data(void);
62static inline void pbuf_clear(void); 70static inline void pbuf_clear(void);
63 71
72#if defined(PROTOCOL_CHIBIOS)
73void ps2_interrupt_service_routine(void);
74void 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
64void ps2_host_init(void) { 90void 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
72uint8_t ps2_host_send(uint8_t data) { 98uint8_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
151ISR(PS2_INT_VECT) { 176void 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__)
247ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); }
248#endif
249
221/* send LED state to keyboard */ 250/* send LED state to keyboard */
222void ps2_host_set_led(uint8_t led) { 251void 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];
232static uint8_t pbuf_head = 0; 261static uint8_t pbuf_head = 0;
233static uint8_t pbuf_tail = 0; 262static uint8_t pbuf_tail = 0;
234static inline void pbuf_enqueue(uint8_t data) { 263static 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}
246static inline uint8_t pbuf_dequeue(void) { 285static 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}
259static inline bool pbuf_has_data(void) { 308static 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}
266static inline void pbuf_clear(void) { 325static 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}
diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c
new file mode 100644
index 000000000..b672bd1f4
--- /dev/null
+++ b/tmk_core/protocol/ps2_io_chibios.c
@@ -0,0 +1,55 @@
1#include <stdbool.h>
2#include "ps2_io.h"
3
4// chibiOS headers
5#include "ch.h"
6#include "hal.h"
7
8/* Check port settings for clock and data line */
9#if !(defined(PS2_CLOCK))
10# error "PS/2 clock setting is required in config.h"
11#endif
12
13#if !(defined(PS2_DATA))
14# error "PS/2 data setting is required in config.h"
15#endif
16
17/*
18 * Clock
19 */
20void clock_init(void) {}
21
22void clock_lo(void) {
23 palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN);
24 palWriteLine(PS2_CLOCK, PAL_LOW);
25}
26
27void clock_hi(void) {
28 palSetLineMode(PS2_CLOCK, PAL_MODE_OUTPUT_OPENDRAIN);
29 palWriteLine(PS2_CLOCK, PAL_HIGH);
30}
31
32bool clock_in(void) {
33 palSetLineMode(PS2_CLOCK, PAL_MODE_INPUT);
34 return palReadLine(PS2_CLOCK);
35}
36
37/*
38 * Data
39 */
40void data_init(void) {}
41
42void data_lo(void) {
43 palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN);
44 palWriteLine(PS2_DATA, PAL_LOW);
45}
46
47void data_hi(void) {
48 palSetLineMode(PS2_DATA, PAL_MODE_OUTPUT_OPENDRAIN);
49 palWriteLine(PS2_DATA, PAL_HIGH);
50}
51
52bool data_in(void) {
53 palSetLineMode(PS2_DATA, PAL_MODE_INPUT);
54 return palReadLine(PS2_DATA);
55}
diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c
index 5415453a0..525aeb45a 100644
--- a/tmk_core/protocol/ps2_mouse.c
+++ b/tmk_core/protocol/ps2_mouse.c
@@ -16,9 +16,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/ 16*/
17 17
18#include <stdbool.h> 18#include <stdbool.h>
19#include <avr/io.h> 19
20#include <util/delay.h> 20#if defined(__AVR__)
21# include <avr/io.h>
22#endif
23
21#include "ps2_mouse.h" 24#include "ps2_mouse.h"
25#include "wait.h"
22#include "host.h" 26#include "host.h"
23#include "timer.h" 27#include "timer.h"
24#include "print.h" 28#include "print.h"
@@ -42,7 +46,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report);
42void ps2_mouse_init(void) { 46void ps2_mouse_init(void) {
43 ps2_host_init(); 47 ps2_host_init();
44 48
45 _delay_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up 49 wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up
46 50
47 PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset"); 51 PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset");
48 52
@@ -210,7 +214,7 @@ static inline void ps2_mouse_enable_scrolling(void) {
210 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate"); 214 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
211 PS2_MOUSE_SEND(80, "80"); 215 PS2_MOUSE_SEND(80, "80");
212 PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel"); 216 PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel");
213 _delay_ms(20); 217 wait_ms(20);
214} 218}
215 219
216#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK) 220#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK)
@@ -252,7 +256,7 @@ static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) {
252 if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) { 256 if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
253 PRESS_SCROLL_BUTTONS; 257 PRESS_SCROLL_BUTTONS;
254 host_mouse_send(mouse_report); 258 host_mouse_send(mouse_report);
255 _delay_ms(100); 259 wait_ms(100);
256 RELEASE_SCROLL_BUTTONS; 260 RELEASE_SCROLL_BUTTONS;
257 } 261 }
258#endif 262#endif