From 56e3f06a26851976e559aacf7a096c61403304be Mon Sep 17 00:00:00 2001 From: Drashna Jaelre Date: Sun, 14 Nov 2021 22:03:24 -0800 Subject: Rework and expand Pointing Device support (#14343) Co-authored-by: Dasky <32983009+daskygit@users.noreply.github.com> --- drivers/sensors/adns5050.c | 157 ++++++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 67 deletions(-) (limited to 'drivers/sensors/adns5050.c') diff --git a/drivers/sensors/adns5050.c b/drivers/sensors/adns5050.c index 254ef2ee87..c23d24d5af 100644 --- a/drivers/sensors/adns5050.c +++ b/drivers/sensors/adns5050.c @@ -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. @@ -108,17 +122,17 @@ 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 @@ -126,38 +140,38 @@ uint8_t adns_read_reg(uint8_t reg_addr) { // 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); @@ -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); } -- cgit v1.2.3