keyboard stuff
at master 356 lines 9.8 kB view raw view rendered
1# PS/2 Mouse Support {#ps2-mouse-support} 2 3Its possible to hook up a PS/2 mouse (for example touchpads or trackpoints) to your keyboard as a composite device. 4 5To 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 7There 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 {#the-circuitry-between-trackpoint-and-controller} 10 11To 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 | 19MODULE 5+ --------+--+--------- PWR CONTROLLER 20 | 21 4.7K 22 | 23 CLK ------+------------ PIN 24``` 25 26## Driver Configuration {#driver-configuration} 27 28Driver selection can be configured in `rules.mk` as `PS2_DRIVER`, or in `info.json` as `ps2.driver`. Valid values are `busywait` (default), `interrupt`, `usart`, or `vendor`. See below for information on individual drivers. 29 30### Busywait Driver {#busywait-driver} 31 32Note: This is not recommended, you may encounter jerky movement or unsent inputs. Please use interrupt or USART version if possible. 33 34In rules.mk: 35 36```make 37PS2_MOUSE_ENABLE = yes 38PS2_ENABLE = yes 39PS2_DRIVER = busywait 40``` 41 42In your keyboard config.h: 43 44```c 45#ifdef PS2_DRIVER_BUSYWAIT 46# define PS2_CLOCK_PIN D1 47# define PS2_DATA_PIN D2 48#endif 49``` 50 51### Interrupt Driver (AVR/ATMega32u4) {#interrupt-driver-avr} 52 53The 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. 54 55In rules.mk: 56 57```make 58PS2_MOUSE_ENABLE = yes 59PS2_ENABLE = yes 60PS2_DRIVER = interrupt 61``` 62 63In your keyboard config.h: 64 65```c 66#ifdef PS2_DRIVER_INTERRUPT 67#define PS2_CLOCK_PIN D2 68#define PS2_DATA_PIN D5 69 70#define PS2_INT_INIT() do { \ 71 EICRA |= ((1<<ISC21) | \ 72 (0<<ISC20)); \ 73} while (0) 74#define PS2_INT_ON() do { \ 75 EIMSK |= (1<<INT2); \ 76} while (0) 77#define PS2_INT_OFF() do { \ 78 EIMSK &= ~(1<<INT2); \ 79} while (0) 80#define PS2_INT_VECT INT2_vect 81#endif 82``` 83 84### Interrupt Driver (ARM chibios) {#interrupt-driver-chibios} 85 86Pretty 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. 87 88In rules.mk: 89 90``` 91PS2_MOUSE_ENABLE = yes 92PS2_ENABLE = yes 93PS2_DRIVER = interrupt 94``` 95 96In your keyboard `config.h`: 97 98```c 99#define PS2_CLOCK_PIN A8 100#define PS2_DATA_PIN A9 101``` 102 103And in the ChibiOS specific `halconf.h`: 104 105```c 106#pragma once 107 108#define PAL_USE_CALLBACKS TRUE // [!code focus] 109 110#include_next <halconf.h> 111``` 112 113### USART Driver {#usart-driver} 114 115To 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. 116 117In rules.mk: 118 119```make 120PS2_MOUSE_ENABLE = yes 121PS2_ENABLE = yes 122PS2_DRIVER = usart 123``` 124 125In your keyboard config.h: 126 127```c 128#ifdef PS2_DRIVER_USART 129#define PS2_CLOCK_PIN D5 130#define PS2_DATA_PIN D2 131 132/* synchronous, odd parity, 1-bit stop, 8-bit data, sample at falling edge */ 133/* set DDR of CLOCK as input to be slave */ 134#define PS2_USART_INIT() do { \ 135 PS2_CLOCK_DDR &= ~(1<<PS2_CLOCK_BIT); \ 136 PS2_DATA_DDR &= ~(1<<PS2_DATA_BIT); \ 137 UCSR1C = ((1 << UMSEL10) | \ 138 (3 << UPM10) | \ 139 (0 << USBS1) | \ 140 (3 << UCSZ10) | \ 141 (0 << UCPOL1)); \ 142 UCSR1A = 0; \ 143 UBRR1H = 0; \ 144 UBRR1L = 0; \ 145} while (0) 146#define PS2_USART_RX_INT_ON() do { \ 147 UCSR1B = ((1 << RXCIE1) | \ 148 (1 << RXEN1)); \ 149} while (0) 150#define PS2_USART_RX_POLL_ON() do { \ 151 UCSR1B = (1 << RXEN1); \ 152} while (0) 153#define PS2_USART_OFF() do { \ 154 UCSR1C = 0; \ 155 UCSR1B &= ~((1 << RXEN1) | \ 156 (1 << TXEN1)); \ 157} while (0) 158#define PS2_USART_RX_READY (UCSR1A & (1<<RXC1)) 159#define PS2_USART_RX_DATA UDR1 160#define PS2_USART_ERROR (UCSR1A & ((1<<FE1) | (1<<DOR1) | (1<<UPE1))) 161#define PS2_USART_RX_VECT USART1_RX_vect 162#endif 163``` 164 165### RP2040 PIO Driver {#rp2040-pio-driver} 166 167The `PIO` subsystem is a Raspberry Pi RP2040 specific implementation, using the integrated PIO peripheral and is therefore only available on this MCU. 168 169There are strict requirements for pin ordering but any pair of GPIO pins can be used. The GPIO used for clock must be directly after data, see the included info.json snippet for an example of correct order. 170 171You may optionally switch the PIO peripheral used with the following define in config.h: 172```c 173#define PS2_PIO_USE_PIO1 // Force the usage of PIO1 peripheral, by default the PS2 implementation uses the PIO0 peripheral 174``` 175 176Example info.json content: 177 178```json 179 "ps2": { 180 "clock_pin": "GP1", 181 "data_pin": "GP0", 182 "driver": "vendor", 183 "enabled": true, 184 "mouse_enabled": true 185 } 186``` 187 188## Additional Settings {#additional-settings} 189 190### PS/2 Mouse Features {#ps2-mouse-features} 191 192These enable settings supported by the PS/2 mouse protocol. 193 194```c 195/* Use remote mode instead of the default stream mode (see link) */ 196#define PS2_MOUSE_USE_REMOTE_MODE 197 198/* Enable the scrollwheel or scroll gesture on your mouse or touchpad */ 199#define PS2_MOUSE_ENABLE_SCROLLING 200 201/* Some mice will need a scroll mask to be configured. The default is 0xFF. */ 202#define PS2_MOUSE_SCROLL_MASK 0x0F 203 204/* Applies a transformation to the movement before sending to the host (see link) */ 205#define PS2_MOUSE_USE_2_1_SCALING 206 207/* The time to wait after initializing the ps2 host */ 208#define PS2_MOUSE_INIT_DELAY 1000 /* Default */ 209``` 210 211You can also call the following functions from ps2_mouse.h 212 213```c 214void ps2_mouse_disable_data_reporting(void); 215 216void ps2_mouse_enable_data_reporting(void); 217 218void ps2_mouse_set_remote_mode(void); 219 220void ps2_mouse_set_stream_mode(void); 221 222void ps2_mouse_set_scaling_2_1(void); 223 224void ps2_mouse_set_scaling_1_1(void); 225 226void ps2_mouse_set_resolution(ps2_mouse_resolution_t resolution); 227 228void ps2_mouse_set_sample_rate(ps2_mouse_sample_rate_t sample_rate); 229``` 230 231### Fine Control {#fine-control} 232 233Use the following defines to change the sensitivity and speed of the mouse. 234Note: you can also use `ps2_mouse_set_resolution` for the same effect (not supported on most touchpads). 235 236```c 237#define PS2_MOUSE_X_MULTIPLIER 3 238#define PS2_MOUSE_Y_MULTIPLIER 3 239#define PS2_MOUSE_V_MULTIPLIER 1 240``` 241 242### Scroll Button {#scroll-button} 243 244If you're using a trackpoint, you will likely want to be able to use it for scrolling. 245It's possible to enable a "scroll button/s" that when pressed will cause the mouse to scroll instead of moving. 246To enable the feature, you must set a scroll button mask as follows: 247 248```c 249#define PS2_MOUSE_SCROLL_BTN_MASK (1<<PS2_MOUSE_BTN_MIDDLE) /* Default */ 250``` 251 252To disable the scroll button feature: 253 254```c 255#define PS2_MOUSE_SCROLL_BTN_MASK 0 256``` 257 258The available buttons are: 259 260```c 261#define PS2_MOUSE_BTN_LEFT 0 262#define PS2_MOUSE_BTN_RIGHT 1 263#define PS2_MOUSE_BTN_MIDDLE 2 264``` 265 266You can also combine buttons in the mask by `|`ing them together. 267 268Once you've configured your scroll button mask, you must configure the scroll button send interval. 269This is the interval before which if the scroll buttons were released they would be sent to the host. 270After this interval, they will cause the mouse to scroll and will not be sent. 271 272```c 273#define PS2_MOUSE_SCROLL_BTN_SEND 300 /* Default */ 274``` 275 276To disable sending the scroll buttons: 277 278```c 279#define PS2_MOUSE_SCROLL_BTN_SEND 0 280``` 281 282Fine control over the scrolling is supported with the following defines: 283 284```c 285#define PS2_MOUSE_SCROLL_DIVISOR_H 2 286#define PS2_MOUSE_SCROLL_DIVISOR_V 2 287``` 288 289### Invert Mouse buttons {#invert-buttons} 290 291To invert the left & right buttons you can put: 292 293```c 294#define PS2_MOUSE_INVERT_BUTTONS 295``` 296 297into config.h. 298 299### Invert Mouse and Scroll Axes {#invert-mouse-and-scroll-axes} 300 301To invert the X and Y axes you can put: 302 303```c 304#define PS2_MOUSE_INVERT_X 305#define PS2_MOUSE_INVERT_Y 306``` 307 308into config.h. 309 310To reverse the scroll axes you can put: 311 312```c 313#define PS2_MOUSE_INVERT_H 314#define PS2_MOUSE_INVERT_V 315``` 316 317into config.h. 318 319### Rotate Mouse Axes {#rotate-mouse-axes} 320 321Transform the output of the device with a clockwise rotation of 90, 180, or 270 322degrees. 323 324When compensating for device orientation, rotate the output the same amount in 325the opposite direction. E.g. if the normal device orientation is considered to 326be North-facing, compensate as follows: 327 328```c 329#define PS2_MOUSE_ROTATE 270 /* Compensate for East-facing device orientation. */ 330``` 331```c 332#define PS2_MOUSE_ROTATE 180 /* Compensate for South-facing device orientation. */ 333``` 334```c 335#define PS2_MOUSE_ROTATE 90 /* Compensate for West-facing device orientation. */ 336``` 337 338### Debug Settings {#debug-settings} 339 340To debug the mouse, add `debug_mouse = true` or enable via bootmagic. 341 342```c 343/* To debug the mouse reports */ 344#define PS2_MOUSE_DEBUG_HID 345#define PS2_MOUSE_DEBUG_RAW 346``` 347 348### Movement Hook {#movement-hook} 349 350Process mouse movement in the keymap before it is sent to the host. Example 351uses include filtering noise, adding acceleration, and automatically activating 352a layer. To use, define the following function in your keymap: 353 354```c 355void ps2_mouse_moved_user(report_mouse_t *mouse_report); 356```