diff options
Diffstat (limited to 'drivers/sensors/adns5050.c')
| -rw-r--r-- | drivers/sensors/adns5050.c | 157 | 
1 files changed, 90 insertions, 67 deletions
| 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);  } | 
