diff options
author | Drashna Jaelre <drashna@live.com> | 2022-07-19 17:46:22 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-19 17:46:22 -0700 |
commit | 12eb6444c67456d522c815120de8eed431ead2f8 (patch) | |
tree | 50445a98e7f06d531cefd2648455ca6ce2576b84 /drivers/sensors/paw3204.c | |
parent | 6992efb2291f8b78cb5feb5c750bab616640045d (diff) |
Add support for PAW3204 Optical Sensor (#17669)
Co-authored-by: gompa <gompa@h-bomb.nl>
Co-authored-by: Stefan Kerkmann <karlk90@pm.me>
Diffstat (limited to 'drivers/sensors/paw3204.c')
-rw-r--r-- | drivers/sensors/paw3204.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/drivers/sensors/paw3204.c b/drivers/sensors/paw3204.c new file mode 100644 index 0000000000..a13753dd6f --- /dev/null +++ b/drivers/sensors/paw3204.c @@ -0,0 +1,172 @@ +/* Copyright 2021 Gompa (@Gompa) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +// https://github.com/shinoaliceKabocha/choco60_track/tree/master/keymaps/default + +#include "paw3204.h" +#include "wait.h" +#include "debug.h" +#include "gpio.h" + +#define REG_PID1 0x00 +#define REG_PID2 0x01 +#define REG_STAT 0x02 +#define REG_X 0x03 +#define REG_Y 0x04 + +#define REG_SETUP 0x06 +#define REG_IMGQUAL 0x07 +#define REG_IMGREC 0x0E +#define REG_IMGTRASH 0x0D + +#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt))) + +// CPI values +enum cpi_values { + CPI400, // 0b000 + CPI500, // 0b001 + CPI600, // 0b010 + CPI800, // 0b011 + CPI1000, // 0b100 + CPI1200, // 0b101 + CPI1600, // 0b110 +}; + +uint8_t paw3204_serial_read(void); +void paw3204_serial_write(uint8_t reg_addr); +uint8_t paw3204_read_reg(uint8_t reg_addr); +void paw3204_write_reg(uint8_t reg_addr, uint8_t data); + +void paw3204_init(void) { + setPinOutput(PAW3204_SCLK_PIN); // setclockpin to output + setPinInputHigh(PAW3204_SDIO_PIN); // set datapin input high + + paw3204_write_reg(REG_SETUP, 0x86); // reset sensor and set 1600cpi + wait_us(5); + + paw3204_read_reg(0x00); // read id + paw3204_read_reg(0x01); // read id2 + // PAW3204_write_reg(REG_SETUP,0x06); // dont reset sensor and set cpi 1600 + paw3204_write_reg(REG_IMGTRASH, 0x32); // write image trashhold +} + +uint8_t paw3204_serial_read(void) { + setPinInput(PAW3204_SDIO_PIN); + uint8_t byte = 0; + + for (uint8_t i = 0; i < 8; ++i) { + writePinLow(PAW3204_SCLK_PIN); + wait_us(1); + + byte = (byte << 1) | readPin(PAW3204_SDIO_PIN); + + writePinHigh(PAW3204_SCLK_PIN); + wait_us(1); + } + + return byte; +} + +void paw3204_serial_write(uint8_t data) { + writePinLow(PAW3204_SDIO_PIN); + setPinOutput(PAW3204_SDIO_PIN); + + for (int8_t b = 7; b >= 0; b--) { + writePinLow(PAW3204_SCLK_PIN); + if (data & (1 << b)) { + writePinHigh(PAW3204_SDIO_PIN); + } else { + writePinLow(PAW3204_SDIO_PIN); + } + writePinHigh(PAW3204_SCLK_PIN); + } + + wait_us(4); +} + +report_paw3204_t paw3204_read(void) { + report_paw3204_t data = {0}; + + data.isMotion = paw3204_read_reg(REG_STAT) & (1 << 7); // check for motion only (bit 7 in field) + data.x = (int8_t)paw3204_read_reg(REG_X); + data.y = (int8_t)paw3204_read_reg(REG_Y); + + return data; +} + +void paw3204_write_reg(uint8_t reg_addr, uint8_t data) { + paw3204_serial_write(0b10000000 | reg_addr); + paw3204_serial_write(data); +} + +uint8_t paw3204_read_reg(uint8_t reg_addr) { + paw3204_serial_write(reg_addr); + wait_us(5); + return paw3204_serial_read(); +} + +void paw3204_set_cpi(uint16_t cpi) { + uint8_t cpival = CPI1000; + if (cpi <= 450) { + cpival = CPI400; + } else if (cpi <= 550) { + cpival = CPI500; + } else if (cpi <= 700) { + cpival = CPI600; + } else if (cpi <= 900) { + cpival = CPI800; + } else if (cpi <= 1100) { + cpival = CPI1000; + } else if (cpi <= 1400) { + cpival = CPI1200; + } else if (cpi > 1400) { + cpival = CPI1600; + } + paw3204_write_reg(REG_SETUP, cpival); +} + +uint16_t paw3204_get_cpi(void) { + uint16_t cpival = 1000; + + switch (paw3204_read_reg(REG_SETUP) & 0b111) { + case CPI400: + cpival = 400; + break; + case CPI500: + cpival = 500; + break; + case CPI600: + cpival = 600; + break; + case CPI800: + cpival = 800; + break; + case CPI1000: + cpival = 1000; + break; + case CPI1200: + cpival = 1200; + break; + case CPI1600: + cpival = 1600; + break; + } + return cpival; +} + +uint8_t read_pid_paw3204(void) { + return paw3204_read_reg(REG_PID1); +} |