diff options
Diffstat (limited to 'drivers/sensors/adns5050.c')
| -rw-r--r-- | drivers/sensors/adns5050.c | 166 |
1 files changed, 91 insertions, 75 deletions
diff --git a/drivers/sensors/adns5050.c b/drivers/sensors/adns5050.c index e7273977d..c23d24d5a 100644 --- a/drivers/sensors/adns5050.c +++ b/drivers/sensors/adns5050.c | |||
| @@ -17,89 +17,98 @@ | |||
| 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | |||
| 21 | #include "adns5050.h" | 20 | #include "adns5050.h" |
| 22 | #include "wait.h" | 21 | #include "wait.h" |
| 23 | #include "debug.h" | 22 | #include "debug.h" |
| 24 | #include "print.h" | ||
| 25 | #include "gpio.h" | 23 | #include "gpio.h" |
| 26 | 24 | ||
| 27 | #ifndef OPTIC_ROTATED | 25 | // Registers |
| 28 | # define OPTIC_ROTATED false | 26 | // clang-format off |
| 29 | #endif | 27 | #define REG_PRODUCT_ID 0x00 |
| 30 | 28 | #define REG_REVISION_ID 0x01 | |
| 31 | // Definitions for the ADNS serial line. | 29 | #define REG_MOTION 0x02 |
| 32 | #ifndef ADNS_SCLK_PIN | 30 | #define REG_DELTA_X 0x03 |
| 33 | # define ADNS_SCLK_PIN B7 | 31 | #define REG_DELTA_Y 0x04 |
| 34 | #endif | 32 | #define REG_SQUAL 0x05 |
| 35 | 33 | #define REG_SHUTTER_UPPER 0x06 | |
| 36 | #ifndef ADNS_SDIO_PIN | 34 | #define REG_SHUTTER_LOWER 0x07 |
| 37 | # define ADNS_SDIO_PIN C6 | 35 | #define REG_MAXIMUM_PIXEL 0x08 |
| 38 | #endif | 36 | #define REG_PIXEL_SUM 0x09 |
| 39 | 37 | #define REG_MINIMUM_PIXEL 0x0a | |
| 40 | #ifndef ADNS_CS_PIN | 38 | #define REG_PIXEL_GRAB 0x0b |
| 41 | # define ADNS_CS_PIN B4 | 39 | #define REG_MOUSE_CONTROL 0x0d |
| 42 | #endif | 40 | #define REG_MOUSE_CONTROL2 0x19 |
| 43 | 41 | #define REG_LED_DC_MODE 0x22 | |
| 44 | #ifdef CONSOLE_ENABLE | 42 | #define REG_CHIP_RESET 0x3a |
| 45 | 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')); } | 43 | #define REG_PRODUCT_ID2 0x3e |
| 46 | #endif | 44 | #define REG_INV_REV_ID 0x3f |
| 47 | 45 | #define REG_MOTION_BURST 0x63 | |
| 48 | // Initialize the ADNS serial pins. | 46 | // clang-format on |
| 49 | void adns_init(void) { | 47 | |
| 50 | setPinOutput(ADNS_SCLK_PIN); | 48 | void adns5050_init(void) { |
| 51 | setPinOutput(ADNS_SDIO_PIN); | 49 | // Initialize the ADNS serial pins. |
| 52 | setPinOutput(ADNS_CS_PIN); | 50 | setPinOutput(ADNS5050_SCLK_PIN); |
| 51 | setPinOutput(ADNS5050_SDIO_PIN); | ||
| 52 | setPinOutput(ADNS5050_CS_PIN); | ||
| 53 | |||
| 54 | // reboot the adns. | ||
| 55 | // if the adns hasn't initialized yet, this is harmless. | ||
| 56 | adns5050_write_reg(REG_CHIP_RESET, 0x5a); | ||
| 57 | |||
| 58 | // wait maximum time before adns is ready. | ||
| 59 | // this ensures that the adns is actuall ready after reset. | ||
| 60 | wait_ms(55); | ||
| 61 | |||
| 62 | // read a burst from the adns and then discard it. | ||
| 63 | // gets the adns ready for write commands | ||
| 64 | // (for example, setting the dpi). | ||
| 65 | adns5050_read_burst(); | ||
| 53 | } | 66 | } |
| 54 | 67 | ||
| 55 | // Perform a synchronization with the ADNS. | 68 | // Perform a synchronization with the ADNS. |
| 56 | // Just as with the serial protocol, this is used by the slave to send a | 69 | // Just as with the serial protocol, this is used by the slave to send a |
| 57 | // synchronization signal to the master. | 70 | // synchronization signal to the master. |
| 58 | void adns_sync(void) { | 71 | void adns5050_sync(void) { |
| 59 | writePinLow(ADNS_CS_PIN); | 72 | writePinLow(ADNS5050_CS_PIN); |
| 60 | wait_us(1); | 73 | wait_us(1); |
| 61 | writePinHigh(ADNS_CS_PIN); | 74 | writePinHigh(ADNS5050_CS_PIN); |
| 62 | } | 75 | } |
| 63 | 76 | ||
| 64 | void adns_cs_select(void) { | 77 | void adns5050_cs_select(void) { writePinLow(ADNS5050_CS_PIN); } |
| 65 | writePinLow(ADNS_CS_PIN); | ||
| 66 | } | ||
| 67 | 78 | ||
| 68 | void adns_cs_deselect(void) { | 79 | void adns5050_cs_deselect(void) { writePinHigh(ADNS5050_CS_PIN); } |
| 69 | writePinHigh(ADNS_CS_PIN); | ||
| 70 | } | ||
| 71 | 80 | ||
| 72 | uint8_t adns_serial_read(void) { | 81 | uint8_t adns5050_serial_read(void) { |
| 73 | setPinInput(ADNS_SDIO_PIN); | 82 | setPinInput(ADNS5050_SDIO_PIN); |
| 74 | uint8_t byte = 0; | 83 | uint8_t byte = 0; |
| 75 | 84 | ||
| 76 | for (uint8_t i = 0; i < 8; ++i) { | 85 | for (uint8_t i = 0; i < 8; ++i) { |
| 77 | writePinLow(ADNS_SCLK_PIN); | 86 | writePinLow(ADNS5050_SCLK_PIN); |
| 78 | wait_us(1); | 87 | wait_us(1); |
| 79 | 88 | ||
| 80 | byte = (byte << 1) | readPin(ADNS_SDIO_PIN); | 89 | byte = (byte << 1) | readPin(ADNS5050_SDIO_PIN); |
| 81 | 90 | ||
| 82 | writePinHigh(ADNS_SCLK_PIN); | 91 | writePinHigh(ADNS5050_SCLK_PIN); |
| 83 | wait_us(1); | 92 | wait_us(1); |
| 84 | } | 93 | } |
| 85 | 94 | ||
| 86 | return byte; | 95 | return byte; |
| 87 | } | 96 | } |
| 88 | 97 | ||
| 89 | void adns_serial_write(uint8_t data) { | 98 | void adns5050_serial_write(uint8_t data) { |
| 90 | setPinOutput(ADNS_SDIO_PIN); | 99 | setPinOutput(ADNS5050_SDIO_PIN); |
| 91 | 100 | ||
| 92 | for (int8_t b = 7; b >= 0; b--) { | 101 | for (int8_t b = 7; b >= 0; b--) { |
| 93 | writePinLow(ADNS_SCLK_PIN); | 102 | writePinLow(ADNS5050_SCLK_PIN); |
| 94 | 103 | ||
| 95 | if (data & (1 << b)) | 104 | if (data & (1 << b)) |
| 96 | writePinHigh(ADNS_SDIO_PIN); | 105 | writePinHigh(ADNS5050_SDIO_PIN); |
| 97 | else | 106 | else |
| 98 | writePinLow(ADNS_SDIO_PIN); | 107 | writePinLow(ADNS5050_SDIO_PIN); |
| 99 | 108 | ||
| 100 | wait_us(2); | 109 | wait_us(2); |
| 101 | 110 | ||
| 102 | writePinHigh(ADNS_SCLK_PIN); | 111 | writePinHigh(ADNS5050_SCLK_PIN); |
| 103 | } | 112 | } |
| 104 | 113 | ||
| 105 | // tSWR. See page 15 of the ADNS spec sheet. | 114 | // tSWR. See page 15 of the ADNS spec sheet. |
| @@ -113,17 +122,17 @@ void adns_serial_write(uint8_t data) { | |||
| 113 | 122 | ||
| 114 | // Read a byte of data from a register on the ADNS. | 123 | // Read a byte of data from a register on the ADNS. |
| 115 | // Don't forget to use the register map (as defined in the header file). | 124 | // Don't forget to use the register map (as defined in the header file). |
| 116 | uint8_t adns_read_reg(uint8_t reg_addr) { | 125 | uint8_t adns5050_read_reg(uint8_t reg_addr) { |
| 117 | adns_cs_select(); | 126 | adns5050_cs_select(); |
| 118 | 127 | ||
| 119 | adns_serial_write(reg_addr); | 128 | adns5050_serial_write(reg_addr); |
| 120 | 129 | ||
| 121 | // We don't need a minimum tSRAD here. That's because a 4ms wait time is | 130 | // We don't need a minimum tSRAD here. That's because a 4ms wait time is |
| 122 | // already included in adns_serial_write(), so we're good. | 131 | // already included in adns5050_serial_write(), so we're good. |
| 123 | // See page 10 and 15 of the ADNS spec sheet. | 132 | // See page 10 and 15 of the ADNS spec sheet. |
| 124 | //wait_us(4); | 133 | // wait_us(4); |
| 125 | 134 | ||
| 126 | uint8_t byte = adns_serial_read(); | 135 | uint8_t byte = adns5050_serial_read(); |
| 127 | 136 | ||
| 128 | // tSRW & tSRR. See page 15 of the ADNS spec sheet. | 137 | // tSRW & tSRR. See page 15 of the ADNS spec sheet. |
| 129 | // Technically, this is only necessary if the next operation is an SDIO | 138 | // Technically, this is only necessary if the next operation is an SDIO |
| @@ -131,38 +140,38 @@ uint8_t adns_read_reg(uint8_t reg_addr) { | |||
| 131 | // Honestly, this wait could probably be removed. | 140 | // Honestly, this wait could probably be removed. |
| 132 | wait_us(1); | 141 | wait_us(1); |
| 133 | 142 | ||
| 134 | adns_cs_deselect(); | 143 | adns5050_cs_deselect(); |
| 135 | 144 | ||
| 136 | return byte; | 145 | return byte; |
| 137 | } | 146 | } |
| 138 | 147 | ||
| 139 | void adns_write_reg(uint8_t reg_addr, uint8_t data) { | 148 | void adns5050_write_reg(uint8_t reg_addr, uint8_t data) { |
| 140 | adns_cs_select(); | 149 | adns5050_cs_select(); |
| 141 | adns_serial_write( 0b10000000 | reg_addr ); | 150 | adns5050_serial_write(0b10000000 | reg_addr); |
| 142 | adns_serial_write(data); | 151 | adns5050_serial_write(data); |
| 143 | adns_cs_deselect(); | 152 | adns5050_cs_deselect(); |
| 144 | } | 153 | } |
| 145 | 154 | ||
| 146 | report_adns_t adns_read_burst(void) { | 155 | report_adns5050_t adns5050_read_burst(void) { |
| 147 | adns_cs_select(); | 156 | adns5050_cs_select(); |
| 148 | 157 | ||
| 149 | report_adns_t data; | 158 | report_adns5050_t data; |
| 150 | data.dx = 0; | 159 | data.dx = 0; |
| 151 | data.dy = 0; | 160 | data.dy = 0; |
| 152 | 161 | ||
| 153 | adns_serial_write(REG_MOTION_BURST); | 162 | adns5050_serial_write(REG_MOTION_BURST); |
| 154 | 163 | ||
| 155 | // We don't need a minimum tSRAD here. That's because a 4ms wait time is | 164 | // We don't need a minimum tSRAD here. That's because a 4ms wait time is |
| 156 | // already included in adns_serial_write(), so we're good. | 165 | // already included in adns5050_serial_write(), so we're good. |
| 157 | // See page 10 and 15 of the ADNS spec sheet. | 166 | // See page 10 and 15 of the ADNS spec sheet. |
| 158 | //wait_us(4); | 167 | // wait_us(4); |
| 159 | 168 | ||
| 160 | uint8_t x = adns_serial_read(); | 169 | uint8_t x = adns5050_serial_read(); |
| 161 | uint8_t y = adns_serial_read(); | 170 | uint8_t y = adns5050_serial_read(); |
| 162 | 171 | ||
| 163 | // Burst mode returns a bunch of other shit that we don't really need. | 172 | // Burst mode returns a bunch of other shit that we don't really need. |
| 164 | // Setting CS to high ends burst mode early. | 173 | // Setting CS to high ends burst mode early. |
| 165 | adns_cs_deselect(); | 174 | adns5050_cs_deselect(); |
| 166 | 175 | ||
| 167 | data.dx = convert_twoscomp(x); | 176 | data.dx = convert_twoscomp(x); |
| 168 | data.dy = convert_twoscomp(y); | 177 | data.dy = convert_twoscomp(y); |
| @@ -180,14 +189,21 @@ int8_t convert_twoscomp(uint8_t data) { | |||
| 180 | } | 189 | } |
| 181 | 190 | ||
| 182 | // Don't forget to use the definitions for CPI in the header file. | 191 | // Don't forget to use the definitions for CPI in the header file. |
| 183 | void adns_set_cpi(uint8_t cpi) { | 192 | void adns5050_set_cpi(uint16_t cpi) { |
| 184 | adns_write_reg(REG_MOUSE_CONTROL2, cpi); | 193 | uint8_t cpival = constrain((cpi / 125), 0x1, 0xD); // limits to 0--119 |
| 194 | |||
| 195 | adns5050_write_reg(REG_MOUSE_CONTROL2, 0b10000 | cpival); | ||
| 196 | } | ||
| 197 | |||
| 198 | uint16_t adns5050_get_cpi(void) { | ||
| 199 | uint8_t cpival = adns5050_read_reg(REG_MOUSE_CONTROL2); | ||
| 200 | return (uint16_t)((cpival & 0b10000) * 125); | ||
| 185 | } | 201 | } |
| 186 | 202 | ||
| 187 | bool adns_check_signature(void) { | 203 | bool adns5050_check_signature(void) { |
| 188 | uint8_t pid = adns_read_reg(REG_PRODUCT_ID); | 204 | uint8_t pid = adns5050_read_reg(REG_PRODUCT_ID); |
| 189 | uint8_t rid = adns_read_reg(REG_REVISION_ID); | 205 | uint8_t rid = adns5050_read_reg(REG_REVISION_ID); |
| 190 | uint8_t pid2 = adns_read_reg(REG_PRODUCT_ID2); | 206 | uint8_t pid2 = adns5050_read_reg(REG_PRODUCT_ID2); |
| 191 | 207 | ||
| 192 | return (pid == 0x12 && rid == 0x01 && pid2 == 0x26); | 208 | return (pid == 0x12 && rid == 0x01 && pid2 == 0x26); |
| 193 | } | 209 | } |
