aboutsummaryrefslogtreecommitdiff
path: root/tmk_core
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2021-10-20 21:18:49 +0100
committerGitHub <noreply@github.com>2021-10-20 21:18:49 +0100
commitd4be4b67a251ecc046d857c5cd00cfb37c394ab7 (patch)
tree15f6dd05ec293081782a9b42a30e1a81b33b6aa0 /tmk_core
parent5500c428dd41348243e8a1695986b0da070e2ffa (diff)
downloadqmk_firmware-d4be4b67a251ecc046d857c5cd00cfb37c394ab7.tar.gz
qmk_firmware-d4be4b67a251ecc046d857c5cd00cfb37c394ab7.zip
Relocate PS2 code (#14895)
* Relocate ps2 protocol code * clang * Move makefile logic
Diffstat (limited to 'tmk_core')
-rw-r--r--tmk_core/protocol.mk25
-rw-r--r--tmk_core/protocol/ps2.h139
-rw-r--r--tmk_core/protocol/ps2_busywait.c187
-rw-r--r--tmk_core/protocol/ps2_interrupt.c340
-rw-r--r--tmk_core/protocol/ps2_io.h11
-rw-r--r--tmk_core/protocol/ps2_io_avr.c51
-rw-r--r--tmk_core/protocol/ps2_io_chibios.c55
-rw-r--r--tmk_core/protocol/ps2_mouse.c274
-rw-r--r--tmk_core/protocol/ps2_mouse.h177
-rw-r--r--tmk_core/protocol/ps2_usart.c226
10 files changed, 0 insertions, 1485 deletions
diff --git a/tmk_core/protocol.mk b/tmk_core/protocol.mk
index 30c87a0f1..8aa063c91 100644
--- a/tmk_core/protocol.mk
+++ b/tmk_core/protocol.mk
@@ -1,30 +1,5 @@
1PROTOCOL_DIR = protocol 1PROTOCOL_DIR = protocol
2 2
3ifeq ($(strip $(PS2_MOUSE_ENABLE)), yes)
4 SRC += $(PROTOCOL_DIR)/ps2_mouse.c
5 OPT_DEFS += -DPS2_MOUSE_ENABLE
6 OPT_DEFS += -DMOUSE_ENABLE
7endif
8
9ifeq ($(strip $(PS2_USE_BUSYWAIT)), yes)
10 SRC += protocol/ps2_busywait.c
11 SRC += protocol/ps2_io_avr.c
12 OPT_DEFS += -DPS2_USE_BUSYWAIT
13endif
14
15ifeq ($(strip $(PS2_USE_INT)), yes)
16 SRC += protocol/ps2_interrupt.c
17 SRC += protocol/ps2_io_$(PLATFORM_KEY).c
18 OPT_DEFS += -DPS2_USE_INT
19endif
20
21ifeq ($(strip $(PS2_USE_USART)), yes)
22 SRC += protocol/ps2_usart.c
23 SRC += protocol/ps2_io_$(PLATFORM_KEY).c
24 OPT_DEFS += -DPS2_USE_USART
25endif
26
27
28ifeq ($(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)), yes) 3ifeq ($(strip $(SERIAL_MOUSE_MICROSOFT_ENABLE)), yes)
29 SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c 4 SRC += $(PROTOCOL_DIR)/serial_mouse_microsoft.c
30 OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \ 5 OPT_DEFS += -DSERIAL_MOUSE_ENABLE -DSERIAL_MOUSE_MICROSOFT \
diff --git a/tmk_core/protocol/ps2.h b/tmk_core/protocol/ps2.h
deleted file mode 100644
index f12319285..000000000
--- a/tmk_core/protocol/ps2.h
+++ /dev/null
@@ -1,139 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38#pragma once
39
40#include <stdbool.h>
41#include "wait.h"
42#include "ps2_io.h"
43#include "print.h"
44
45/*
46 * Primitive PS/2 Library for AVR
47 *
48 * PS/2 Resources
49 * --------------
50 * [1] The PS/2 Mouse/Keyboard Protocol
51 * http://www.computer-engineering.org/ps2protocol/
52 * Concise and thorough primer of PS/2 protocol.
53 *
54 * [2] Keyboard and Auxiliary Device Controller
55 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
56 * Signal Timing and Format
57 *
58 * [3] Keyboards(101- and 102-key)
59 * http://www.mcamafia.de/pdf/ibm_hitrc11.pdf
60 * Keyboard Layout, Scan Code Set, POR, and Commands.
61 *
62 * [4] PS/2 Reference Manuals
63 * http://www.mcamafia.de/pdf/ibm_hitrc07.pdf
64 * Collection of IBM Personal System/2 documents.
65 *
66 * [5] TrackPoint Engineering Specifications for version 3E
67 * https://web.archive.org/web/20100526161812/http://wwwcssrv.almaden.ibm.com/trackpoint/download.html
68 */
69#define PS2_ACK 0xFA
70#define PS2_RESEND 0xFE
71#define PS2_SET_LED 0xED
72
73// TODO: error numbers
74#define PS2_ERR_NONE 0
75#define PS2_ERR_STARTBIT1 1
76#define PS2_ERR_STARTBIT2 2
77#define PS2_ERR_STARTBIT3 3
78#define PS2_ERR_PARITY 0x10
79#define PS2_ERR_NODATA 0x20
80
81#define PS2_LED_SCROLL_LOCK 0
82#define PS2_LED_NUM_LOCK 1
83#define PS2_LED_CAPS_LOCK 2
84
85extern uint8_t ps2_error;
86
87void ps2_host_init(void);
88uint8_t ps2_host_send(uint8_t data);
89uint8_t ps2_host_recv_response(void);
90uint8_t ps2_host_recv(void);
91void ps2_host_set_led(uint8_t usb_led);
92
93/*--------------------------------------------------------------------
94 * static functions
95 *------------------------------------------------------------------*/
96static inline uint16_t wait_clock_lo(uint16_t us) {
97 while (clock_in() && us) {
98 asm("");
99 wait_us(1);
100 us--;
101 }
102 return us;
103}
104static inline uint16_t wait_clock_hi(uint16_t us) {
105 while (!clock_in() && us) {
106 asm("");
107 wait_us(1);
108 us--;
109 }
110 return us;
111}
112static inline uint16_t wait_data_lo(uint16_t us) {
113 while (data_in() && us) {
114 asm("");
115 wait_us(1);
116 us--;
117 }
118 return us;
119}
120static inline uint16_t wait_data_hi(uint16_t us) {
121 while (!data_in() && us) {
122 asm("");
123 wait_us(1);
124 us--;
125 }
126 return us;
127}
128
129/* idle state that device can send */
130static inline void idle(void) {
131 clock_hi();
132 data_hi();
133}
134
135/* inhibit device to send */
136static inline void inhibit(void) {
137 clock_lo();
138 data_hi();
139}
diff --git a/tmk_core/protocol/ps2_busywait.c b/tmk_core/protocol/ps2_busywait.c
deleted file mode 100644
index 983194eea..000000000
--- a/tmk_core/protocol/ps2_busywait.c
+++ /dev/null
@@ -1,187 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38/*
39 * PS/2 protocol busywait version
40 */
41
42#include <stdbool.h>
43#include "wait.h"
44#include "ps2.h"
45#include "ps2_io.h"
46#include "debug.h"
47
48#define WAIT(stat, us, err) \
49 do { \
50 if (!wait_##stat(us)) { \
51 ps2_error = err; \
52 goto ERROR; \
53 } \
54 } while (0)
55
56uint8_t ps2_error = PS2_ERR_NONE;
57
58void ps2_host_init(void) {
59 clock_init();
60 data_init();
61
62 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
63 wait_ms(2500);
64
65 inhibit();
66}
67
68uint8_t ps2_host_send(uint8_t data) {
69 bool parity = true;
70 ps2_error = PS2_ERR_NONE;
71
72 /* terminate a transmission if we have */
73 inhibit();
74 wait_us(100); // 100us [4]p.13, [5]p.50
75
76 /* 'Request to Send' and Start bit */
77 data_lo();
78 clock_hi();
79 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
80
81 /* Data bit */
82 for (uint8_t i = 0; i < 8; i++) {
83 wait_us(15);
84 if (data & (1 << i)) {
85 parity = !parity;
86 data_hi();
87 } else {
88 data_lo();
89 }
90 WAIT(clock_hi, 50, 2);
91 WAIT(clock_lo, 50, 3);
92 }
93
94 /* Parity bit */
95 wait_us(15);
96 if (parity) {
97 data_hi();
98 } else {
99 data_lo();
100 }
101 WAIT(clock_hi, 50, 4);
102 WAIT(clock_lo, 50, 5);
103
104 /* Stop bit */
105 wait_us(15);
106 data_hi();
107
108 /* Ack */
109 WAIT(data_lo, 50, 6);
110 WAIT(clock_lo, 50, 7);
111
112 /* wait for idle state */
113 WAIT(clock_hi, 50, 8);
114 WAIT(data_hi, 50, 9);
115
116 inhibit();
117 return ps2_host_recv_response();
118ERROR:
119 inhibit();
120 return 0;
121}
122
123/* receive data when host want else inhibit communication */
124uint8_t ps2_host_recv_response(void) {
125 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
126 // 250 * 100us(wait for start bit in ps2_host_recv)
127 uint8_t data = 0;
128 uint8_t try
129 = 250;
130 do {
131 data = ps2_host_recv();
132 } while (try --&&ps2_error);
133 return data;
134}
135
136/* called after start bit comes */
137uint8_t ps2_host_recv(void) {
138 uint8_t data = 0;
139 bool parity = true;
140 ps2_error = PS2_ERR_NONE;
141
142 /* release lines(idle state) */
143 idle();
144
145 /* start bit [1] */
146 WAIT(clock_lo, 100, 1); // TODO: this is enough?
147 WAIT(data_lo, 1, 2);
148 WAIT(clock_hi, 50, 3);
149
150 /* data [2-9] */
151 for (uint8_t i = 0; i < 8; i++) {
152 WAIT(clock_lo, 50, 4);
153 if (data_in()) {
154 parity = !parity;
155 data |= (1 << i);
156 }
157 WAIT(clock_hi, 50, 5);
158 }
159
160 /* parity [10] */
161 WAIT(clock_lo, 50, 6);
162 if (data_in() != parity) {
163 ps2_error = PS2_ERR_PARITY;
164 goto ERROR;
165 }
166 WAIT(clock_hi, 50, 7);
167
168 /* stop bit [11] */
169 WAIT(clock_lo, 50, 8);
170 WAIT(data_hi, 1, 9);
171 WAIT(clock_hi, 50, 10);
172
173 inhibit();
174 return data;
175ERROR:
176 if (ps2_error > PS2_ERR_STARTBIT3) {
177 xprintf("x%02X\n", ps2_error);
178 }
179 inhibit();
180 return 0;
181}
182
183/* send LED state to keyboard */
184void ps2_host_set_led(uint8_t led) {
185 ps2_host_send(0xED);
186 ps2_host_send(led);
187}
diff --git a/tmk_core/protocol/ps2_interrupt.c b/tmk_core/protocol/ps2_interrupt.c
deleted file mode 100644
index 70debd02f..000000000
--- a/tmk_core/protocol/ps2_interrupt.c
+++ /dev/null
@@ -1,340 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38/*
39 * PS/2 protocol Pin interrupt version
40 */
41
42#include <stdbool.h>
43
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
52#include "ps2.h"
53#include "ps2_io.h"
54#include "print.h"
55#include "wait.h"
56
57#define WAIT(stat, us, err) \
58 do { \
59 if (!wait_##stat(us)) { \
60 ps2_error = err; \
61 goto ERROR; \
62 } \
63 } while (0)
64
65uint8_t ps2_error = PS2_ERR_NONE;
66
67static inline uint8_t pbuf_dequeue(void);
68static inline void pbuf_enqueue(uint8_t data);
69static inline bool pbuf_has_data(void);
70static inline void pbuf_clear(void);
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_PIN, PAL_MODE_INPUT); } \
78 while (0)
79# define PS2_INT_ON() \
80 { \
81 palEnableLineEvent(PS2_CLOCK_PIN, PAL_EVENT_MODE_FALLING_EDGE); \
82 palSetLineCallback(PS2_CLOCK_PIN, palCallback, NULL); \
83 } \
84 while (0)
85# define PS2_INT_OFF() \
86 { palDisableLineEvent(PS2_CLOCK_PIN); } \
87 while (0)
88#endif // PROTOCOL_CHIBIOS
89
90void ps2_host_init(void) {
91 idle();
92 PS2_INT_INIT();
93 PS2_INT_ON();
94 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
95 // wait_ms(2500);
96}
97
98uint8_t ps2_host_send(uint8_t data) {
99 bool parity = true;
100 ps2_error = PS2_ERR_NONE;
101
102 PS2_INT_OFF();
103
104 /* terminate a transmission if we have */
105 inhibit();
106 wait_us(100); // 100us [4]p.13, [5]p.50
107
108 /* 'Request to Send' and Start bit */
109 data_lo();
110 clock_hi();
111 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
112
113 /* Data bit[2-9] */
114 for (uint8_t i = 0; i < 8; i++) {
115 if (data & (1 << i)) {
116 parity = !parity;
117 data_hi();
118 } else {
119 data_lo();
120 }
121 WAIT(clock_hi, 50, 2);
122 WAIT(clock_lo, 50, 3);
123 }
124
125 /* Parity bit */
126 wait_us(15);
127 if (parity) {
128 data_hi();
129 } else {
130 data_lo();
131 }
132 WAIT(clock_hi, 50, 4);
133 WAIT(clock_lo, 50, 5);
134
135 /* Stop bit */
136 wait_us(15);
137 data_hi();
138
139 /* Ack */
140 WAIT(data_lo, 50, 6);
141 WAIT(clock_lo, 50, 7);
142
143 /* wait for idle state */
144 WAIT(clock_hi, 50, 8);
145 WAIT(data_hi, 50, 9);
146
147 idle();
148 PS2_INT_ON();
149 return ps2_host_recv_response();
150ERROR:
151 idle();
152 PS2_INT_ON();
153 return 0;
154}
155
156uint8_t ps2_host_recv_response(void) {
157 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
158 uint8_t retry = 25;
159 while (retry-- && !pbuf_has_data()) {
160 wait_ms(1);
161 }
162 return pbuf_dequeue();
163}
164
165/* get data received by interrupt */
166uint8_t ps2_host_recv(void) {
167 if (pbuf_has_data()) {
168 ps2_error = PS2_ERR_NONE;
169 return pbuf_dequeue();
170 } else {
171 ps2_error = PS2_ERR_NODATA;
172 return 0;
173 }
174}
175
176void ps2_interrupt_service_routine(void) {
177 static enum {
178 INIT,
179 START,
180 BIT0,
181 BIT1,
182 BIT2,
183 BIT3,
184 BIT4,
185 BIT5,
186 BIT6,
187 BIT7,
188 PARITY,
189 STOP,
190 } state = INIT;
191 static uint8_t data = 0;
192 static uint8_t parity = 1;
193
194 // TODO: abort if elapse 100us from previous interrupt
195
196 // return unless falling edge
197 if (clock_in()) {
198 goto RETURN;
199 }
200
201 state++;
202 switch (state) {
203 case START:
204 if (data_in()) goto ERROR;
205 break;
206 case BIT0:
207 case BIT1:
208 case BIT2:
209 case BIT3:
210 case BIT4:
211 case BIT5:
212 case BIT6:
213 case BIT7:
214 data >>= 1;
215 if (data_in()) {
216 data |= 0x80;
217 parity++;
218 }
219 break;
220 case PARITY:
221 if (data_in()) {
222 if (!(parity & 0x01)) goto ERROR;
223 } else {
224 if (parity & 0x01) goto ERROR;
225 }
226 break;
227 case STOP:
228 if (!data_in()) goto ERROR;
229 pbuf_enqueue(data);
230 goto DONE;
231 break;
232 default:
233 goto ERROR;
234 }
235 goto RETURN;
236ERROR:
237 ps2_error = state;
238DONE:
239 state = INIT;
240 data = 0;
241 parity = 1;
242RETURN:
243 return;
244}
245
246#if defined(__AVR__)
247ISR(PS2_INT_VECT) { ps2_interrupt_service_routine(); }
248#endif
249
250/* send LED state to keyboard */
251void ps2_host_set_led(uint8_t led) {
252 ps2_host_send(0xED);
253 ps2_host_send(led);
254}
255
256/*--------------------------------------------------------------------
257 * Ring buffer to store scan codes from keyboard
258 *------------------------------------------------------------------*/
259#define PBUF_SIZE 32
260static uint8_t pbuf[PBUF_SIZE];
261static uint8_t pbuf_head = 0;
262static uint8_t pbuf_tail = 0;
263static inline void pbuf_enqueue(uint8_t data) {
264#if defined(__AVR__)
265 uint8_t sreg = SREG;
266 cli();
267#elif defined(PROTOCOL_CHIBIOS)
268 chSysLockFromISR();
269#endif
270
271 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
272 if (next != pbuf_tail) {
273 pbuf[pbuf_head] = data;
274 pbuf_head = next;
275 } else {
276 print("pbuf: full\n");
277 }
278
279#if defined(__AVR__)
280 SREG = sreg;
281#elif defined(PROTOCOL_CHIBIOS)
282 chSysUnlockFromISR();
283#endif
284}
285static inline uint8_t pbuf_dequeue(void) {
286 uint8_t val = 0;
287
288#if defined(__AVR__)
289 uint8_t sreg = SREG;
290 cli();
291#elif defined(PROTOCOL_CHIBIOS)
292 chSysLock();
293#endif
294
295 if (pbuf_head != pbuf_tail) {
296 val = pbuf[pbuf_tail];
297 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
298 }
299
300#if defined(__AVR__)
301 SREG = sreg;
302#elif defined(PROTOCOL_CHIBIOS)
303 chSysUnlock();
304#endif
305
306 return val;
307}
308static inline bool pbuf_has_data(void) {
309#if defined(__AVR__)
310 uint8_t sreg = SREG;
311 cli();
312#elif defined(PROTOCOL_CHIBIOS)
313 chSysLock();
314#endif
315
316 bool has_data = (pbuf_head != pbuf_tail);
317
318#if defined(__AVR__)
319 SREG = sreg;
320#elif defined(PROTOCOL_CHIBIOS)
321 chSysUnlock();
322#endif
323 return has_data;
324}
325static inline void pbuf_clear(void) {
326#if defined(__AVR__)
327 uint8_t sreg = SREG;
328 cli();
329#elif defined(PROTOCOL_CHIBIOS)
330 chSysLock();
331#endif
332
333 pbuf_head = pbuf_tail = 0;
334
335#if defined(__AVR__)
336 SREG = sreg;
337#elif defined(PROTOCOL_CHIBIOS)
338 chSysUnlock();
339#endif
340}
diff --git a/tmk_core/protocol/ps2_io.h b/tmk_core/protocol/ps2_io.h
deleted file mode 100644
index de93cb7a3..000000000
--- a/tmk_core/protocol/ps2_io.h
+++ /dev/null
@@ -1,11 +0,0 @@
1#pragma once
2
3void clock_init(void);
4void clock_lo(void);
5void clock_hi(void);
6bool clock_in(void);
7
8void data_init(void);
9void data_lo(void);
10void data_hi(void);
11bool data_in(void);
diff --git a/tmk_core/protocol/ps2_io_avr.c b/tmk_core/protocol/ps2_io_avr.c
deleted file mode 100644
index 7c826fbf1..000000000
--- a/tmk_core/protocol/ps2_io_avr.c
+++ /dev/null
@@ -1,51 +0,0 @@
1#include <stdbool.h>
2#include "ps2_io.h"
3#include "gpio.h"
4#include "wait.h"
5
6/* Check port settings for clock and data line */
7#if !(defined(PS2_CLOCK_PIN))
8# error "PS/2 clock setting is required in config.h"
9#endif
10
11#if !(defined(PS2_DATA_PIN))
12# error "PS/2 data setting is required in config.h"
13#endif
14
15/*
16 * Clock
17 */
18void clock_init(void) {}
19
20void clock_lo(void) {
21 // Transition from input with pull-up to output low via Hi-Z instead of output high
22 writePinLow(PS2_CLOCK_PIN);
23 setPinOutput(PS2_CLOCK_PIN);
24}
25
26void clock_hi(void) { setPinInputHigh(PS2_CLOCK_PIN); }
27
28bool clock_in(void) {
29 setPinInputHigh(PS2_CLOCK_PIN);
30 wait_us(1);
31 return readPin(PS2_CLOCK_PIN);
32}
33
34/*
35 * Data
36 */
37void data_init(void) {}
38
39void data_lo(void) {
40 // Transition from input with pull-up to output low via Hi-Z instead of output high
41 writePinLow(PS2_DATA_PIN);
42 setPinOutput(PS2_DATA_PIN);
43}
44
45void data_hi(void) { setPinInputHigh(PS2_DATA_PIN); }
46
47bool data_in(void) {
48 setPinInputHigh(PS2_DATA_PIN);
49 wait_us(1);
50 return readPin(PS2_DATA_PIN);
51}
diff --git a/tmk_core/protocol/ps2_io_chibios.c b/tmk_core/protocol/ps2_io_chibios.c
deleted file mode 100644
index 906d85d84..000000000
--- a/tmk_core/protocol/ps2_io_chibios.c
+++ /dev/null
@@ -1,55 +0,0 @@
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_PIN))
10# error "PS/2 clock setting is required in config.h"
11#endif
12
13#if !(defined(PS2_DATA_PIN))
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_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
24 palWriteLine(PS2_CLOCK_PIN, PAL_LOW);
25}
26
27void clock_hi(void) {
28 palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
29 palWriteLine(PS2_CLOCK_PIN, PAL_HIGH);
30}
31
32bool clock_in(void) {
33 palSetLineMode(PS2_CLOCK_PIN, PAL_MODE_INPUT);
34 return palReadLine(PS2_CLOCK_PIN);
35}
36
37/*
38 * Data
39 */
40void data_init(void) {}
41
42void data_lo(void) {
43 palSetLineMode(PS2_DATA_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
44 palWriteLine(PS2_DATA_PIN, PAL_LOW);
45}
46
47void data_hi(void) {
48 palSetLineMode(PS2_DATA_PIN, PAL_MODE_OUTPUT_OPENDRAIN);
49 palWriteLine(PS2_DATA_PIN, PAL_HIGH);
50}
51
52bool data_in(void) {
53 palSetLineMode(PS2_DATA_PIN, PAL_MODE_INPUT);
54 return palReadLine(PS2_DATA_PIN);
55}
diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c
deleted file mode 100644
index 39251a643..000000000
--- a/tmk_core/protocol/ps2_mouse.c
+++ /dev/null
@@ -1,274 +0,0 @@
1/*
2Copyright 2011,2013 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#include <stdbool.h>
19
20#if defined(__AVR__)
21# include <avr/io.h>
22#endif
23
24#include "ps2_mouse.h"
25#include "wait.h"
26#include "host.h"
27#include "timer.h"
28#include "print.h"
29#include "report.h"
30#include "debug.h"
31#include "ps2.h"
32
33/* ============================= MACROS ============================ */
34
35static report_mouse_t mouse_report = {};
36
37static inline void ps2_mouse_print_report(report_mouse_t *mouse_report);
38static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report);
39static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report);
40static inline void ps2_mouse_enable_scrolling(void);
41static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report);
42
43/* ============================= IMPLEMENTATION ============================ */
44
45/* supports only 3 button mouse at this time */
46void ps2_mouse_init(void) {
47 ps2_host_init();
48
49 wait_ms(PS2_MOUSE_INIT_DELAY); // wait for powering up
50
51 PS2_MOUSE_SEND(PS2_MOUSE_RESET, "ps2_mouse_init: sending reset");
52
53 PS2_MOUSE_RECEIVE("ps2_mouse_init: read BAT");
54 PS2_MOUSE_RECEIVE("ps2_mouse_init: read DevID");
55
56#ifdef PS2_MOUSE_USE_REMOTE_MODE
57 ps2_mouse_set_remote_mode();
58#else
59 ps2_mouse_enable_data_reporting();
60#endif
61
62#ifdef PS2_MOUSE_ENABLE_SCROLLING
63 ps2_mouse_enable_scrolling();
64#endif
65
66#ifdef PS2_MOUSE_USE_2_1_SCALING
67 ps2_mouse_set_scaling_2_1();
68#endif
69
70 ps2_mouse_init_user();
71}
72
73__attribute__((weak)) void ps2_mouse_init_user(void) {}
74
75__attribute__((weak)) void ps2_mouse_moved_user(report_mouse_t *mouse_report) {}
76
77void ps2_mouse_task(void) {
78 static uint8_t buttons_prev = 0;
79 extern int tp_buttons;
80
81 /* receives packet from mouse */
82 uint8_t rcv;
83 rcv = ps2_host_send(PS2_MOUSE_READ_DATA);
84 if (rcv == PS2_ACK) {
85 mouse_report.buttons = ps2_host_recv_response() | tp_buttons;
86 mouse_report.x = ps2_host_recv_response() * PS2_MOUSE_X_MULTIPLIER;
87 mouse_report.y = ps2_host_recv_response() * PS2_MOUSE_Y_MULTIPLIER;
88#ifdef PS2_MOUSE_ENABLE_SCROLLING
89 mouse_report.v = -(ps2_host_recv_response() & PS2_MOUSE_SCROLL_MASK) * PS2_MOUSE_V_MULTIPLIER;
90#endif
91 } else {
92 if (debug_mouse) print("ps2_mouse: fail to get mouse packet\n");
93 return;
94 }
95
96 /* if mouse moves or buttons state changes */
97 if (mouse_report.x || mouse_report.y || mouse_report.v || ((mouse_report.buttons ^ buttons_prev) & PS2_MOUSE_BTN_MASK)) {
98#ifdef PS2_MOUSE_DEBUG_RAW
99 // Used to debug raw ps2 bytes from mouse
100 ps2_mouse_print_report(&mouse_report);
101#endif
102 buttons_prev = mouse_report.buttons;
103 ps2_mouse_convert_report_to_hid(&mouse_report);
104#if PS2_MOUSE_SCROLL_BTN_MASK
105 ps2_mouse_scroll_button_task(&mouse_report);
106#endif
107 if (mouse_report.x || mouse_report.y || mouse_report.v) {
108 ps2_mouse_moved_user(&mouse_report);
109 }
110#ifdef PS2_MOUSE_DEBUG_HID
111 // Used to debug the bytes sent to the host
112 ps2_mouse_print_report(&mouse_report);
113#endif
114 host_mouse_send(&mouse_report);
115 }
116
117 ps2_mouse_clear_report(&mouse_report);
118}
119
120void ps2_mouse_disable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_DISABLE_DATA_REPORTING, "ps2 mouse disable data reporting"); }
121
122void ps2_mouse_enable_data_reporting(void) { PS2_MOUSE_SEND(PS2_MOUSE_ENABLE_DATA_REPORTING, "ps2 mouse enable data reporting"); }
123
124void ps2_mouse_set_remote_mode(void) {
125 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_REMOTE_MODE, "ps2 mouse set remote mode");
126 ps2_mouse_mode = PS2_MOUSE_REMOTE_MODE;
127}
128
129void ps2_mouse_set_stream_mode(void) {
130 PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_STREAM_MODE, "ps2 mouse set stream mode");
131 ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
132}
133
134void ps2_mouse_set_scaling_2_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_2_1, "ps2 mouse set scaling 2:1"); }
135
136void ps2_mouse_set_scaling_1_1(void) { PS2_MOUSE_SEND_SAFE(PS2_MOUSE_SET_SCALING_1_1, "ps2 mouse set scaling 1:1"); }
137
138void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_RESOLUTION, resolution, "ps2 mouse set resolution"); }
139
140void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate) { PS2_MOUSE_SET_SAFE(PS2_MOUSE_SET_SAMPLE_RATE, sample_rate, "ps2 mouse set sample rate"); }
141
142/* ============================= HELPERS ============================ */
143
144#define X_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_X_SIGN))
145#define Y_IS_NEG (mouse_report->buttons & (1 << PS2_MOUSE_Y_SIGN))
146#define X_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_X_OVFLW))
147#define Y_IS_OVF (mouse_report->buttons & (1 << PS2_MOUSE_Y_OVFLW))
148static inline void ps2_mouse_convert_report_to_hid(report_mouse_t *mouse_report) {
149 // PS/2 mouse data is '9-bit integer'(-256 to 255) which is comprised of sign-bit and 8-bit value.
150 // bit: 8 7 ... 0
151 // sign \8-bit/
152 //
153 // Meanwhile USB HID mouse indicates 8bit data(-127 to 127), note that -128 is not used.
154 //
155 // This converts PS/2 data into HID value. Use only -127-127 out of PS/2 9-bit.
156 mouse_report->x = X_IS_NEG ? ((!X_IS_OVF && -127 <= mouse_report->x && mouse_report->x <= -1) ? mouse_report->x : -127) : ((!X_IS_OVF && 0 <= mouse_report->x && mouse_report->x <= 127) ? mouse_report->x : 127);
157 mouse_report->y = Y_IS_NEG ? ((!Y_IS_OVF && -127 <= mouse_report->y && mouse_report->y <= -1) ? mouse_report->y : -127) : ((!Y_IS_OVF && 0 <= mouse_report->y && mouse_report->y <= 127) ? mouse_report->y : 127);
158
159#ifdef PS2_MOUSE_INVERT_BUTTONS
160 // swap left & right buttons
161 uint8_t needs_left = mouse_report->buttons & PS2_MOUSE_BTN_RIGHT;
162 uint8_t needs_right = mouse_report->buttons & PS2_MOUSE_BTN_LEFT;
163 mouse_report->buttons = (mouse_report->buttons & ~(PS2_MOUSE_BTN_MASK)) | (needs_left ? PS2_MOUSE_BTN_LEFT : 0) | (needs_right ? PS2_MOUSE_BTN_RIGHT : 0);
164#else
165 // remove sign and overflow flags
166 mouse_report->buttons &= PS2_MOUSE_BTN_MASK;
167#endif
168
169#ifdef PS2_MOUSE_INVERT_X
170 mouse_report->x = -mouse_report->x;
171#endif
172#ifndef PS2_MOUSE_INVERT_Y // NOTE if not!
173 // invert coordinate of y to conform to USB HID mouse
174 mouse_report->y = -mouse_report->y;
175#endif
176
177#ifdef PS2_MOUSE_ROTATE
178 int8_t x = mouse_report->x;
179 int8_t y = mouse_report->y;
180# if PS2_MOUSE_ROTATE == 90
181 mouse_report->x = y;
182 mouse_report->y = -x;
183# elif PS2_MOUSE_ROTATE == 180
184 mouse_report->x = -x;
185 mouse_report->y = -y;
186# elif PS2_MOUSE_ROTATE == 270
187 mouse_report->x = -y;
188 mouse_report->y = x;
189# endif
190#endif
191}
192
193static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) {
194 mouse_report->x = 0;
195 mouse_report->y = 0;
196 mouse_report->v = 0;
197 mouse_report->h = 0;
198 mouse_report->buttons = 0;
199}
200
201static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) {
202 if (!debug_mouse) return;
203 print("ps2_mouse: [");
204 print_hex8(mouse_report->buttons);
205 print("|");
206 print_hex8((uint8_t)mouse_report->x);
207 print(" ");
208 print_hex8((uint8_t)mouse_report->y);
209 print(" ");
210 print_hex8((uint8_t)mouse_report->v);
211 print(" ");
212 print_hex8((uint8_t)mouse_report->h);
213 print("]\n");
214}
215
216static inline void ps2_mouse_enable_scrolling(void) {
217 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Initiaing scroll wheel enable: Set sample rate");
218 PS2_MOUSE_SEND(200, "200");
219 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
220 PS2_MOUSE_SEND(100, "100");
221 PS2_MOUSE_SEND(PS2_MOUSE_SET_SAMPLE_RATE, "Set sample rate");
222 PS2_MOUSE_SEND(80, "80");
223 PS2_MOUSE_SEND(PS2_MOUSE_GET_DEVICE_ID, "Finished enabling scroll wheel");
224 wait_ms(20);
225}
226
227#define PRESS_SCROLL_BUTTONS mouse_report->buttons |= (PS2_MOUSE_SCROLL_BTN_MASK)
228#define RELEASE_SCROLL_BUTTONS mouse_report->buttons &= ~(PS2_MOUSE_SCROLL_BTN_MASK)
229static inline void ps2_mouse_scroll_button_task(report_mouse_t *mouse_report) {
230 static enum {
231 SCROLL_NONE,
232 SCROLL_BTN,
233 SCROLL_SENT,
234 } scroll_state = SCROLL_NONE;
235 static uint16_t scroll_button_time = 0;
236
237 if (PS2_MOUSE_SCROLL_BTN_MASK == (mouse_report->buttons & (PS2_MOUSE_SCROLL_BTN_MASK))) {
238 // All scroll buttons are pressed
239
240 if (scroll_state == SCROLL_NONE) {
241 scroll_button_time = timer_read();
242 scroll_state = SCROLL_BTN;
243 }
244
245 // If the mouse has moved, update the report to scroll instead of move the mouse
246 if (mouse_report->x || mouse_report->y) {
247 scroll_state = SCROLL_SENT;
248 mouse_report->v = -mouse_report->y / (PS2_MOUSE_SCROLL_DIVISOR_V);
249 mouse_report->h = mouse_report->x / (PS2_MOUSE_SCROLL_DIVISOR_H);
250 mouse_report->x = 0;
251 mouse_report->y = 0;
252#ifdef PS2_MOUSE_INVERT_H
253 mouse_report->h = -mouse_report->h;
254#endif
255#ifdef PS2_MOUSE_INVERT_V
256 mouse_report->v = -mouse_report->v;
257#endif
258 }
259 } else if (0 == (PS2_MOUSE_SCROLL_BTN_MASK & mouse_report->buttons)) {
260 // None of the scroll buttons are pressed
261
262#if PS2_MOUSE_SCROLL_BTN_SEND
263 if (scroll_state == SCROLL_BTN && timer_elapsed(scroll_button_time) < PS2_MOUSE_SCROLL_BTN_SEND) {
264 PRESS_SCROLL_BUTTONS;
265 host_mouse_send(mouse_report);
266 wait_ms(100);
267 RELEASE_SCROLL_BUTTONS;
268 }
269#endif
270 scroll_state = SCROLL_NONE;
271 }
272
273 RELEASE_SCROLL_BUTTONS;
274}
diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h
deleted file mode 100644
index c97c6c893..000000000
--- a/tmk_core/protocol/ps2_mouse.h
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2Copyright 2011 Jun Wako <wakojun@gmail.com>
3
4This program is free software: you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation, either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18#pragma once
19
20#include <stdbool.h>
21#include "debug.h"
22#include "report.h"
23
24#define PS2_MOUSE_SEND(command, message) \
25 do { \
26 __attribute__((unused)) uint8_t rcv = ps2_host_send(command); \
27 if (debug_mouse) { \
28 print((message)); \
29 xprintf(" command: %X, result: %X, error: %X \n", command, rcv, ps2_error); \
30 } \
31 } while (0)
32
33#define PS2_MOUSE_SEND_SAFE(command, message) \
34 do { \
35 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
36 ps2_mouse_disable_data_reporting(); \
37 } \
38 PS2_MOUSE_SEND(command, message); \
39 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
40 ps2_mouse_enable_data_reporting(); \
41 } \
42 } while (0)
43
44#define PS2_MOUSE_SET_SAFE(command, value, message) \
45 do { \
46 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
47 ps2_mouse_disable_data_reporting(); \
48 } \
49 PS2_MOUSE_SEND(command, message); \
50 PS2_MOUSE_SEND(value, "Sending value"); \
51 if (PS2_MOUSE_STREAM_MODE == ps2_mouse_mode) { \
52 ps2_mouse_enable_data_reporting(); \
53 } \
54 } while (0)
55
56#define PS2_MOUSE_RECEIVE(message) \
57 do { \
58 __attribute__((unused)) uint8_t rcv = ps2_host_recv_response(); \
59 if (debug_mouse) { \
60 print((message)); \
61 xprintf(" result: %X, error: %X \n", rcv, ps2_error); \
62 } \
63 } while (0)
64
65__attribute__((unused)) static enum ps2_mouse_mode_e {
66 PS2_MOUSE_STREAM_MODE,
67 PS2_MOUSE_REMOTE_MODE,
68} ps2_mouse_mode = PS2_MOUSE_STREAM_MODE;
69
70/*
71 * Data format:
72 * byte|7 6 5 4 3 2 1 0
73 * ----+----------------------------------------------------------------
74 * 0|[Yovflw][Xovflw][Ysign ][Xsign ][ 1 ][Middle][Right ][Left ]
75 * 1|[ X movement(0-255) ]
76 * 2|[ Y movement(0-255) ]
77 */
78#define PS2_MOUSE_BTN_MASK 0x07
79#define PS2_MOUSE_BTN_LEFT 0
80#define PS2_MOUSE_BTN_RIGHT 1
81#define PS2_MOUSE_BTN_MIDDLE 2
82#define PS2_MOUSE_X_SIGN 4
83#define PS2_MOUSE_Y_SIGN 5
84#define PS2_MOUSE_X_OVFLW 6
85#define PS2_MOUSE_Y_OVFLW 7
86
87/* mouse button to start scrolling; set 0 to disable scroll */
88#ifndef PS2_MOUSE_SCROLL_BTN_MASK
89# define PS2_MOUSE_SCROLL_BTN_MASK (1 << PS2_MOUSE_BTN_MIDDLE)
90#endif
91/* send button event when button is released within this value(ms); set 0 to disable */
92#ifndef PS2_MOUSE_SCROLL_BTN_SEND
93# define PS2_MOUSE_SCROLL_BTN_SEND 300
94#endif
95/* divide virtical and horizontal mouse move by this to convert to scroll move */
96#ifndef PS2_MOUSE_SCROLL_DIVISOR_V
97# define PS2_MOUSE_SCROLL_DIVISOR_V 2
98#endif
99#ifndef PS2_MOUSE_SCROLL_DIVISOR_H
100# define PS2_MOUSE_SCROLL_DIVISOR_H 2
101#endif
102/* multiply reported mouse values by these */
103#ifndef PS2_MOUSE_X_MULTIPLIER
104# define PS2_MOUSE_X_MULTIPLIER 1
105#endif
106#ifndef PS2_MOUSE_Y_MULTIPLIER
107# define PS2_MOUSE_Y_MULTIPLIER 1
108#endif
109#ifndef PS2_MOUSE_V_MULTIPLIER
110# define PS2_MOUSE_V_MULTIPLIER 1
111#endif
112/* For some mice this will need to be 0x0F */
113#ifndef PS2_MOUSE_SCROLL_MASK
114# define PS2_MOUSE_SCROLL_MASK 0xFF
115#endif
116#ifndef PS2_MOUSE_INIT_DELAY
117# define PS2_MOUSE_INIT_DELAY 1000
118#endif
119
120enum ps2_mouse_command_e {
121 PS2_MOUSE_RESET = 0xFF,
122 PS2_MOUSE_RESEND = 0xFE,
123 PS2_MOSUE_SET_DEFAULTS = 0xF6,
124 PS2_MOUSE_DISABLE_DATA_REPORTING = 0xF5,
125 PS2_MOUSE_ENABLE_DATA_REPORTING = 0xF4,
126 PS2_MOUSE_SET_SAMPLE_RATE = 0xF3,
127 PS2_MOUSE_GET_DEVICE_ID = 0xF2,
128 PS2_MOUSE_SET_REMOTE_MODE = 0xF0,
129 PS2_MOUSE_SET_WRAP_MODE = 0xEC,
130 PS2_MOUSE_READ_DATA = 0xEB,
131 PS2_MOUSE_SET_STREAM_MODE = 0xEA,
132 PS2_MOUSE_STATUS_REQUEST = 0xE9,
133 PS2_MOUSE_SET_RESOLUTION = 0xE8,
134 PS2_MOUSE_SET_SCALING_2_1 = 0xE7,
135 PS2_MOUSE_SET_SCALING_1_1 = 0xE6,
136};
137
138typedef enum ps2_mouse_resolution_e {
139 PS2_MOUSE_1_COUNT_MM,
140 PS2_MOUSE_2_COUNT_MM,
141 PS2_MOUSE_4_COUNT_MM,
142 PS2_MOUSE_8_COUNT_MM,
143} ps2_mouse_resolution_t;
144
145typedef enum ps2_mouse_sample_rate_e {
146 PS2_MOUSE_10_SAMPLES_SEC = 10,
147 PS2_MOUSE_20_SAMPLES_SEC = 20,
148 PS2_MOUSE_40_SAMPLES_SEC = 40,
149 PS2_MOUSE_60_SAMPLES_SEC = 60,
150 PS2_MOUSE_80_SAMPLES_SEC = 80,
151 PS2_MOUSE_100_SAMPLES_SEC = 100,
152 PS2_MOUSE_200_SAMPLES_SEC = 200,
153} ps2_mouse_sample_rate_t;
154
155void ps2_mouse_init(void);
156
157void ps2_mouse_init_user(void);
158
159void ps2_mouse_task(void);
160
161void ps2_mouse_disable_data_reporting(void);
162
163void ps2_mouse_enable_data_reporting(void);
164
165void ps2_mouse_set_remote_mode(void);
166
167void ps2_mouse_set_stream_mode(void);
168
169void ps2_mouse_set_scaling_2_1(void);
170
171void ps2_mouse_set_scaling_1_1(void);
172
173void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution);
174
175void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate);
176
177void ps2_mouse_moved_user(report_mouse_t *mouse_report);
diff --git a/tmk_core/protocol/ps2_usart.c b/tmk_core/protocol/ps2_usart.c
deleted file mode 100644
index 5f7008369..000000000
--- a/tmk_core/protocol/ps2_usart.c
+++ /dev/null
@@ -1,226 +0,0 @@
1/*
2Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com>
3
4This software is licensed with a Modified BSD License.
5All of this is supposed to be Free Software, Open Source, DFSG-free,
6GPL-compatible, and OK to use in both free and proprietary applications.
7Additions and corrections to this file are welcome.
8
9
10Redistribution and use in source and binary forms, with or without
11modification, are permitted provided that the following conditions are met:
12
13* Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15
16* Redistributions in binary form must reproduce the above copyright
17 notice, this list of conditions and the following disclaimer in
18 the documentation and/or other materials provided with the
19 distribution.
20
21* Neither the name of the copyright holders nor the names of
22 contributors may be used to endorse or promote products derived
23 from this software without specific prior written permission.
24
25THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35POSSIBILITY OF SUCH DAMAGE.
36*/
37
38/*
39 * PS/2 protocol USART version
40 */
41
42#include <stdbool.h>
43#include <avr/interrupt.h>
44#include <util/delay.h>
45#include "ps2.h"
46#include "ps2_io.h"
47#include "print.h"
48
49#ifndef PS2_CLOCK_DDR
50# define PS2_CLOCK_DDR PORTx_ADDRESS(PS2_CLOCK_PIN)
51#endif
52#ifndef PS2_CLOCK_BIT
53# define PS2_CLOCK_BIT (PS2_CLOCK_PIN & 0xF)
54#endif
55#ifndef PS2_DATA_DDR
56# define PS2_DATA_DDR PORTx_ADDRESS(PS2_DATA_PIN)
57#endif
58#ifndef PS2_DATA_BIT
59# define PS2_DATA_BIT (PS2_DATA_PIN & 0xF)
60#endif
61
62#define WAIT(stat, us, err) \
63 do { \
64 if (!wait_##stat(us)) { \
65 ps2_error = err; \
66 goto ERROR; \
67 } \
68 } while (0)
69
70uint8_t ps2_error = PS2_ERR_NONE;
71
72static inline uint8_t pbuf_dequeue(void);
73static inline void pbuf_enqueue(uint8_t data);
74static inline bool pbuf_has_data(void);
75static inline void pbuf_clear(void);
76
77void ps2_host_init(void) {
78 idle(); // without this many USART errors occur when cable is disconnected
79 PS2_USART_INIT();
80 PS2_USART_RX_INT_ON();
81 // POR(150-2000ms) plus BAT(300-500ms) may take 2.5sec([3]p.20)
82 //_delay_ms(2500);
83}
84
85uint8_t ps2_host_send(uint8_t data) {
86 bool parity = true;
87 ps2_error = PS2_ERR_NONE;
88
89 PS2_USART_OFF();
90
91 /* terminate a transmission if we have */
92 inhibit();
93 _delay_us(100); // [4]p.13
94
95 /* 'Request to Send' and Start bit */
96 data_lo();
97 clock_hi();
98 WAIT(clock_lo, 10000, 10); // 10ms [5]p.50
99
100 /* Data bit[2-9] */
101 for (uint8_t i = 0; i < 8; i++) {
102 _delay_us(15);
103 if (data & (1 << i)) {
104 parity = !parity;
105 data_hi();
106 } else {
107 data_lo();
108 }
109 WAIT(clock_hi, 50, 2);
110 WAIT(clock_lo, 50, 3);
111 }
112
113 /* Parity bit */
114 _delay_us(15);
115 if (parity) {
116 data_hi();
117 } else {
118 data_lo();
119 }
120 WAIT(clock_hi, 50, 4);
121 WAIT(clock_lo, 50, 5);
122
123 /* Stop bit */
124 _delay_us(15);
125 data_hi();
126
127 /* Ack */
128 WAIT(data_lo, 50, 6);
129 WAIT(clock_lo, 50, 7);
130
131 /* wait for idle state */
132 WAIT(clock_hi, 50, 8);
133 WAIT(data_hi, 50, 9);
134
135 idle();
136 PS2_USART_INIT();
137 PS2_USART_RX_INT_ON();
138 return ps2_host_recv_response();
139ERROR:
140 idle();
141 PS2_USART_INIT();
142 PS2_USART_RX_INT_ON();
143 return 0;
144}
145
146uint8_t ps2_host_recv_response(void) {
147 // Command may take 25ms/20ms at most([5]p.46, [3]p.21)
148 uint8_t retry = 25;
149 while (retry-- && !pbuf_has_data()) {
150 _delay_ms(1);
151 }
152 return pbuf_dequeue();
153}
154
155uint8_t ps2_host_recv(void) {
156 if (pbuf_has_data()) {
157 ps2_error = PS2_ERR_NONE;
158 return pbuf_dequeue();
159 } else {
160 ps2_error = PS2_ERR_NODATA;
161 return 0;
162 }
163}
164
165ISR(PS2_USART_RX_VECT) {
166 // TODO: request RESEND when error occurs?
167 uint8_t error = PS2_USART_ERROR; // USART error should be read before data
168 uint8_t data = PS2_USART_RX_DATA;
169 if (!error) {
170 pbuf_enqueue(data);
171 } else {
172 xprintf("PS2 USART error: %02X data: %02X\n", error, data);
173 }
174}
175
176/* send LED state to keyboard */
177void ps2_host_set_led(uint8_t led) {
178 ps2_host_send(0xED);
179 ps2_host_send(led);
180}
181
182/*--------------------------------------------------------------------
183 * Ring buffer to store scan codes from keyboard
184 *------------------------------------------------------------------*/
185#define PBUF_SIZE 32
186static uint8_t pbuf[PBUF_SIZE];
187static uint8_t pbuf_head = 0;
188static uint8_t pbuf_tail = 0;
189static inline void pbuf_enqueue(uint8_t data) {
190 uint8_t sreg = SREG;
191 cli();
192 uint8_t next = (pbuf_head + 1) % PBUF_SIZE;
193 if (next != pbuf_tail) {
194 pbuf[pbuf_head] = data;
195 pbuf_head = next;
196 } else {
197 print("pbuf: full\n");
198 }
199 SREG = sreg;
200}
201static inline uint8_t pbuf_dequeue(void) {
202 uint8_t val = 0;
203
204 uint8_t sreg = SREG;
205 cli();
206 if (pbuf_head != pbuf_tail) {
207 val = pbuf[pbuf_tail];
208 pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE;
209 }
210 SREG = sreg;
211
212 return val;
213}
214static inline bool pbuf_has_data(void) {
215 uint8_t sreg = SREG;
216 cli();
217 bool has_data = (pbuf_head != pbuf_tail);
218 SREG = sreg;
219 return has_data;
220}
221static inline void pbuf_clear(void) {
222 uint8_t sreg = SREG;
223 cli();
224 pbuf_head = pbuf_tail = 0;
225 SREG = sreg;
226}