diff options
author | Akshay <[email protected]> | 2022-04-10 12:13:40 +0100 |
---|---|---|
committer | Akshay <[email protected]> | 2022-04-10 12:13:40 +0100 |
commit | dc90387ce7d8ba7b607d9c48540bf6d8b560f14d (patch) | |
tree | 4ccb8fa5886b66fa9d480edef74236c27f035e16 /docs/feature_ps2_mouse.md |
Diffstat (limited to 'docs/feature_ps2_mouse.md')
-rw-r--r-- | docs/feature_ps2_mouse.md | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/docs/feature_ps2_mouse.md b/docs/feature_ps2_mouse.md new file mode 100644 index 000000000..c980705ae --- /dev/null +++ b/docs/feature_ps2_mouse.md | |||
@@ -0,0 +1,322 @@ | |||
1 | # PS/2 Mouse Support :id=ps2-mouse-support | ||
2 | |||
3 | Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device. | ||
4 | |||
5 | To hook up a Trackpoint, you need to obtain a Trackpoint module (i.e. harvest from a Thinkpad keyboard), identify the function of each pin of the module, and make the necessary circuitry between controller and Trackpoint module. For more information, please refer to [Trackpoint Hardware](https://deskthority.net/wiki/TrackPoint_Hardware) page on Deskthority Wiki. | ||
6 | |||
7 | There are three available modes for hooking up PS/2 devices: USART (best), interrupts (better) or busywait (not recommended). | ||
8 | |||
9 | ## The Circuitry between Trackpoint and Controller :id=the-circuitry-between-trackpoint-and-controller | ||
10 | |||
11 | To get the things working, a 4.7K drag is needed between the two lines DATA and CLK and the line 5+. | ||
12 | |||
13 | ``` | ||
14 | |||
15 | DATA ----------+--------- PIN | ||
16 | | | ||
17 | 4.7K | ||
18 | | | ||
19 | MODULE 5+ --------+--+--------- PWR CONTROLLER | ||
20 | | | ||
21 | 4.7K | ||
22 | | | ||
23 | CLK ------+------------ PIN | ||
24 | ``` | ||
25 | |||
26 | |||
27 | ## Busywait Version :id=busywait-version | ||
28 | |||
29 | Note: This is not recommended, you may encounter jerky movement or unsent inputs. Please use interrupt or USART version if possible. | ||
30 | |||
31 | In rules.mk: | ||
32 | |||
33 | ```make | ||
34 | PS2_MOUSE_ENABLE = yes | ||
35 | PS2_USE_BUSYWAIT = yes | ||
36 | ``` | ||
37 | |||
38 | In your keyboard config.h: | ||
39 | |||
40 | ```c | ||
41 | #ifdef PS2_USE_BUSYWAIT | ||
42 | # define PS2_CLOCK_PIN D1 | ||
43 | # define PS2_DATA_PIN D2 | ||
44 | #endif | ||
45 | ``` | ||
46 | |||
47 | ### Interrupt Version (AVR/ATMega32u4) :id=interrupt-version-avr | ||
48 | |||
49 | The 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. | ||
50 | |||
51 | In rules.mk: | ||
52 | |||
53 | ```make | ||
54 | PS2_MOUSE_ENABLE = yes | ||
55 | PS2_USE_INT = yes | ||
56 | ``` | ||
57 | |||
58 | In your keyboard config.h: | ||
59 | |||
60 | ```c | ||
61 | #ifdef PS2_USE_INT | ||
62 | #define PS2_CLOCK_PIN D2 | ||
63 | #define PS2_DATA_PIN D5 | ||
64 | |||
65 | #define PS2_INT_INIT() do { \ | ||
66 | EICRA |= ((1<<ISC21) | \ | ||
67 | (0<<ISC20)); \ | ||
68 | } while (0) | ||
69 | #define PS2_INT_ON() do { \ | ||
70 | EIMSK |= (1<<INT2); \ | ||
71 | } while (0) | ||
72 | #define PS2_INT_OFF() do { \ | ||
73 | EIMSK &= ~(1<<INT2); \ | ||
74 | } while (0) | ||
75 | #define PS2_INT_VECT INT2_vect | ||
76 | #endif | ||
77 | ``` | ||
78 | |||
79 | ### Interrupt Version (ARM chibios) :id=interrupt-version-chibios | ||
80 | |||
81 | Pretty 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. | ||
82 | |||
83 | In rules.mk: | ||
84 | |||
85 | ``` | ||
86 | PS2_MOUSE_ENABLE = yes | ||
87 | PS2_USE_INT = yes | ||
88 | ``` | ||
89 | |||
90 | In your keyboard config.h: | ||
91 | |||
92 | ```c | ||
93 | #define PS2_CLOCK_PIN A8 | ||
94 | #define PS2_DATA_PIN A9 | ||
95 | ``` | ||
96 | |||
97 | And in the chibios specifig halconf.h: | ||
98 | ```c | ||
99 | #define PAL_USE_CALLBACKS TRUE | ||
100 | ``` | ||
101 | |||
102 | |||
103 | ### USART Version :id=usart-version | ||
104 | |||
105 | To 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. | ||
106 | |||
107 | In rules.mk: | ||
108 | |||
109 | ```make | ||
110 | PS2_MOUSE_ENABLE = yes | ||
111 | PS2_USE_USART = yes | ||
112 | ``` | ||
113 | |||
114 | In your keyboard config.h: | ||
115 | |||
116 | ```c | ||
117 | #ifdef PS2_USE_USART | ||
118 | #define PS2_CLOCK_PIN D5 | ||
119 | #define PS2_DATA_PIN D2 | ||
120 | |||
121 | /* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ | ||
122 | /* set DDR of CLOCK as input to be slave */ | ||
123 | #define PS2_USART_INIT() do { \ | ||
124 | PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ | ||
125 | PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ | ||
126 | UCSR1C = ((1 << UMSEL10) | \ | ||
127 | (3 << UPM10) | \ | ||
128 | (0 << USBS1) | \ | ||
129 | (3 << UCSZ10) | \ | ||
130 | (0 << UCPOL1)); \ | ||
131 | UCSR1A = 0; \ | ||
132 | UBRR1H = 0; \ | ||
133 | UBRR1L = 0; \ | ||
134 | } while (0) | ||
135 | #define PS2_USART_RX_INT_ON() do { \ | ||
136 | UCSR1B = ((1 << RXCIE1) | \ | ||
137 | (1 << RXEN1)); \ | ||
138 | } while (0) | ||
139 | #define PS2_USART_RX_POLL_ON() do { \ | ||
140 | UCSR1B = (1 << RXEN1); \ | ||
141 | } while (0) | ||
142 | #define PS2_USART_OFF() do { \ | ||
143 | UCSR1C = 0; \ | ||
144 | UCSR1B &= ~((1 << RXEN1) | \ | ||
145 | (1 << TXEN1)); \ | ||
146 | } while (0) | ||
147 | #define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) | ||
148 | #define PS2_USART_RX_DATA UDR1 | ||
149 | #define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) | ||
150 | #define PS2_USART_RX_VECT USART1_RX_vect | ||
151 | #endif | ||
152 | ``` | ||
153 | |||
154 | ## Additional Settings :id=additional-settings | ||
155 | |||
156 | ### PS/2 Mouse Features :id=ps2-mouse-features | ||
157 | |||
158 | These enable settings supported by the PS/2 mouse protocol. | ||
159 | |||
160 | ```c | ||
161 | /* Use remote mode instead of the default stream mode (see link) */ | ||
162 | #define PS2_MOUSE_USE_REMOTE_MODE | ||
163 | |||
164 | /* Enable the scrollwheel or scroll gesture on your mouse or touchpad */ | ||
165 | #define PS2_MOUSE_ENABLE_SCROLLING | ||
166 | |||
167 | /* Some mice will need a scroll mask to be configured. The default is 0xFF. */ | ||
168 | #define PS2_MOUSE_SCROLL_MASK 0x0F | ||
169 | |||
170 | /* Applies a transformation to the movement before sending to the host (see link) */ | ||
171 | #define PS2_MOUSE_USE_2_1_SCALING | ||
172 | |||
173 | /* The time to wait after initializing the ps2 host */ | ||
174 | #define PS2_MOUSE_INIT_DELAY 1000 /* Default */ | ||
175 | ``` | ||
176 | |||
177 | You can also call the following functions from ps2_mouse.h | ||
178 | |||
179 | ```c | ||
180 | void ps2_mouse_disable_data_reporting(void); | ||
181 | |||
182 | void ps2_mouse_enable_data_reporting(void); | ||
183 | |||
184 | void ps2_mouse_set_remote_mode(void); | ||
185 | |||
186 | void ps2_mouse_set_stream_mode(void); | ||
187 | |||
188 | void ps2_mouse_set_scaling_2_1(void); | ||
189 | |||
190 | void ps2_mouse_set_scaling_1_1(void); | ||
191 | |||
192 | void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution); | ||
193 | |||
194 | void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate); | ||
195 | ``` | ||
196 | |||
197 | ### Fine Control :id=fine-control | ||
198 | |||
199 | Use the following defines to change the sensitivity and speed of the mouse. | ||
200 | Note: you can also use `ps2_mouse_set_resolution` for the same effect (not supported on most touchpads). | ||
201 | |||
202 | ```c | ||
203 | #define PS2_MOUSE_X_MULTIPLIER 3 | ||
204 | #define PS2_MOUSE_Y_MULTIPLIER 3 | ||
205 | #define PS2_MOUSE_V_MULTIPLIER 1 | ||
206 | ``` | ||
207 | |||
208 | ### Scroll Button :id=scroll-button | ||
209 | |||
210 | If you're using a trackpoint, you will likely want to be able to use it for scrolling. | ||
211 | It's possible to enable a "scroll button/s" that when pressed will cause the mouse to scroll instead of moving. | ||
212 | To enable the feature, you must set a scroll button mask as follows: | ||
213 | |||
214 | ```c | ||
215 | #define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE) /* Default */ | ||
216 | ``` | ||
217 | |||
218 | To disable the scroll button feature: | ||
219 | |||
220 | ```c | ||
221 | #define PS2_MOUSE_SCROLL_BTN_MASK 0 | ||
222 | ``` | ||
223 | |||
224 | The available buttons are: | ||
225 | |||
226 | ```c | ||
227 | #define PS2_MOUSE_BTN_LEFT 0 | ||
228 | #define PS2_MOUSE_BTN_RIGHT 1 | ||
229 | #define PS2_MOUSE_BTN_MIDDLE 2 | ||
230 | ``` | ||
231 | |||
232 | You can also combine buttons in the mask by `|`ing them together. | ||
233 | |||
234 | Once you've configured your scroll button mask, you must configure the scroll button send interval. | ||
235 | This is the interval before which if the scroll buttons were released they would be sent to the host. | ||
236 | After this interval, they will cause the mouse to scroll and will not be sent. | ||
237 | |||
238 | ```c | ||
239 | #define PS2_MOUSE_SCROLL_BTN_SEND 300 /* Default */ | ||
240 | ``` | ||
241 | |||
242 | To disable sending the scroll buttons: | ||
243 | |||
244 | ```c | ||
245 | #define PS2_MOUSE_SCROLL_BTN_SEND 0 | ||
246 | ``` | ||
247 | |||
248 | Fine control over the scrolling is supported with the following defines: | ||
249 | |||
250 | ```c | ||
251 | #define PS2_MOUSE_SCROLL_DIVISOR_H 2 | ||
252 | #define PS2_MOUSE_SCROLL_DIVISOR_V 2 | ||
253 | ``` | ||
254 | |||
255 | ### Invert Mouse buttons :id=invert-buttons | ||
256 | |||
257 | To invert the left & right buttons you can put: | ||
258 | |||
259 | ```c | ||
260 | #define PS2_MOUSE_INVERT_BUTTONS | ||
261 | ``` | ||
262 | |||
263 | into config.h. | ||
264 | |||
265 | ### Invert Mouse and Scroll Axes :id=invert-mouse-and-scroll-axes | ||
266 | |||
267 | To invert the X and Y axes you can put: | ||
268 | |||
269 | ```c | ||
270 | #define PS2_MOUSE_INVERT_X | ||
271 | #define PS2_MOUSE_INVERT_Y | ||
272 | ``` | ||
273 | |||
274 | into config.h. | ||
275 | |||
276 | To reverse the scroll axes you can put: | ||
277 | |||
278 | ```c | ||
279 | #define PS2_MOUSE_INVERT_H | ||
280 | #define PS2_MOUSE_INVERT_V | ||
281 | ``` | ||
282 | |||
283 | into config.h. | ||
284 | |||
285 | ### Rotate Mouse Axes :id=rotate-mouse-axes | ||
286 | |||
287 | Transform the output of the device with a clockwise rotation of 90, 180, or 270 | ||
288 | degrees. | ||
289 | |||
290 | When compensating for device orientation, rotate the output the same amount in | ||
291 | the opposite direction. E.g. if the normal device orientation is considered to | ||
292 | be North-facing, compensate as follows: | ||
293 | |||
294 | ```c | ||
295 | #define PS2_MOUSE_ROTATE 270 /* Compensate for East-facing device orientation. */ | ||
296 | ``` | ||
297 | ```c | ||
298 | #define PS2_MOUSE_ROTATE 180 /* Compensate for South-facing device orientation. */ | ||
299 | ``` | ||
300 | ```c | ||
301 | #define PS2_MOUSE_ROTATE 90 /* Compensate for West-facing device orientation. */ | ||
302 | ``` | ||
303 | |||
304 | ### Debug Settings :id=debug-settings | ||
305 | |||
306 | To debug the mouse, add `debug_mouse = true` or enable via bootmagic. | ||
307 | |||
308 | ```c | ||
309 | /* To debug the mouse reports */ | ||
310 | #define PS2_MOUSE_DEBUG_HID | ||
311 | #define PS2_MOUSE_DEBUG_RAW | ||
312 | ``` | ||
313 | |||
314 | ### Movement Hook :id=movement-hook | ||
315 | |||
316 | Process mouse movement in the keymap before it is sent to the host. Example | ||
317 | uses include filtering noise, adding acceleration, and automatically activating | ||
318 | a layer. To use, define the following function in your keymap: | ||
319 | |||
320 | ```c | ||
321 | void ps2_mouse_moved_user(report_mouse_t *mouse_report); | ||
322 | ``` | ||