diff options
Diffstat (limited to 'drivers/sensors/pmw3360.c')
| -rw-r--r-- | drivers/sensors/pmw3360.c | 140 |
1 files changed, 74 insertions, 66 deletions
diff --git a/drivers/sensors/pmw3360.c b/drivers/sensors/pmw3360.c index 79b653e45..2b27dccbb 100644 --- a/drivers/sensors/pmw3360.c +++ b/drivers/sensors/pmw3360.c | |||
| @@ -20,62 +20,71 @@ | |||
| 20 | #include "wait.h" | 20 | #include "wait.h" |
| 21 | #include "debug.h" | 21 | #include "debug.h" |
| 22 | #include "print.h" | 22 | #include "print.h" |
| 23 | #include "pmw3360_firmware.h" | 23 | #include PMW3360_FIRMWARE_H |
| 24 | 24 | ||
| 25 | // Registers | 25 | // Registers |
| 26 | #define REG_Product_ID 0x00 | 26 | // clang-format off |
| 27 | #define REG_Revision_ID 0x01 | 27 | #define REG_Product_ID 0x00 |
| 28 | #define REG_Motion 0x02 | 28 | #define REG_Revision_ID 0x01 |
| 29 | #define REG_Delta_X_L 0x03 | 29 | #define REG_Motion 0x02 |
| 30 | #define REG_Delta_X_H 0x04 | 30 | #define REG_Delta_X_L 0x03 |
| 31 | #define REG_Delta_Y_L 0x05 | 31 | #define REG_Delta_X_H 0x04 |
| 32 | #define REG_Delta_Y_H 0x06 | 32 | #define REG_Delta_Y_L 0x05 |
| 33 | #define REG_SQUAL 0x07 | 33 | #define REG_Delta_Y_H 0x06 |
| 34 | #define REG_Raw_Data_Sum 0x08 | 34 | #define REG_SQUAL 0x07 |
| 35 | #define REG_Maximum_Raw_data 0x09 | 35 | #define REG_Raw_Data_Sum 0x08 |
| 36 | #define REG_Minimum_Raw_data 0x0A | 36 | #define REG_Maximum_Raw_data 0x09 |
| 37 | #define REG_Shutter_Lower 0x0B | 37 | #define REG_Minimum_Raw_data 0x0A |
| 38 | #define REG_Shutter_Upper 0x0C | 38 | #define REG_Shutter_Lower 0x0B |
| 39 | #define REG_Control 0x0D | 39 | #define REG_Shutter_Upper 0x0C |
| 40 | #define REG_Config1 0x0F | 40 | #define REG_Control 0x0D |
| 41 | #define REG_Config2 0x10 | 41 | #define REG_Config1 0x0F |
| 42 | #define REG_Angle_Tune 0x11 | 42 | #define REG_Config2 0x10 |
| 43 | #define REG_Frame_Capture 0x12 | 43 | #define REG_Angle_Tune 0x11 |
| 44 | #define REG_SROM_Enable 0x13 | 44 | #define REG_Frame_Capture 0x12 |
| 45 | #define REG_Run_Downshift 0x14 | 45 | #define REG_SROM_Enable 0x13 |
| 46 | #define REG_Rest1_Rate_Lower 0x15 | 46 | #define REG_Run_Downshift 0x14 |
| 47 | #define REG_Rest1_Rate_Upper 0x16 | 47 | #define REG_Rest1_Rate_Lower 0x15 |
| 48 | #define REG_Rest1_Downshift 0x17 | 48 | #define REG_Rest1_Rate_Upper 0x16 |
| 49 | #define REG_Rest2_Rate_Lower 0x18 | 49 | #define REG_Rest1_Downshift 0x17 |
| 50 | #define REG_Rest2_Rate_Upper 0x19 | 50 | #define REG_Rest2_Rate_Lower 0x18 |
| 51 | #define REG_Rest2_Downshift 0x1A | 51 | #define REG_Rest2_Rate_Upper 0x19 |
| 52 | #define REG_Rest3_Rate_Lower 0x1B | 52 | #define REG_Rest2_Downshift 0x1A |
| 53 | #define REG_Rest3_Rate_Upper 0x1C | 53 | #define REG_Rest3_Rate_Lower 0x1B |
| 54 | #define REG_Observation 0x24 | 54 | #define REG_Rest3_Rate_Upper 0x1C |
| 55 | #define REG_Data_Out_Lower 0x25 | 55 | #define REG_Observation 0x24 |
| 56 | #define REG_Data_Out_Upper 0x26 | 56 | #define REG_Data_Out_Lower 0x25 |
| 57 | #define REG_Raw_Data_Dump 0x29 | 57 | #define REG_Data_Out_Upper 0x26 |
| 58 | #define REG_SROM_ID 0x2A | 58 | #define REG_Raw_Data_Dump 0x29 |
| 59 | #define REG_Min_SQ_Run 0x2B | 59 | #define REG_SROM_ID 0x2A |
| 60 | #define REG_Raw_Data_Threshold 0x2C | 60 | #define REG_Min_SQ_Run 0x2B |
| 61 | #define REG_Config5 0x2F | 61 | #define REG_Raw_Data_Threshold 0x2C |
| 62 | #define REG_Power_Up_Reset 0x3A | 62 | #define REG_Config5 0x2F |
| 63 | #define REG_Shutdown 0x3B | 63 | #define REG_Power_Up_Reset 0x3A |
| 64 | #define REG_Inverse_Product_ID 0x3F | 64 | #define REG_Shutdown 0x3B |
| 65 | #define REG_LiftCutoff_Tune3 0x41 | 65 | #define REG_Inverse_Product_ID 0x3F |
| 66 | #define REG_Angle_Snap 0x42 | 66 | #define REG_LiftCutoff_Tune3 0x41 |
| 67 | #define REG_LiftCutoff_Tune1 0x4A | 67 | #define REG_Angle_Snap 0x42 |
| 68 | #define REG_Motion_Burst 0x50 | 68 | #define REG_LiftCutoff_Tune1 0x4A |
| 69 | #define REG_LiftCutoff_Tune_Timeout 0x58 | 69 | #define REG_Motion_Burst 0x50 |
| 70 | #define REG_LiftCutoff_Tune_Timeout 0x58 | ||
| 70 | #define REG_LiftCutoff_Tune_Min_Length 0x5A | 71 | #define REG_LiftCutoff_Tune_Min_Length 0x5A |
| 71 | #define REG_SROM_Load_Burst 0x62 | 72 | #define REG_SROM_Load_Burst 0x62 |
| 72 | #define REG_Lift_Config 0x63 | 73 | #define REG_Lift_Config 0x63 |
| 73 | #define REG_Raw_Data_Burst 0x64 | 74 | #define REG_Raw_Data_Burst 0x64 |
| 74 | #define REG_LiftCutoff_Tune2 0x65 | 75 | #define REG_LiftCutoff_Tune2 0x65 |
| 76 | // clang-format on | ||
| 77 | |||
| 78 | #ifndef MAX_CPI | ||
| 79 | # define MAX_CPI 0x77 // limits to 0--119, should be max cpi/100 | ||
| 80 | #endif | ||
| 75 | 81 | ||
| 76 | bool _inBurst = false; | 82 | bool _inBurst = false; |
| 77 | 83 | ||
| 84 | #ifdef CONSOLE_ENABLE | ||
| 78 | 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')); } | 85 | 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')); } |
| 86 | #endif | ||
| 87 | #define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) | ||
| 79 | 88 | ||
| 80 | bool spi_start_adv(void) { | 89 | bool spi_start_adv(void) { |
| 81 | bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR); | 90 | bool status = spi_start(PMW3360_CS_PIN, PMW3360_SPI_LSBFIRST, PMW3360_SPI_MODE, PMW3360_SPI_DIVISOR); |
| @@ -124,20 +133,20 @@ uint8_t spi_read_adv(uint8_t reg_addr) { | |||
| 124 | return data; | 133 | return data; |
| 125 | } | 134 | } |
| 126 | 135 | ||
| 127 | void pmw_set_cpi(uint16_t cpi) { | 136 | void pmw3360_set_cpi(uint16_t cpi) { |
| 128 | uint8_t cpival = constrain((cpi / 100) - 1, 0, 0x77); // limits to 0--119 | 137 | uint8_t cpival = constrain((cpi / 100) - 1, 0, MAX_CPI); |
| 129 | 138 | ||
| 130 | spi_start_adv(); | 139 | spi_start_adv(); |
| 131 | spi_write_adv(REG_Config1, cpival); | 140 | spi_write_adv(REG_Config1, cpival); |
| 132 | spi_stop(); | 141 | spi_stop(); |
| 133 | } | 142 | } |
| 134 | 143 | ||
| 135 | uint16_t pmw_get_cpi(void) { | 144 | uint16_t pmw3360_get_cpi(void) { |
| 136 | uint8_t cpival = spi_read_adv(REG_Config1); | 145 | uint8_t cpival = spi_read_adv(REG_Config1); |
| 137 | return (uint16_t)(cpival & 0xFF) * 100; | 146 | return (uint16_t)(cpival & 0xFF) * 100; |
| 138 | } | 147 | } |
| 139 | 148 | ||
| 140 | bool pmw_spi_init(void) { | 149 | bool pmw3360_init(void) { |
| 141 | setPinOutput(PMW3360_CS_PIN); | 150 | setPinOutput(PMW3360_CS_PIN); |
| 142 | 151 | ||
| 143 | spi_init(); | 152 | spi_init(); |
| @@ -164,12 +173,12 @@ bool pmw_spi_init(void) { | |||
| 164 | spi_read_adv(REG_Delta_Y_L); | 173 | spi_read_adv(REG_Delta_Y_L); |
| 165 | spi_read_adv(REG_Delta_Y_H); | 174 | spi_read_adv(REG_Delta_Y_H); |
| 166 | 175 | ||
| 167 | pmw_upload_firmware(); | 176 | pmw3360_upload_firmware(); |
| 168 | 177 | ||
| 169 | spi_stop_adv(); | 178 | spi_stop_adv(); |
| 170 | 179 | ||
| 171 | wait_ms(10); | 180 | wait_ms(10); |
| 172 | pmw_set_cpi(PMW3360_CPI); | 181 | pmw3360_set_cpi(PMW3360_CPI); |
| 173 | 182 | ||
| 174 | wait_ms(1); | 183 | wait_ms(1); |
| 175 | 184 | ||
| @@ -177,14 +186,14 @@ bool pmw_spi_init(void) { | |||
| 177 | 186 | ||
| 178 | spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30)); | 187 | spi_write_adv(REG_Angle_Tune, constrain(ROTATIONAL_TRANSFORM_ANGLE, -30, 30)); |
| 179 | 188 | ||
| 180 | bool init_success = pmw_check_signature(); | 189 | bool init_success = pmw3360_check_signature(); |
| 181 | 190 | ||
| 182 | writePinLow(PMW3360_CS_PIN); | 191 | writePinLow(PMW3360_CS_PIN); |
| 183 | 192 | ||
| 184 | return init_success; | 193 | return init_success; |
| 185 | } | 194 | } |
| 186 | 195 | ||
| 187 | void pmw_upload_firmware(void) { | 196 | void pmw3360_upload_firmware(void) { |
| 188 | spi_write_adv(REG_SROM_Enable, 0x1d); | 197 | spi_write_adv(REG_SROM_Enable, 0x1d); |
| 189 | 198 | ||
| 190 | wait_ms(10); | 199 | wait_ms(10); |
| @@ -211,16 +220,18 @@ void pmw_upload_firmware(void) { | |||
| 211 | wait_ms(10); | 220 | wait_ms(10); |
| 212 | } | 221 | } |
| 213 | 222 | ||
| 214 | bool pmw_check_signature(void) { | 223 | bool pmw3360_check_signature(void) { |
| 215 | uint8_t pid = spi_read_adv(REG_Product_ID); | 224 | uint8_t pid = spi_read_adv(REG_Product_ID); |
| 216 | uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID); | 225 | uint8_t iv_pid = spi_read_adv(REG_Inverse_Product_ID); |
| 217 | uint8_t SROM_ver = spi_read_adv(REG_SROM_ID); | 226 | uint8_t SROM_ver = spi_read_adv(REG_SROM_ID); |
| 218 | return (pid == 0x42 && iv_pid == 0xBD && SROM_ver == 0x04); // signature for SROM 0x04 | 227 | return (pid == firmware_signature[0] && iv_pid == firmware_signature[1] && SROM_ver == firmware_signature[2]); // signature for SROM 0x04 |
| 219 | } | 228 | } |
| 220 | 229 | ||
| 221 | report_pmw_t pmw_read_burst(void) { | 230 | report_pmw3360_t pmw3360_read_burst(void) { |
| 222 | if (!_inBurst) { | 231 | if (!_inBurst) { |
| 232 | #ifdef CONSOLE_ENABLE | ||
| 223 | dprintf("burst on"); | 233 | dprintf("burst on"); |
| 234 | #endif | ||
| 224 | spi_write_adv(REG_Motion_Burst, 0x00); | 235 | spi_write_adv(REG_Motion_Burst, 0x00); |
| 225 | _inBurst = true; | 236 | _inBurst = true; |
| 226 | } | 237 | } |
| @@ -229,12 +240,7 @@ report_pmw_t pmw_read_burst(void) { | |||
| 229 | spi_write(REG_Motion_Burst); | 240 | spi_write(REG_Motion_Burst); |
| 230 | wait_us(35); // waits for tSRAD | 241 | wait_us(35); // waits for tSRAD |
| 231 | 242 | ||
| 232 | report_pmw_t data; | 243 | report_pmw3360_t data = {0}; |
| 233 | data.motion = 0; | ||
| 234 | data.dx = 0; | ||
| 235 | data.mdx = 0; | ||
| 236 | data.dy = 0; | ||
| 237 | data.mdx = 0; | ||
| 238 | 244 | ||
| 239 | data.motion = spi_read(); | 245 | data.motion = spi_read(); |
| 240 | spi_write(0x00); // skip Observation | 246 | spi_write(0x00); // skip Observation |
| @@ -245,6 +251,7 @@ report_pmw_t pmw_read_burst(void) { | |||
| 245 | 251 | ||
| 246 | spi_stop(); | 252 | spi_stop(); |
| 247 | 253 | ||
| 254 | #ifdef CONSOLE_ENABLE | ||
| 248 | if (debug_mouse) { | 255 | if (debug_mouse) { |
| 249 | print_byte(data.motion); | 256 | print_byte(data.motion); |
| 250 | print_byte(data.dx); | 257 | print_byte(data.dx); |
| @@ -253,6 +260,7 @@ report_pmw_t pmw_read_burst(void) { | |||
| 253 | print_byte(data.mdy); | 260 | print_byte(data.mdy); |
| 254 | dprintf("\n"); | 261 | dprintf("\n"); |
| 255 | } | 262 | } |
| 263 | #endif | ||
| 256 | 264 | ||
| 257 | data.isMotion = (data.motion & 0x80) != 0; | 265 | data.isMotion = (data.motion & 0x80) != 0; |
| 258 | data.isOnSurface = (data.motion & 0x08) == 0; | 266 | data.isOnSurface = (data.motion & 0x08) == 0; |
