Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework and expand Pointing Device support #14343

Merged
merged 92 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
20b6892
Add _DRIVERS support
drashna Feb 17, 2021
3d15cc8
Add drivers
drashna Feb 17, 2021
9025e96
Add prototypes for kb/user callbacks
drashna Feb 17, 2021
6120e6c
Add include for i2c stuff
drashna Feb 17, 2021
84c37ed
add comments, remove ifdefs
drashna Feb 17, 2021
53560ae
Clean up pimoroni code a bit
drashna Sep 7, 2021
5110bca
Remove pointing device code from pimoroni
drashna Sep 7, 2021
26381a0
Update pimoroni code
drashna Sep 7, 2021
46ef902
Update pmw330 code
drashna Sep 7, 2021
bf519de
Fix Typo
drashna Sep 7, 2021
cb5424f
Add a few bug fixes
drashna Sep 7, 2021
1ee737a
fix compilation issues
drashna Sep 7, 2021
0ca6eea
Convert PloopyCo Mouse
drashna Sep 7, 2021
81e965c
Convert PloopyCo Trackball Classic
drashna Sep 7, 2021
6758b3d
add include to qunatum
drashna Sep 7, 2021
b7ddb61
Fix includes
drashna Sep 7, 2021
3fa04ee
fix compilation issues for pimoroni
drashna Sep 7, 2021
f83887b
tweak includes
drashna Sep 7, 2021
39cedce
Fix sensor file include
drashna Sep 7, 2021
8a8b780
Get adns9800 working
drashna Sep 7, 2021
eb136ca
Update oddball config
drashna Sep 7, 2021
716af93
Update adns5050 code
drashna Sep 7, 2021
ba592bd
Update Ploopy trackballs for adns5050
drashna Sep 7, 2021
0174f3b
cleanup
drashna Sep 7, 2021
fa579cf
Fix function calls in ploopy trackball
drashna Sep 7, 2021
022a26d
better handle custom driver
drashna Sep 7, 2021
16fae45
fix tractyl manuform code
drashna Sep 7, 2021
9d4c4a2
fix pimoroni trackball (#42)
daskygit Sep 7, 2021
b8c6dd8
Add Analog Joystick
drashna Sep 7, 2021
55b2d3d
Convert 40percentclub nano keymap
drashna Sep 7, 2021
bda6f03
Minor cleanup
drashna Sep 7, 2021
769ae5e
Add cpi stuff
drashna Sep 8, 2021
8d12ba0
CPI changes
drashna Sep 8, 2021
9d42dd8
Apply cpi changes to keyboards
drashna Sep 8, 2021
0687fd8
Fix analog joystick report
drashna Sep 9, 2021
eac4e4b
Add support for Cirque tm040040
drashna Sep 9, 2021
08e3537
Add some additional fixes
drashna Sep 9, 2021
a0e9553
Add cpi/scaling for cirque
drashna Sep 9, 2021
4725342
Add mousekey coexistence code
drashna Sep 9, 2021
071bac2
Add rotation and inversion of reports
drashna Sep 20, 2021
2bacb3f
Add callback for button handling
drashna Sep 20, 2021
d0a1985
Add button handling function to existing devices
drashna Sep 20, 2021
191f41c
Fix adns5050 defines
drashna Sep 20, 2021
e64c5f6
Fix up defines for adns9800
drashna Sep 20, 2021
efa5d41
Fix analog joystick defines
drashna Sep 20, 2021
1d250e3
Fix up cirque trackpad and naming
drashna Sep 20, 2021
a04278f
Fixup pimoroni code
drashna Sep 20, 2021
ec4f8ac
Fixup CPI code
drashna Sep 20, 2021
e88bf72
Cleanup
drashna Sep 20, 2021
f21c127
fix handle button function
drashna Sep 20, 2021
d12e71f
Update documentation
drashna Sep 20, 2021
c76ed8b
Fix rotatin for adns5050 based ploopy devices
drashna Sep 20, 2021
7a7b287
Fix DPI values for adns 5050 based Ploopy devices
drashna Sep 20, 2021
d8a000d
Fix casting for process mouse functions
drashna Sep 20, 2021
55b53a5
Fix typo in docs
drashna Sep 20, 2021
3881f50
suspend hack for pointing devices
drashna Sep 20, 2021
c9b7b16
Add additional doc fixes
drashna Sep 20, 2021
78972f6
Add defaults for CPI
drashna Sep 20, 2021
2207033
Use Shorter Debug info
drashna Sep 21, 2021
ab08877
Fixup debug printing
drashna Sep 22, 2021
137c802
Cleanup some functions
drashna Sep 29, 2021
e059d53
Convert Oddball keyboard
drashna Sep 29, 2021
afe78c3
Add support for motion pin on sensors
drashna Sep 29, 2021
c2e8b42
Fix Typos for inversion
drashna Sep 29, 2021
52e2beb
Fix issue with mousekeys
drashna Sep 29, 2021
b112840
Update tractyl manuform with newer schema
drashna Sep 30, 2021
0cfdad6
Use hierarchical branching for reports
drashna Sep 30, 2021
1523da0
Update Ploopy code
drashna Sep 30, 2021
9ddd054
Update grandiceps config
drashna Sep 30, 2021
4027958
Fix config for pimoroni
drashna Sep 30, 2021
e5d1617
Add driver define
drashna Sep 30, 2021
26a0e2e
Rename Cirque trackpad code to more closely reflect the hardware
drashna Oct 3, 2021
eee627d
Add different type handling
drashna Oct 3, 2021
13fc3df
Add support for i2c and spi cirque
drashna Oct 3, 2021
be39f3d
Update documentation for cirque
drashna Oct 3, 2021
95a6fe2
Fix compilation issue with i2c drivers
drashna Oct 5, 2021
beaddd7
Add support for legacy defines
drashna Oct 6, 2021
40cd7b7
Fix Cirque not working
drashna Oct 7, 2021
9b8867c
Improve Cirque code
drashna Oct 7, 2021
714d8b5
Fix clicking for cirque trackpad
drashna Oct 7, 2021
25f1529
Misc tapping fixes
drashna Oct 7, 2021
21445aa
Allow pmw3360 firmware to be configurable
drashna Oct 12, 2021
cef141b
Fix issues with cirque tapping
drashna Oct 13, 2021
8b67937
Add comment to pmw3360 firmware define
drashna Oct 13, 2021
99928a4
Add proper support for get tapping term
drashna Oct 13, 2021
c543f98
fix formattiing
drashna Oct 31, 2021
9bcd486
Fix adns9800 firmware name
drashna Nov 3, 2021
6ae53c6
Update drivers/sensors/adns9800.c
drashna Nov 4, 2021
ffc8580
Fix typo in adns5050
drashna Nov 13, 2021
38c1ce0
clean up formatting in adns9800.c
drashna Nov 13, 2021
b6a1e2a
Fix up docs based on feedback
drashna Nov 15, 2021
d05869d
Use memcmp for report changes
drashna Nov 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,43 @@ ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
SRC += $(QUANTUM_DIR)/mousekey.c
endif

VALID_POINTING_DEVICE_DRIVER_TYPES := adns5050 adns9800 analog_joystick cirque_pinnacle_i2c cirque_pinnacle_spi pmw3360 pimoroni_trackball custom
POINTING_DEVICE_DRIVER ?= custom
ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
OPT_DEFS += -DPOINTING_DEVICE_ENABLE
MOUSE_ENABLE := yes
SRC += $(QUANTUM_DIR)/pointing_device.c
ifeq ($(filter $(POINTING_DEVICE_DRIVER),$(VALID_POINTING_DEVICE_DRIVER_TYPES)),)
$(error POINTING_DEVICE_DRIVER="$(POINTING_DEVICE_DRIVER)" is not a valid pointing device type)
else
OPT_DEFS += -DPOINTING_DEVICE_ENABLE
MOUSE_ENABLE := yes
SRC += $(QUANTUM_DIR)/pointing_device.c
SRC += $(QUANTUM_DIR)/pointing_device_drivers.c
ifneq ($(strip $(POINTING_DEVICE_DRIVER)), custom)
SRC += drivers/sensors/$(strip $(POINTING_DEVICE_DRIVER)).c
OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(shell echo $(POINTING_DEVICE_DRIVER) | tr '[:lower:]' '[:upper:]'))
endif
OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(POINTING_DEVICE_DRIVER))
ifeq ($(strip $(POINTING_DEVICE_DRIVER)), adns9800)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
QUANTUM_LIB_SRC += spi_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), analog_joystick)
OPT_DEFS += -DSTM32_ADC -DHAL_USE_ADC=TRUE
LIB_SRC += analog.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_i2c)
OPT_DEFS += -DSTM32_I2C -DHAL_USE_I2C=TRUE
SRC += drivers/sensors/cirque_pinnacle.c
QUANTUM_LIB_SRC += i2c_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), cirque_pinnacle_spi)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
SRC += drivers/sensors/cirque_pinnacle.c
QUANTUM_LIB_SRC += spi_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pimoroni_trackball)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_I2C=TRUE
QUANTUM_LIB_SRC += i2c_master.c
else ifeq ($(strip $(POINTING_DEVICE_DRIVER)), pmw3360)
OPT_DEFS += -DSTM32_SPI -DHAL_USE_SPI=TRUE
QUANTUM_LIB_SRC += spi_master.c
endif
endif
endif

VALID_EEPROM_DRIVER_TYPES := vendor custom transient i2c spi
Expand Down
202 changes: 196 additions & 6 deletions docs/feature_pointing_device.md

Large diffs are not rendered by default.

157 changes: 90 additions & 67 deletions drivers/sensors/adns5050.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,81 +20,95 @@
#include "adns5050.h"
#include "wait.h"
#include "debug.h"
#include "print.h"
#include "gpio.h"

#ifndef OPTIC_ROTATED
# define OPTIC_ROTATED false
#endif

// Definitions for the ADNS serial line.
#ifndef ADNS_SCLK_PIN
# define ADNS_SCLK_PIN B7
#endif

#ifndef ADNS_SDIO_PIN
# define ADNS_SDIO_PIN C6
#endif

#ifndef ADNS_CS_PIN
# define ADNS_CS_PIN B4
#endif

#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte) { dprintf("%c%c%c%c%c%c%c%c|", (byte & 0x80 ? '1' : '0'), (byte & 0x40 ? '1' : '0'), (byte & 0x20 ? '1' : '0'), (byte & 0x10 ? '1' : '0'), (byte & 0x08 ? '1' : '0'), (byte & 0x04 ? '1' : '0'), (byte & 0x02 ? '1' : '0'), (byte & 0x01 ? '1' : '0')); }
#endif

// Initialize the ADNS serial pins.
void adns_init(void) {
setPinOutput(ADNS_SCLK_PIN);
setPinOutput(ADNS_SDIO_PIN);
setPinOutput(ADNS_CS_PIN);
// Registers
// clang-format off
#define REG_PRODUCT_ID 0x00
#define REG_REVISION_ID 0x01
#define REG_MOTION 0x02
#define REG_DELTA_X 0x03
#define REG_DELTA_Y 0x04
#define REG_SQUAL 0x05
#define REG_SHUTTER_UPPER 0x06
#define REG_SHUTTER_LOWER 0x07
#define REG_MAXIMUM_PIXEL 0x08
#define REG_PIXEL_SUM 0x09
#define REG_MINIMUM_PIXEL 0x0a
#define REG_PIXEL_GRAB 0x0b
#define REG_MOUSE_CONTROL 0x0d
#define REG_MOUSE_CONTROL2 0x19
#define REG_LED_DC_MODE 0x22
#define REG_CHIP_RESET 0x3a
#define REG_PRODUCT_ID2 0x3e
#define REG_INV_REV_ID 0x3f
#define REG_MOTION_BURST 0x63
// clang-format on

void adns5050_init(void) {
// Initialize the ADNS serial pins.
setPinOutput(ADNS5050_SCLK_PIN);
setPinOutput(ADNS5050_SDIO_PIN);
setPinOutput(ADNS5050_CS_PIN);

// reboot the adns.
// if the adns hasn't initialized yet, this is harmless.
adns5050_write_reg(REG_CHIP_RESET, 0x5a);

// wait maximum time before adns is ready.
// this ensures that the adns is actuall ready after reset.
wait_ms(55);

// read a burst from the adns and then discard it.
// gets the adns ready for write commands
// (for example, setting the dpi).
adns5050_read_burst();
}

// Perform a synchronization with the ADNS.
// Just as with the serial protocol, this is used by the slave to send a
// synchronization signal to the master.
void adns_sync(void) {
writePinLow(ADNS_CS_PIN);
void adns5050_sync(void) {
writePinLow(ADNS5050_CS_PIN);
wait_us(1);
writePinHigh(ADNS_CS_PIN);
writePinHigh(ADNS5050_CS_PIN);
}

void adns_cs_select(void) { writePinLow(ADNS_CS_PIN); }
void adns5050_cs_select(void) { writePinLow(ADNS5050_CS_PIN); }

void adns_cs_deselect(void) { writePinHigh(ADNS_CS_PIN); }
void adns5050_cs_deselect(void) { writePinHigh(ADNS5050_CS_PIN); }

uint8_t adns_serial_read(void) {
setPinInput(ADNS_SDIO_PIN);
uint8_t adns5050_serial_read(void) {
setPinInput(ADNS5050_SDIO_PIN);
uint8_t byte = 0;

for (uint8_t i = 0; i < 8; ++i) {
writePinLow(ADNS_SCLK_PIN);
writePinLow(ADNS5050_SCLK_PIN);
wait_us(1);

byte = (byte << 1) | readPin(ADNS_SDIO_PIN);
byte = (byte << 1) | readPin(ADNS5050_SDIO_PIN);

writePinHigh(ADNS_SCLK_PIN);
writePinHigh(ADNS5050_SCLK_PIN);
wait_us(1);
}

return byte;
}

void adns_serial_write(uint8_t data) {
setPinOutput(ADNS_SDIO_PIN);
void adns5050_serial_write(uint8_t data) {
setPinOutput(ADNS5050_SDIO_PIN);

for (int8_t b = 7; b >= 0; b--) {
writePinLow(ADNS_SCLK_PIN);
writePinLow(ADNS5050_SCLK_PIN);

if (data & (1 << b))
writePinHigh(ADNS_SDIO_PIN);
writePinHigh(ADNS5050_SDIO_PIN);
else
writePinLow(ADNS_SDIO_PIN);
writePinLow(ADNS5050_SDIO_PIN);

wait_us(2);

writePinHigh(ADNS_SCLK_PIN);
writePinHigh(ADNS5050_SCLK_PIN);
}

// tSWR. See page 15 of the ADNS spec sheet.
Expand All @@ -108,56 +122,56 @@ void adns_serial_write(uint8_t data) {

// Read a byte of data from a register on the ADNS.
// Don't forget to use the register map (as defined in the header file).
uint8_t adns_read_reg(uint8_t reg_addr) {
adns_cs_select();
uint8_t adns5050_read_reg(uint8_t reg_addr) {
adns5050_cs_select();

adns_serial_write(reg_addr);
adns5050_serial_write(reg_addr);

// We don't need a minimum tSRAD here. That's because a 4ms wait time is
// already included in adns_serial_write(), so we're good.
// already included in adns5050_serial_write(), so we're good.
// See page 10 and 15 of the ADNS spec sheet.
// wait_us(4);

uint8_t byte = adns_serial_read();
uint8_t byte = adns5050_serial_read();

// tSRW & tSRR. See page 15 of the ADNS spec sheet.
// Technically, this is only necessary if the next operation is an SDIO
// read or write. This is not guaranteed to be the case.
// Honestly, this wait could probably be removed.
wait_us(1);

adns_cs_deselect();
adns5050_cs_deselect();

return byte;
}

void adns_write_reg(uint8_t reg_addr, uint8_t data) {
adns_cs_select();
adns_serial_write(0b10000000 | reg_addr);
adns_serial_write(data);
adns_cs_deselect();
void adns5050_write_reg(uint8_t reg_addr, uint8_t data) {
adns5050_cs_select();
adns5050_serial_write(0b10000000 | reg_addr);
adns5050_serial_write(data);
adns5050_cs_deselect();
}

report_adns_t adns_read_burst(void) {
adns_cs_select();
report_adns5050_t adns5050_read_burst(void) {
adns5050_cs_select();

report_adns_t data;
report_adns5050_t data;
data.dx = 0;
data.dy = 0;

adns_serial_write(REG_MOTION_BURST);
adns5050_serial_write(REG_MOTION_BURST);

// We don't need a minimum tSRAD here. That's because a 4ms wait time is
// already included in adns_serial_write(), so we're good.
// already included in adns5050_serial_write(), so we're good.
// See page 10 and 15 of the ADNS spec sheet.
// wait_us(4);

uint8_t x = adns_serial_read();
uint8_t y = adns_serial_read();
uint8_t x = adns5050_serial_read();
uint8_t y = adns5050_serial_read();

// Burst mode returns a bunch of other shit that we don't really need.
// Setting CS to high ends burst mode early.
adns_cs_deselect();
adns5050_cs_deselect();

data.dx = convert_twoscomp(x);
data.dy = convert_twoscomp(y);
Expand All @@ -175,12 +189,21 @@ int8_t convert_twoscomp(uint8_t data) {
}

// Don't forget to use the definitions for CPI in the header file.
void adns_set_cpi(uint8_t cpi) { adns_write_reg(REG_MOUSE_CONTROL2, cpi); }
void adns5050_set_cpi(uint16_t cpi) {
uint8_t cpival = constrain((cpi / 125), 0x1, 0xD); // limits to 0--119

adns5050_write_reg(REG_MOUSE_CONTROL2, 0b10000 | cpival);
}

uint16_t adns5050_get_cpi(void) {
uint8_t cpival = adns5050_read_reg(REG_MOUSE_CONTROL2);
return (uint16_t)((cpival & 0b10000) * 125);
}

bool adns_check_signature(void) {
uint8_t pid = adns_read_reg(REG_PRODUCT_ID);
uint8_t rid = adns_read_reg(REG_REVISION_ID);
uint8_t pid2 = adns_read_reg(REG_PRODUCT_ID2);
bool adns5050_check_signature(void) {
uint8_t pid = adns5050_read_reg(REG_PRODUCT_ID);
uint8_t rid = adns5050_read_reg(REG_REVISION_ID);
uint8_t pid2 = adns5050_read_reg(REG_PRODUCT_ID2);

return (pid == 0x12 && rid == 0x01 && pid2 == 0x26);
}
75 changes: 34 additions & 41 deletions drivers/sensors/adns5050.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,52 @@

#include <stdbool.h>

// Registers
#define REG_PRODUCT_ID 0x00
#define REG_REVISION_ID 0x01
#define REG_MOTION 0x02
#define REG_DELTA_X 0x03
#define REG_DELTA_Y 0x04
#define REG_SQUAL 0x05
#define REG_SHUTTER_UPPER 0x06
#define REG_SHUTTER_LOWER 0x07
#define REG_MAXIMUM_PIXEL 0x08
#define REG_PIXEL_SUM 0x09
#define REG_MINIMUM_PIXEL 0x0a
#define REG_PIXEL_GRAB 0x0b
#define REG_MOUSE_CONTROL 0x0d
#define REG_MOUSE_CONTROL2 0x19
#define REG_LED_DC_MODE 0x22
#define REG_CHIP_RESET 0x3a
#define REG_PRODUCT_ID2 0x3e
#define REG_INV_REV_ID 0x3f
#define REG_MOTION_BURST 0x63

// CPI values
#define CPI125 0x11
#define CPI250 0x12
#define CPI375 0x13
#define CPI500 0x14
#define CPI625 0x15
#define CPI750 0x16
#define CPI875 0x17
// clang-format off
#define CPI125 0x11
#define CPI250 0x12
#define CPI375 0x13
#define CPI500 0x14
#define CPI625 0x15
#define CPI750 0x16
#define CPI875 0x17
#define CPI1000 0x18
#define CPI1125 0x19
#define CPI1250 0x1a
#define CPI1375 0x1b
// clang-format on

#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))

// Definitions for the ADNS serial line.
#ifndef ADNS5050_SCLK_PIN
# error "No clock pin defined -- missing ADNS5050_SCLK_PIN"
#endif

#ifndef ADNS5050_SDIO_PIN
# error "No data pin defined -- missing ADNS5050_SDIO_PIN"
#endif

#ifdef CONSOLE_ENABLE
void print_byte(uint8_t byte);
#ifndef ADNS5050_CS_PIN
# error "No chip select pin defined -- missing ADNS5050_CS_PIN"
#endif

typedef struct {
int8_t dx;
int8_t dy;
} report_adns_t;
} report_adns5050_t;

// A bunch of functions to implement the ADNS5050-specific serial protocol.
// Note that the "serial.h" driver is insufficient, because it does not
// manually manipulate a serial clock signal.
void adns_init(void);
void adns_sync(void);
uint8_t adns_serial_read(void);
void adns_serial_write(uint8_t data);
uint8_t adns_read_reg(uint8_t reg_addr);
void adns_write_reg(uint8_t reg_addr, uint8_t data);
report_adns_t adns_read_burst(void);
int8_t convert_twoscomp(uint8_t data);
void adns_set_cpi(uint8_t cpi);
bool adns_check_signature(void);
void adns5050_init(void);
void adns5050_sync(void);
uint8_t adns5050_serial_read(void);
void adns5050_serial_write(uint8_t data);
uint8_t adns5050_read_reg(uint8_t reg_addr);
void adns5050_write_reg(uint8_t reg_addr, uint8_t data);
report_adns5050_t adns5050_read_burst(void);
void adns5050_set_cpi(uint16_t cpi);
uint16_t adns5050_get_cpi(void);
int8_t convert_twoscomp(uint8_t data);
bool adns5050_check_signature(void);
Loading