summaryrefslogtreecommitdiffstats
path: root/drivers/sensors
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sensors')
-rw-r--r--drivers/sensors/adns5050.c157
-rw-r--r--drivers/sensors/adns5050.h75
-rw-r--r--drivers/sensors/adns9800.c175
-rw-r--r--drivers/sensors/adns9800.h42
-rw-r--r--drivers/sensors/adns9800_srom_A6.h2
-rw-r--r--drivers/sensors/analog_joystick.c94
-rw-r--r--drivers/sensors/analog_joystick.h51
-rw-r--r--drivers/sensors/cirque_pinnacle.c232
-rw-r--r--drivers/sensors/cirque_pinnacle.h74
-rw-r--r--drivers/sensors/cirque_pinnacle_i2c.c43
-rw-r--r--drivers/sensors/cirque_pinnacle_spi.c52
-rw-r--r--drivers/sensors/pimoroni_trackball.c187
-rw-r--r--drivers/sensors/pimoroni_trackball.h48
-rw-r--r--drivers/sensors/pmw3360.c140
-rw-r--r--drivers/sensors/pmw3360.h38
-rw-r--r--drivers/sensors/pmw3360_firmware.h5
-rw-r--r--drivers/sensors/pmw3389_firmware.h303
17 files changed, 1281 insertions, 437 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);
}
diff --git a/drivers/sensors/adns5050.h b/drivers/sensors/adns5050.h
index 5e9edc2962..e45a250196 100644
--- a/drivers/sensors/adns5050.h
+++ b/drivers/sensors/adns5050.h
@@ -21,59 +21,52 @@
#include <stdbool.h>
-// Registers
-#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
-
// CPI values
-#define CPI125 0x11
-#define CPI250 0x12
-#define CPI375 0x13
-#define CPI500 0x14
-#define CPI625 0x15
-#define CPI750 0x16
-#define CPI875 0x17
+// clang-format off
+#define CPI125 0x11
+#define CPI250 0x12
+#define CPI375 0x13
+#define CPI500 0x14
+#define CPI625 0x15
+#define CPI750 0x16
+#define CPI875 0x17
#define CPI1000 0x18
#define CPI1125 0x19
#define CPI1250 0x1a
#define CPI1375 0x1b
+// clang-format on
+
+#define constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
+
+// Definitions for the ADNS serial line.
+#ifndef ADNS5050_SCLK_PIN
+# error "No clock pin defined -- missing ADNS5050_SCLK_PIN"
+#endif
+
+#ifndef ADNS5050_SDIO_PIN
+# error "No data pin defined -- missing ADNS5050_SDIO_PIN"
+#endif
-#ifdef CONSOLE_ENABLE
-void print_byte(uint8_t byte);
+#ifndef ADNS5050_CS_PIN
+# error "No chip select pin defined -- missing ADNS5050_CS_PIN"
#endif
typedef struct {
int8_t dx;
int8_t dy;
-} report_adns_t;
+} report_adns5050_t;
// A bunch of functions to implement the ADNS5050-specific serial protocol.
// Note that the "serial.h" driver is insufficient, because it does not
// manually manipulate a serial clock signal.
-void adns_init(void);
-void adns_sync(void);
-uint8_t adns_serial_read(void);
-void adns_serial_write(uint8_t data);
-uint8_t adns_read_reg(uint8_t reg_addr);
-void adns_write_reg(uint8_t reg_addr, uint8_t data);
-report_adns_t adns_read_burst(void);
-int8_t convert_twoscomp(uint8_t data);
-void adns_set_cpi(uint8_t cpi);
-bool adns_check_signature(void);
+void adns5050_init(void);
+void adns5050_sync(void);
+uint8_t adns5050_serial_read(void);
+void adns5050_serial_write(uint8_t data);
+uint8_t adns5050_read_reg(uint8_t reg_addr);
+void adns5050_write_reg(uint8_t reg_addr, uint8_t data);
+report_adns5050_t adns5050_read_burst(void);
+void adns5050_set_cpi(uint16_t cpi);
+uint16_t adns5050_get_cpi(void);
+int8_t convert_twoscomp(uint8_t data);
+bool adns5050_check_signature(void);
diff --git a/drivers/sensors/adns9800.c b/drivers/sensors/adns9800.c
index b4f683452c..c52f991804 100644
--- a/drivers/sensors/adns9800.c
+++ b/drivers/sensors/adns9800.c
@@ -15,83 +15,80 @@
*/
#include "spi_master.h"
-#include "quantum.h"
#include "adns9800_srom_A6.h"
#include "adns9800.h"
+#include "wait.h"
// registers
-#define REG_Product_ID 0x00
-#define REG_Revision_ID 0x01
-#define REG_Motion 0x02
-#define REG_Delta_X_L 0x03
-#define REG_Delta_X_H 0x04
-#define REG_Delta_Y_L 0x05
-#define REG_Delta_Y_H 0x06
-#define REG_SQUAL 0x07
-#define REG_Pixel_Sum 0x08
-#define REG_Maximum_Pixel 0x09
-#define REG_Minimum_Pixel 0x0a
-#define REG_Shutter_Lower 0x0b
-#define REG_Shutter_Upper 0x0c
-#define REG_Frame_Period_Lower 0x0d
-#define REG_Frame_Period_Upper 0x0e
-#define REG_Configuration_I 0x0f
-#define REG_Configuration_II 0x10
-#define REG_Frame_Capture 0x12
-#define REG_SROM_Enable 0x13
-#define REG_Run_Downshift 0x14
-#define REG_Rest1_Rate 0x15
-#define REG_Rest1_Downshift 0x16
-#define REG_Rest2_Rate 0x17
-#define REG_Rest2_Downshift 0x18
-#define REG_Rest3_Rate 0x19
+// clang-format off
+#define REG_Product_ID 0x00
+#define REG_Revision_ID 0x01
+#define REG_Motion 0x02
+#define REG_Delta_X_L 0x03
+#define REG_Delta_X_H 0x04
+#define REG_Delta_Y_L 0x05
+#define REG_Delta_Y_H 0x06
+#define REG_SQUAL 0x07
+#define REG_Pixel_Sum 0x08
+#define REG_Maximum_Pixel 0x09
+#define REG_Minimum_Pixel 0x0a
+#define REG_Shutter_Lower 0x0b
+#define REG_Shutter_Upper 0x0c
+#define REG_Frame_Period_Lower 0x0d
+#define REG_Frame_Period_Upper 0x0e
+#define REG_Configuration_I 0x0f
+#define REG_Configuration_II 0x10
+#define REG_Frame_Capture 0x12
+#define REG_SROM_Enable 0x13
+#define REG_Run_Downshift 0x14
+#define REG_Rest1_Rate 0x15
+#define REG_Rest1_Downshift 0x16
+#define REG_Rest2_Rate 0x17
+#define REG_Rest2_Downshift 0x18
+#define REG_Rest3_Rate 0x19
#define REG_Frame_Period_Max_Bound_Lower 0x1a
#define REG_Frame_Period_Max_Bound_Upper 0x1b
#define REG_Frame_Period_Min_Bound_Lower 0x1c
#define REG_Frame_Period_Min_Bound_Upper 0x1d
-#define REG_Shutter_Max_Bound_Lower 0x1e
-#define REG_Shutter_Max_Bound_Upper 0x1f
-#define REG_LASER_CTRL0 0x20
-#define REG_Observation 0x24
-#define REG_Data_Out_Lower 0x25
-#define REG_Data_Out_Upper 0x26
-#define REG_SROM_ID 0x2a
-#define REG_Lift_Detection_Thr 0x2e
-#define REG_Configuration_V 0x2f
-#define REG_Configuration_IV 0x39
-#define REG_Power_Up_Reset 0x3a
-#define REG_Shutdown 0x3b
-#define REG_Inverse_Product_ID 0x3f
-#define REG_Motion_Burst 0x50
-#define REG_SROM_Load_Burst 0x62
-#define REG_Pixel_Burst 0x64
-
-#define ADNS_CLOCK_SPEED 2000000
-#define MIN_CPI 200
-#define MAX_CPI 8200
-#define CPI_STEP 200
-#define CLAMP_CPI(value) value<MIN_CPI ? MIN_CPI : value> MAX_CPI ? MAX_CPI : value
-#define SPI_MODE 3
-#define SPI_DIVISOR (F_CPU / ADNS_CLOCK_SPEED)
+#define REG_Shutter_Max_Bound_Lower 0x1e
+#define REG_Shutter_Max_Bound_Upper 0x1f
+#define REG_LASER_CTRL0 0x20
+#define REG_Observation 0x24
+#define REG_Data_Out_Lower 0x25
+#define REG_Data_Out_Upper 0x26
+#define REG_SROM_ID 0x2a
+#define REG_Lift_Detection_Thr 0x2e
+#define REG_Configuration_V 0x2f
+#define REG_Configuration_IV 0x39
+#define REG_Power_Up_Reset 0x3a
+#define REG_Shutdown 0x3b
+#define REG_Inverse_Product_ID 0x3f
+#define REG_Motion_Burst 0x50
+#define REG_SROM_Load_Burst 0x62
+#define REG_Pixel_Burst 0x64
+
+#define MIN_CPI 200
+#define MAX_CPI 8200
+#define CPI_STEP 200
+#define CLAMP_CPI(value) value<MIN_CPI ? MIN_CPI : value> MAX_CPI ? MAX_CPI : value
#define US_BETWEEN_WRITES 120
-#define US_BETWEEN_READS 20
-#define US_BEFORE_MOTION 100
-#define MSB1 0x80
+#define US_BETWEEN_READS 20
+#define US_BEFORE_MOTION 100
+#define MSB1 0x80
+// clang-format on
-extern const uint8_t firmware_data[];
+void adns9800_spi_start(void) { spi_start(ADNS9800_CS_PIN, false, ADNS9800_SPI_MODE, ADNS9800_SPI_DIVISOR); }
-void adns_spi_start(void) { spi_start(SPI_SS_PIN, false, SPI_MODE, SPI_DIVISOR); }
-
-void adns_write(uint8_t reg_addr, uint8_t data) {
- adns_spi_start();
+void adns9800_write(uint8_t reg_addr, uint8_t data) {
+ adns9800_spi_start();
spi_write(reg_addr | MSB1);
spi_write(data);
spi_stop();
wait_us(US_BETWEEN_WRITES);
}
-uint8_t adns_read(uint8_t reg_addr) {
- adns_spi_start();
+uint8_t adns9800_read(uint8_t reg_addr) {
+ adns9800_spi_start();
spi_write(reg_addr & 0x7f);
uint8_t data = spi_read();
spi_stop();
@@ -100,39 +97,39 @@ uint8_t adns_read(uint8_t reg_addr) {
return data;
}
-void adns_init() {
- setPinOutput(SPI_SS_PIN);
+void adns9800_init() {
+ setPinOutput(ADNS9800_CS_PIN);
spi_init();
// reboot
- adns_write(REG_Power_Up_Reset, 0x5a);
+ adns9800_write(REG_Power_Up_Reset, 0x5a);
wait_ms(50);
// read registers and discard
- adns_read(REG_Motion);
- adns_read(REG_Delta_X_L);
- adns_read(REG_Delta_X_H);
- adns_read(REG_Delta_Y_L);
- adns_read(REG_Delta_Y_H);
+ adns9800_read(REG_Motion);
+ adns9800_read(REG_Delta_X_L);
+ adns9800_read(REG_Delta_X_H);
+ adns9800_read(REG_Delta_Y_L);
+ adns9800_read(REG_Delta_Y_H);
// upload firmware
// 3k firmware mode
- adns_write(REG_Configuration_IV, 0x02);
+ adns9800_write(REG_Configuration_IV, 0x02);
// enable initialisation
- adns_write(REG_SROM_Enable, 0x1d);
+ adns9800_write(REG_SROM_Enable, 0x1d);
// wait a frame
wait_ms(10);
// start SROM download
- adns_write(REG_SROM_Enable, 0x18);
+ adns9800_write(REG_SROM_Enable, 0x18);
// write the SROM file
- adns_spi_start();
+ adns9800_spi_start();
spi_write(REG_SROM_Load_Burst | 0x80);
wait_us(15);
@@ -140,7 +137,7 @@ void adns_init() {
// send all bytes of the firmware
unsigned char c;
for (int i = 0; i < FIRMWARE_LENGTH; i++) {
- c = (unsigned char)pgm_read_byte(firmware_data + i);
+ c = (unsigned char)pgm_read_byte(adns9800_firmware_data + i);
spi_write(c);
wait_us(15);
}
@@ -150,18 +147,30 @@ void adns_init() {
wait_ms(10);
// enable laser
- uint8_t laser_ctrl0 = adns_read(REG_LASER_CTRL0);
- adns_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
+ uint8_t laser_ctrl0 = adns9800_read(REG_LASER_CTRL0);
+ adns9800_write(REG_LASER_CTRL0, laser_ctrl0 & 0xf0);
+
+ adns9800_set_cpi(ADNS9800_CPI);
}
-config_adns_t adns_get_config(void) {
- uint8_t config_1 = adns_read(REG_Configuration_I);
- return (config_adns_t){(config_1 & 0xFF) * CPI_STEP};
+config_adns9800_t adns9800_get_config(void) {
+ uint8_t config_1 = adns9800_read(REG_Configuration_I);
+ return (config_adns9800_t){(config_1 & 0xFF) * CPI_STEP};
}
-void adns_set_config(config_adns_t config) {
+void adns9800_set_config(config_adns9800_t config) {
uint8_t config_1 = (CLAMP_CPI(config.cpi) / CPI_STEP) & 0xFF;
- adns_write(REG_Configuration_I, config_1);
+ adns9800_write(REG_Configuration_I, config_1);
+}
+
+uint16_t adns9800_get_cpi(void) {
+ uint8_t config_1 = adns9800_read(REG_Configuration_I);
+ return (uint16_t){(config_1 & 0xFF) * CPI_STEP};
+}
+
+void adns9800_set_cpi(uint16_t cpi) {
+ uint8_t config_1 = (CLAMP_CPI(cpi) / CPI_STEP) & 0xFF;
+ adns9800_write(REG_Configuration_I, config_1);
}
static int16_t convertDeltaToInt(uint8_t high, uint8_t low) {
@@ -174,10 +183,10 @@ static int16_t convertDeltaToInt(uint8_t high, uint8_t low) {
return twos_comp;
}
-report_adns_t adns_get_report(void) {
- report_adns_t report = {0, 0};
+report_adns9800_t adns9800_get_report(void) {
+ report_adns9800_t report = {0, 0};
- adns_spi_start();
+ adns9800_spi_start();
// start burst mode
spi_write(REG_Motion_Burst & 0x7f);
diff --git a/drivers/sensors/adns9800.h b/drivers/sensors/adns9800.h
index d19ded4012..e75a869c03 100644
--- a/drivers/sensors/adns9800.h
+++ b/drivers/sensors/adns9800.h
@@ -18,18 +18,48 @@
#include <stdint.h>
+#ifndef ADNS9800_CPI
+# define ADNS9800_CPI 1600
+#endif
+
+#ifndef ADNS9800_CLOCK_SPEED
+# define ADNS9800_CLOCK_SPEED 2000000
+#endif
+
+#ifndef ADNS9800_SPI_LSBFIRST
+# define ADNS9800_SPI_LSBFIRST false
+#endif
+
+#ifndef ADNS9800_SPI_MODE
+# define ADNS9800_SPI_MODE 3
+#endif
+
+#ifndef ADNS9800_SPI_DIVISOR
+# ifdef __AVR__
+# define ADNS9800_SPI_DIVISOR (F_CPU / ADNS9800_CLOCK_SPEED)
+# else
+# define ADNS9800_SPI_DIVISOR 64
+# endif
+#endif
+
+#ifndef ADNS9800_CS_PIN
+# error "No chip select pin defined -- missing ADNS9800_CS_PIN"
+#endif
+
typedef struct {
/* 200 - 8200 CPI supported */
uint16_t cpi;
-} config_adns_t;
+} config_adns9800_t;
typedef struct {
int16_t x;
int16_t y;
-} report_adns_t;
+} report_adns9800_t;
-void adns_init(void);
-config_adns_t adns_get_config(void);
-void adns_set_config(config_adns_t);
+void adns9800_init(void);
+config_adns9800_t adns9800_get_config(void);
+void adns9800_set_config(config_adns9800_t);
+uint16_t adns9800_get_cpi(void);
+void adns9800_set_cpi(uint16_t cpi);
/* Reads and clears the current delta values on the ADNS sensor */
-report_adns_t adns_get_report(void);
+report_adns9800_t adns9800_get_report(void);
diff --git a/drivers/sensors/adns9800_srom_A6.h b/drivers/sensors/adns9800_srom_A6.h
index e698a401b9..d86ecbbd9e 100644
--- a/drivers/sensors/adns9800_srom_A6.h
+++ b/drivers/sensors/adns9800_srom_A6.h
@@ -6,7 +6,7 @@
// clang-format off
-const uint8_t firmware_data[FIRMWARE_LENGTH] PROGMEM = {
+const uint8_t adns9800_firmware_data[FIRMWARE_LENGTH] PROGMEM = {
0x03, 0xA6, 0x68, 0x1E, 0x7D, 0x10, 0x7E, 0x7E, 0x5F, 0x1C, 0xB8, 0xF2, 0x47, 0x0C, 0x7B, 0x74,
0x4B, 0x14, 0x8B, 0x75, 0x66, 0x51, 0x0B, 0x8C, 0x76, 0x74, 0x4B, 0x14, 0xAA, 0xD6, 0x0F, 0x9C,
0xBA, 0xF6, 0x6E, 0x3F, 0xDD, 0x38, 0xD5, 0x02, 0x80, 0x9B, 0x82, 0x6D, 0x58, 0x13, 0xA4, 0xAB,
diff --git a/drivers/sensors/analog_joystick.c b/drivers/sensors/analog_joystick.c
new file mode 100644
index 0000000000..0f4d1d7a4c
--- /dev/null
+++ b/drivers/sensors/analog_joystick.c
@@ -0,0 +1,94 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ *
+ * 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/>.
+ */
+
+#include "analog_joystick.h"
+#include "analog.h"
+#include "gpio.h"
+#include "wait.h"
+
+// Set Parameters
+uint16_t minAxisValue = ANALOG_JOYSTICK_AXIS_MIN;
+uint16_t maxAxisValue = ANALOG_JOYSTICK_AXIS_MAX;
+
+uint8_t maxCursorSpeed = ANALOG_JOYSTICK_SPEED_MAX;
+uint8_t speedRegulator = ANALOG_JOYSTICK_SPEED_REGULATOR; // Lower Values Create Faster Movement
+
+int16_t xOrigin, yOrigin;
+
+uint16_t lastCursor = 0;
+
+int16_t axisCoordinate(uint8_t pin, uint16_t origin) {
+ int8_t direction;
+ int16_t distanceFromOrigin;
+ int16_t range;
+
+ int16_t position = analogReadPin(pin);
+
+ if (origin == position) {
+ return 0;
+ } else if (origin > position) {
+ distanceFromOrigin = origin - position;
+ range = origin - minAxisValue;
+ direction = -1;
+ } else {
+ distanceFromOrigin = position - origin;
+ range = maxAxisValue - origin;
+ direction = 1;
+ }
+
+ float percent = (float)distanceFromOrigin / range;
+ int16_t coordinate = (int16_t)(percent * 100);
+ if (coordinate < 0) {
+ return 0;
+ } else if (coordinate > 100) {
+ return 100 * direction;
+ } else {
+ return coordinate * direction;
+ }
+}
+
+int8_t axisToMouseComponent(uint8_t pin, int16_t origin, uint8_t maxSpeed) {
+ int16_t coordinate = axisCoordinate(pin, origin);
+ if (coordinate != 0) {
+ float percent = (float)coordinate / 100;
+ return percent * maxCursorSpeed * (abs(coordinate) / speedRegulator);
+ } else {
+ return 0;
+ }
+}
+
+report_analog_joystick_t analog_joystick_read(void) {
+ report_analog_joystick_t report = {0};
+
+ if (timer_elapsed(lastCursor) > ANALOG_JOYSTICK_READ_INTERVAL) {
+ lastCursor = timer_read();
+ report.x = axisToMouseComponent(ANALOG_JOYSTICK_X_AXIS_PIN, xOrigin, maxCursorSpeed);
+ report.y = axisToMouseComponent(ANALOG_JOYSTICK_Y_AXIS_PIN, yOrigin, maxCursorSpeed);
+ }
+#ifdef ANALOG_JOYSTICK_CLICK_PIN
+ report.button = !readPin(ANALOG_JOYSTICK_CLICK_PIN);
+#endif
+ return report;
+}
+
+void analog_joystick_init(void) {
+#ifdef ANALOG_JOYSTICK_CLICK_PIN
+ setPinInputHigh(ANALOG_JOYSTICK_CLICK_PIN);
+#endif
+ // Account for drift
+ xOrigin = analogReadPin(ANALOG_JOYSTICK_X_AXIS_PIN);
+ yOrigin = analogReadPin(ANALOG_JOYSTICK_Y_AXIS_PIN);
+}
diff --git a/drivers/sensors/analog_joystick.h b/drivers/sensors/analog_joystick.h
new file mode 100644
index 0000000000..6892a08817
--- /dev/null
+++ b/drivers/sensors/analog_joystick.h
@@ -0,0 +1,51 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're (@drashna) <drashna@live.com>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifndef ANALOG_JOYSTICK_X_AXIS_PIN
+# error No pin specified for X Axis
+#endif
+#ifndef ANALOG_JOYSTICK_Y_AXIS_PIN
+# error No pin specified for Y Axis
+#endif
+
+#ifndef ANALOG_JOYSTICK_AXIS_MIN
+# define ANALOG_JOYSTICK_AXIS_MIN 0
+#endif
+#ifndef ANALOG_JOYSTICK_AXIS_MAX
+# define ANALOG_JOYSTICK_AXIS_MAX 1023
+#endif
+#ifndef ANALOG_JOYSTICK_SPEED_REGULATOR
+# define ANALOG_JOYSTICK_SPEED_REGULATOR 20
+#endif
+#ifndef ANALOG_JOYSTICK_READ_INTERVAL
+# define ANALOG_JOYSTICK_READ_INTERVAL 10
+#endif
+#ifndef ANALOG_JOYSTICK_SPEED_MAX
+# define ANALOG_JOYSTICK_SPEED_MAX 2
+#endif
+
+typedef struct {
+ int8_t x;
+ int8_t y;
+ bool button;
+} report_analog_joystick_t;
+report_analog_joystick_t analog_joystick_read(void);
+void analog_joystick_init(void);
diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c
new file mode 100644
index 0000000000..b807c4f076
--- /dev/null
+++ b/drivers/sensors/cirque_pinnacle.c
@@ -0,0 +1,232 @@
+// Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license
+#include "cirque_pinnacle.h"
+#include "print.h"
+#include "debug.h"
+#include "wait.h"
+
+// Registers for RAP
+// clang-format off
+#define FIRMWARE_ID 0x00
+#define FIRMWARE_VERSION_C 0x01
+#define STATUS_1 0x02
+#define SYSCONFIG_1 0x03
+#define FEEDCONFIG_1 0x04
+#define FEEDCONFIG_2 0x05
+#define CALIBRATION_CONFIG_1 0x07
+#define PS2_AU_CONTROL 0x08
+#define SAMPLE_RATE 0x09
+#define Z_IDLE_COUNT 0x0A
+#define Z_SCALER 0x0B
+#define SLEEP_INTERVAL 0x0C
+#define SLEEP_TIMER 0x0D
+#define PACKET_BYTE_0 0x12
+#define PACKET_BYTE_1 0x13
+#define PACKET_BYTE_2 0x14
+#define PACKET_BYTE_3 0x15
+#define PACKET_BYTE_4 0x16
+#define PACKET_BYTE_5 0x17
+
+#define ERA_VALUE 0x1B
+#define ERA_HIGH_BYTE 0x1C
+#define ERA_LOW_BYTE 0x1D
+#define ERA_CONTROL 0x1E
+
+// ADC-attenuation settings (held in BIT_7 and BIT_6)
+// 1X = most sensitive, 4X = least sensitive
+#define ADC_ATTENUATE_1X 0x00
+#define ADC_ATTENUATE_2X 0x40
+#define ADC_ATTENUATE_3X 0x80
+#define ADC_ATTENUATE_4X 0xC0
+
+// Register config values for this demo
+#define SYSCONFIG_1_VALUE 0x00
+#define FEEDCONFIG_1_VALUE 0x03 // 0x03 for absolute mode 0x01 for relative mode
+#define FEEDCONFIG_2_VALUE 0x1C // 0x1F for normal functionality 0x1E for intellimouse disabled
+#define Z_IDLE_COUNT_VALUE 0x05
+// clang-format on
+
+bool touchpad_init;
+uint16_t scale_data = 1024;
+
+void cirque_pinnacle_clear_flags(void);
+void cirque_pinnacle_enable_feed(bool feedEnable);
+void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count);
+void RAP_Write(uint8_t address, uint8_t data);
+
+#ifdef CONSOLE_ENABLE
+void print_byte(uint8_t byte) { xprintf("%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
+
+/* Logical Scaling Functions */
+// Clips raw coordinates to "reachable" window of sensor
+// NOTE: values outside this window can only appear as a result of noise
+void ClipCoordinates(pinnacle_data_t* coordinates) {
+ if (coordinates->xValue < CIRQUE_PINNACLE_X_LOWER) {
+ coordinates->xValue = CIRQUE_PINNACLE_X_LOWER;
+ } else if (coordinates->xValue > CIRQUE_PINNACLE_X_UPPER) {
+ coordinates->xValue = CIRQUE_PINNACLE_X_UPPER;
+ }
+ if (coordinates->yValue < CIRQUE_PINNACLE_Y_LOWER) {
+ coordinates->yValue = CIRQUE_PINNACLE_Y_LOWER;
+ } else if (coordinates->yValue > CIRQUE_PINNACLE_Y_UPPER) {
+ coordinates->yValue = CIRQUE_PINNACLE_Y_UPPER;
+ }
+}
+
+uint16_t cirque_pinnacle_get_scale(void) { return scale_data; }
+void cirque_pinnacle_set_scale(uint16_t scale) { scale_data = scale; }
+
+// Scales data to desired X & Y resolution
+void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution) {
+ uint32_t xTemp = 0;
+ uint32_t yTemp = 0;
+
+ ClipCoordinates(coordinates);
+
+ xTemp = coordinates->xValue;
+ yTemp = coordinates->yValue;
+
+ // translate coordinates to (0, 0) reference by subtracting edge-offset
+ xTemp -= CIRQUE_PINNACLE_X_LOWER;
+ yTemp -= CIRQUE_PINNACLE_Y_LOWER;
+
+ // scale coordinates to (xResolution, yResolution) range
+ coordinates->xValue = (uint16_t)(xTemp * xResolution / CIRQUE_PINNACLE_X_RANGE);
+ coordinates->yValue = (uint16_t)(yTemp * yResolution / CIRQUE_PINNACLE_Y_RANGE);
+}
+
+// Clears Status1 register flags (SW_CC and SW_DR)
+void cirque_pinnacle_clear_flags() {