From bdc8b9ba2d7e4bcee1f742de623a222ec2ead254 Mon Sep 17 00:00:00 2001 From: crides Date: Sun, 23 Jan 2022 14:47:23 -0600 Subject: [PATCH 01/11] add: Cirque Pinnacle trackpad driver --- app/drivers/sensor/CMakeLists.txt | 3 +- app/drivers/sensor/Kconfig | 3 +- .../sensor/cirque_trackpad/CMakeLists.txt | 8 + app/drivers/sensor/cirque_trackpad/Kconfig | 51 ++++ .../sensor/cirque_trackpad/cirque_trackpad.c | 260 ++++++++++++++++++ .../sensor/cirque_trackpad/cirque_trackpad.h | 80 ++++++ .../dts/bindings/sensor/cirque,pinnacle.yaml | 27 ++ app/include/zmk/sensors.h | 7 + 8 files changed, 437 insertions(+), 2 deletions(-) create mode 100644 app/drivers/sensor/cirque_trackpad/CMakeLists.txt create mode 100644 app/drivers/sensor/cirque_trackpad/Kconfig create mode 100644 app/drivers/sensor/cirque_trackpad/cirque_trackpad.c create mode 100644 app/drivers/sensor/cirque_trackpad/cirque_trackpad.h create mode 100644 app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml diff --git a/app/drivers/sensor/CMakeLists.txt b/app/drivers/sensor/CMakeLists.txt index b549320f121..c8931edacb5 100644 --- a/app/drivers/sensor/CMakeLists.txt +++ b/app/drivers/sensor/CMakeLists.txt @@ -2,4 +2,5 @@ # SPDX-License-Identifier: MIT add_subdirectory_ifdef(CONFIG_ZMK_BATTERY battery) -add_subdirectory_ifdef(CONFIG_EC11 ec11) \ No newline at end of file +add_subdirectory_ifdef(CONFIG_EC11 ec11) +add_subdirectory_ifdef(CONFIG_PINNACLE cirque_trackpad) diff --git a/app/drivers/sensor/Kconfig b/app/drivers/sensor/Kconfig index a828f6c63ab..01a8c49169d 100644 --- a/app/drivers/sensor/Kconfig +++ b/app/drivers/sensor/Kconfig @@ -2,4 +2,5 @@ # SPDX-License-Identifier: MIT rsource "battery/Kconfig" -rsource "ec11/Kconfig" \ No newline at end of file +rsource "ec11/Kconfig" +rsource "cirque_trackpad/Kconfig" diff --git a/app/drivers/sensor/cirque_trackpad/CMakeLists.txt b/app/drivers/sensor/cirque_trackpad/CMakeLists.txt new file mode 100644 index 00000000000..92b6744cc53 --- /dev/null +++ b/app/drivers/sensor/cirque_trackpad/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2022 The ZMK Contributors +# SPDX-License-Identifier: MIT + +zephyr_include_directories(.) + +zephyr_library() + +zephyr_library_sources(cirque_trackpad.c) diff --git a/app/drivers/sensor/cirque_trackpad/Kconfig b/app/drivers/sensor/cirque_trackpad/Kconfig new file mode 100644 index 00000000000..16a4792482c --- /dev/null +++ b/app/drivers/sensor/cirque_trackpad/Kconfig @@ -0,0 +1,51 @@ +# Copyright (c) 2022 The ZMK Contributors +# SPDX-License-Identifier: MIT + +menuconfig PINNACLE + bool "PINNACLE Incremental Encoder Sensor" + depends on GPIO + depends on SPI + help + Enable driver for Cirque Pinnacle trackpads + +if PINNACLE + +choice + prompt "Trigger mode" + default PINNACLE_TRIGGER_NONE + help + Specify the type of triggering to be used by the driver. + +config PINNACLE_TRIGGER_NONE + bool "No trigger" + +config PINNACLE_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + depends on GPIO + select PINNACLE_TRIGGER + +config PINNACLE_TRIGGER_OWN_THREAD + bool "Use own thread" + depends on GPIO + select PINNACLE_TRIGGER + +endchoice + +config PINNACLE_TRIGGER + bool + +config PINNACLE_THREAD_PRIORITY + int "Thread priority" + depends on PINNACLE_TRIGGER_OWN_THREAD + default 10 + help + Priority of thread used by the driver to handle interrupts. + +config PINNACLE_THREAD_STACK_SIZE + int "Thread stack size" + depends on PINNACLE_TRIGGER_OWN_THREAD + default 1024 + help + Stack size of thread used by the driver to handle interrupts. + +endif # PINNACLE diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c new file mode 100644 index 00000000000..779595ce4c5 --- /dev/null +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c @@ -0,0 +1,260 @@ +#define DT_DRV_COMPAT cirque_pinnacle + +#include +#include +#include +#include +#include + +#include "cirque_trackpad.h" + +LOG_MODULE_REGISTER(pinnacle, CONFIG_SENSOR_LOG_LEVEL); + +static int pinnacle_seq_read(const struct device *dev, const uint8_t start, uint8_t *buf, const uint8_t len) { + uint8_t tx_buffer[len + 3], rx_dummy[3]; + tx_buffer[0] = PINNACLE_READ | start; + memset(&tx_buffer[1], PINNACLE_AUTOINC, len + 1); + tx_buffer[len + 2] = PINNACLE_DUMMY; + + const struct spi_buf tx_buf = { + .buf = tx_buffer, + .len = len + 3, + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1, + }; + struct spi_buf rx_buf[2] = { + { + .buf = rx_dummy, + .len = 3, + }, + { + .buf = buf, + .len = len, + }, + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 2, + }; + const struct pinnacle_data *data = dev->data; + const struct pinnacle_config *config = dev->config; + return spi_transceive(data->spi, &config->spi_config, &tx, &rx); +} + +static int pinnacle_write(const struct device *dev, const uint8_t addr, const uint8_t val) { + uint8_t tx_buffer[2] = { PINNACLE_WRITE | addr, val }; + uint8_t rx_buffer[2]; + + const struct spi_buf tx_buf = { + .buf = tx_buffer, + .len = 2, + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1, + }; + const struct spi_buf rx_buf[1] = { + { + .buf = rx_buffer, + .len = sizeof(rx_buffer), + }, + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 1, + }; + const struct pinnacle_data *data = dev->data; + const struct pinnacle_config *config = dev->config; + const int ret = spi_transceive(data->spi, &config->spi_config, &tx, &rx); + if (rx_buffer[1] != 0xFB) { + LOG_ERR("bad ret val"); + return -EIO; + } + if (ret < 0) { + LOG_ERR("spi ret: %d", ret); + } + return ret; +} + +static int pinnacle_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { + const struct pinnacle_data *data = dev->data; + switch (chan) { + case SENSOR_CHAN_POS_DX: val->val1 = data->dx; break; + case SENSOR_CHAN_POS_DY: val->val1 = data->dy; break; + case SENSOR_CHAN_PRESS: val->val1 = data->btn; break; + default: return -ENOTSUP; + } + return 0; +} + +static int pinnacle_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { + const struct pinnacle_config *config = dev->config; + if (attr == SENSOR_ATTR_PINNACLE_GE) { + const uint8_t ge_set = val->val1 ? 0 : PINNACLE_FEED_CFG2_DIS_GE; + const uint8_t taps_set = config->no_taps ? PINNACLE_FEED_CFG2_DIS_TAP : 0; + pinnacle_write(dev, PINNACLE_FEED_CFG2, ge_set | taps_set); + return 0; + } + return -ENOTSUP; +} + +static int pinnacle_sample_fetch(const struct device *dev, enum sensor_channel chan) { + uint8_t packet[3]; + int res = pinnacle_seq_read(dev, PINNACLE_2_2_PACKET0, packet, 3); + if (res < 0) { + LOG_ERR("res: %d", res); + return res; + } + struct pinnacle_data *data = dev->data; + data->btn = packet[0] & PINNACLE_PACKET0_BTN_PRIM; + data->dx = (int16_t) (int8_t) packet[1]; + data->dy = (int16_t) (int8_t) packet[2]; + return 0; +} + +#ifdef CONFIG_PINNACLE_TRIGGER +static void set_int(const struct device *dev, const bool en) { + const struct pinnacle_config *config = dev->config; + int ret = gpio_pin_interrupt_configure(config->dr_port, config->dr_pin, en ? GPIO_INT_LEVEL_ACTIVE : GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("can't set interrupt"); + } +} + +static int pinnacle_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { + struct pinnacle_data *data = dev->data; + + set_int(dev, false); + if (trig->type != SENSOR_TRIG_DATA_READY) { + return -ENOTSUP; + } + data->data_ready_trigger = trig; + data->data_ready_handler = handler; + set_int(dev, true); + return 0; +} + +static void pinnacle_int_cb(const struct device *dev) { + struct pinnacle_data *data = dev->data; + data->data_ready_handler(dev, data->data_ready_trigger); + set_int(dev, true); +} + +#ifdef CONFIG_PINNACLE_TRIGGER_OWN_THREAD +static void pinnacle_thread(void *arg) { + const struct device *dev = arg; + struct pinnacle_data *data = dev->data; + + while (1) { + k_sem_take(&data->gpio_sem, K_FOREVER); + pinnacle_int_cb(dev); + pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR + } +} +#elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) +static void pinnacle_work_cb(struct k_work *work) { + struct pinnacle_data *data = CONTAINER_OF(work, struct pinnacle_data, work); + pinnacle_int_cb(data->dev); + pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR +} +#endif + +static void pinnacle_gpio_cb(const struct device *port, struct gpio_callback *cb, uint32_t pins) { + struct pinnacle_data *data = CONTAINER_OF(cb, struct pinnacle_data, gpio_cb); + const struct device *dev = data->dev; +#if defined(CONFIG_PINNACLE_TRIGGER_OWN_THREAD) + k_sem_give(&data->gpio_sem); +#elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} +#endif + +#define SPI_BUS DT_BUS(DT_DRV_INST(0)) +#define SPI_REG DT_REG_ADDR(DT_DRV_INST(0)) + +static int pinnacle_init(const struct device *dev) { + struct pinnacle_data *data = dev->data; + const struct pinnacle_config *config = dev->config; + data->spi = DEVICE_DT_GET(SPI_BUS); + + pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear CC + pinnacle_write(dev, PINNACLE_Z_IDLE, 0); // No Z-Idle packets + if (config->sleep_en) { + pinnacle_write(dev, PINNACLE_SYS_CFG, PINNACLE_SYS_CFG_EN_SLEEP); + } + if (config->no_taps) { + pinnacle_write(dev, PINNACLE_FEED_CFG2, PINNACLE_FEED_CFG2_DIS_TAP); + } + uint8_t feed_cfg1 = PINNACLE_FEED_CFG1_EN_FEED; + if (config->invert_x) { + feed_cfg1 |= PINNACLE_FEED_CFG1_INV_X; + } + if (config->invert_y) { + feed_cfg1 |= PINNACLE_FEED_CFG1_INV_Y; + } + if (feed_cfg1) { + pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1); + } + +#ifdef CONFIG_PINNACLE_TRIGGER + data->dev = dev; + gpio_pin_configure(config->dr_port, config->dr_pin, GPIO_INPUT | config->dr_flags); + gpio_init_callback(&data->gpio_cb, pinnacle_gpio_cb, BIT(config->dr_pin)); + int ret = gpio_add_callback(config->dr_port, &data->gpio_cb); + if (ret < 0) { + LOG_ERR("Failed to set DR callback: %d", ret); + return -EIO; + } + +#if defined(CONFIG_PINNACLE_TRIGGER_OWN_THREAD) + k_sem_init(&data->gpio_sem, 0, UINT_MAX); + + k_thread_create(&data->thread, data->thread_stack, CONFIG_PINNACLE_THREAD_STACK_SIZE, + (k_thread_entry_t) pinnacle_thread, (void *) dev, 0, NULL, + K_PRIO_COOP(CONFIG_PINNACLE_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) + k_work_init(&data->work, pinnacle_work_cb); +#endif + pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1); +#endif + return 0; +} + +static const struct sensor_driver_api pinnacle_driver_api = { +#if CONFIG_PINNACLE_TRIGGER + .trigger_set = pinnacle_trigger_set, +#endif + .sample_fetch = pinnacle_sample_fetch, + .channel_get = pinnacle_channel_get, + .attr_set = pinnacle_attr_set, +}; + +static struct pinnacle_data pinnacle_data; +static const struct pinnacle_config pinnacle_config = { + .spi_cs = { + .gpio_dev = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(SPI_BUS, cs_gpios, SPI_REG)), + .gpio_pin = DT_GPIO_PIN_BY_IDX(SPI_BUS, cs_gpios, SPI_REG), + .delay = 0, + .gpio_dt_flags = DT_GPIO_FLAGS_BY_IDX(SPI_BUS, cs_gpios, SPI_REG), + }, + .spi_config = { + .cs = &pinnacle_config.spi_cs, + .frequency = DT_INST_PROP(0, spi_max_frequency), + .slave = DT_INST_REG_ADDR(0), + .operation = (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB), + }, + .invert_x = DT_INST_PROP(0, invert_x), + .invert_y = DT_INST_PROP(0, invert_y), + .sleep_en = DT_INST_PROP(0, sleep), + .no_taps = DT_INST_PROP(0, no_taps), +#ifdef CONFIG_PINNACLE_TRIGGER + .dr_port = DEVICE_DT_GET(DT_GPIO_CTLR(DT_DRV_INST(0), dr_gpios)), + .dr_pin = DT_INST_GPIO_PIN(0, dr_gpios), + .dr_flags = DT_INST_GPIO_FLAGS(0, dr_gpios), +#endif +}; + +DEVICE_DT_INST_DEFINE(0, pinnacle_init, device_pm_control_nop, &pinnacle_data, &pinnacle_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h new file mode 100644 index 00000000000..95c01a01ce1 --- /dev/null +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h @@ -0,0 +1,80 @@ +#pragma once + +#include + +#define PINNACLE_READ 0xA0 +#define PINNACLE_WRITE 0x80 + +#define PINNACLE_AUTOINC 0xFC +#define PINNACLE_DUMMY 0xFB + +// Registers +#define PINNACLE_FW_ID 0x00 // ASIC ID. +#define PINNACLE_FW_VER 0x01 // Firmware Version Firmware revision number. +#define PINNACLE_STATUS1 0x02 // Contains status flags about the state of Pinnacle. +#define PINNACLE_SYS_CFG 0x03 // Contains system operation and configuration bits. +#define PINNACLE_SYS_CFG_EN_SLEEP BIT(2) +#define PINNACLE_SYS_CFG_SHUTDOWN BIT(1) +#define PINNACLE_SYS_CFG_RESET BIT(0) + +#define PINNACLE_FEED_CFG1 0x04 // Contains feed operation and configuration bits. +#define PINNACLE_FEED_CFG1_EN_FEED BIT(0) +#define PINNACLE_FEED_CFG1_ABS_MODE BIT(1) +#define PINNACLE_FEED_CFG1_DIS_FILT BIT(2) +#define PINNACLE_FEED_CFG1_DIS_X BIT(3) +#define PINNACLE_FEED_CFG1_DIS_Y BIT(4) +#define PINNACLE_FEED_CFG1_INV_X BIT(6) +#define PINNACLE_FEED_CFG1_INV_Y BIT(7) +#define PINNACLE_FEED_CFG2 0x05 // Contains feed operation and configuration bits. +#define PINNACLE_FEED_CFG2_EN_IM BIT(0) // Intellimouse +#define PINNACLE_FEED_CFG2_DIS_TAP BIT(1) // Disable all taps +#define PINNACLE_FEED_CFG2_DIS_SEC BIT(2) // Disable secondary tap +#define PINNACLE_FEED_CFG2_DIS_SCRL BIT(3) // Disable scroll +#define PINNACLE_FEED_CFG2_DIS_GE BIT(4) // Disable GlideExtend +#define PINNACLE_FEED_CFG2_SWAP_XY BIT(7) // Swap X & Y +#define PINNACLE_CAL_CFG 0x07 // Contains calibration configuration bits. +#define PINNACLE_PS2_AUX 0x08 // Contains Data register for PS/2 Aux Control. +#define PINNACLE_SAMPLE 0x09 // Sample Rate Number of samples generated per second. +#define PINNACLE_Z_IDLE 0x0A // Number of Z=0 packets sent when Z goes from >0 to 0. +#define PINNACLE_Z_SCALER 0x0B // Contains the pen Z_On threshold. +#define PINNACLE_SLEEP_INTERVAL 0x0C // Sleep Interval +#define PINNACLE_SLEEP_TIMER 0x0D // Sleep Timer +#define PINNACLE_AG_PACKET0 0x10 // trackpad Data (Pinnacle AG) +#define PINNACLE_2_2_PACKET0 0x12 // trackpad Data +#define PINNACLE_REG_COUNT 0x18 + +#define PINNACLE_PACKET0_BTN_PRIM BIT(0) // Primary button +#define PINNACLE_PACKET0_BTN_SEC BIT(1) // Secondary button +#define PINNACLE_PACKET0_BTN_AUX BIT(2) // Auxiliary (middle?) button +#define PINNACLE_PACKET0_X_SIGN BIT(4) // X delta sign +#define PINNACLE_PACKET0_Y_SIGN BIT(5) // Y delta sign + +struct pinnacle_data { + const struct device *spi; + int16_t dx, dy; + int8_t wheel; + uint8_t btn; +#ifdef CONFIG_PINNACLE_TRIGGER + const struct device *dev; + const struct sensor_trigger *data_ready_trigger; + struct gpio_callback gpio_cb; + sensor_trigger_handler_t data_ready_handler; +#if defined(CONFIG_PINNACLE_TRIGGER_OWN_THREAD) + K_THREAD_STACK_MEMBER(thread_stack, CONFIG_PINNACLE_THREAD_STACK_SIZE); + struct k_sem gpio_sem; + struct k_thread thread; +#elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +#endif +}; + +struct pinnacle_config { + struct spi_cs_control spi_cs; + struct spi_config spi_config; + bool invert_x, invert_y, sleep_en, no_taps; +#ifdef CONFIG_PINNACLE_TRIGGER + const struct device *dr_port; + uint8_t dr_pin, dr_flags; +#endif +}; diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml new file mode 100644 index 00000000000..fa7e561d07f --- /dev/null +++ b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml @@ -0,0 +1,27 @@ +description: | + Sensor driver for the Cirque Pinnacle trackpad ASICs + +compatible: "cirque,pinnacle" + +include: base.yaml + +on-bus: spi + +properties: + spi-max-frequency: + type: int + required: true + description: | + Maximum SPI clock speed supported by the device, in Hz. + dr-gpios: + type: phandle-array + required: true + description: Data ready pin for the trackpad + invert-x: + type: boolean + invert-y: + type: boolean + sleep: + type: boolean + no-taps: + type: boolean diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h index 8c6c28b3848..09fbd5f69bc 100644 --- a/app/include/zmk/sensors.h +++ b/app/include/zmk/sensors.h @@ -10,3 +10,10 @@ #define ZMK_KEYMAP_HAS_SENSORS DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_NODE, okay) #define ZMK_KEYMAP_SENSORS_LEN DT_PROP_LEN(ZMK_KEYMAP_SENSORS_NODE, sensors) #define ZMK_KEYMAP_SENSORS_BY_IDX(idx) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_SENSORS_NODE, sensors, idx) + +#include + +enum { + // Cirque Pinnacle Glide Extend + SENSOR_ATTR_PINNACLE_GE = SENSOR_ATTR_PRIV_START, +}; From 2e0050fa8f9b7c2b2a26a8001e39135246b92678 Mon Sep 17 00:00:00 2001 From: crides Date: Sun, 12 Jun 2022 22:12:08 -0500 Subject: [PATCH 02/11] fix dts binding include --- app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml index fa7e561d07f..62a8c5ab15f 100644 --- a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml +++ b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml @@ -3,7 +3,7 @@ description: | compatible: "cirque,pinnacle" -include: base.yaml +include: spi-device.yaml on-bus: spi From 56a1d796af52aeca61200715eeeab000c9c9504e Mon Sep 17 00:00:00 2001 From: crides Date: Fri, 25 Nov 2022 17:24:58 -0600 Subject: [PATCH 03/11] Add I2C driver --- .../sensor/cirque_trackpad/cirque_trackpad.c | 54 +++++++++---------- .../sensor/cirque_trackpad/cirque_trackpad.h | 13 +++-- .../sensor/cirque,pinnacle-common.yaml | 12 +++++ .../bindings/sensor/cirque,pinnacle-i2c.yaml | 6 +++ .../bindings/sensor/cirque,pinnacle-spi.yaml | 6 +++ .../dts/bindings/sensor/cirque,pinnacle.yaml | 27 ---------- 6 files changed, 57 insertions(+), 61 deletions(-) create mode 100644 app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml create mode 100644 app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-i2c.yaml create mode 100644 app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-spi.yaml delete mode 100644 app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c index 779595ce4c5..975811e67f6 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c @@ -1,6 +1,5 @@ #define DT_DRV_COMPAT cirque_pinnacle -#include #include #include #include @@ -10,9 +9,11 @@ LOG_MODULE_REGISTER(pinnacle, CONFIG_SENSOR_LOG_LEVEL); -static int pinnacle_seq_read(const struct device *dev, const uint8_t start, uint8_t *buf, const uint8_t len) { +static int pinnacle_seq_read(const struct device *dev, const uint8_t addr, uint8_t *buf, const uint8_t len) { + const struct pinnacle_config *config = dev->config; +#if DT_INST_ON_BUS(0, spi) uint8_t tx_buffer[len + 3], rx_dummy[3]; - tx_buffer[0] = PINNACLE_READ | start; + tx_buffer[0] = PINNACLE_READ | addr; memset(&tx_buffer[1], PINNACLE_AUTOINC, len + 1); tx_buffer[len + 2] = PINNACLE_DUMMY; @@ -38,12 +39,15 @@ static int pinnacle_seq_read(const struct device *dev, const uint8_t start, uint .buffers = rx_buf, .count = 2, }; - const struct pinnacle_data *data = dev->data; - const struct pinnacle_config *config = dev->config; - return spi_transceive(data->spi, &config->spi_config, &tx, &rx); + return spi_transceive_dt(&config->bus, &tx, &rx); +#elif DT_INST_ON_BUS(0, i2c) + return i2c_burst_read_dt(&config->bus, PINNACLE_READ | addr, buf, len); +#endif } static int pinnacle_write(const struct device *dev, const uint8_t addr, const uint8_t val) { + const struct pinnacle_config *config = dev->config; +#if DT_INST_ON_BUS(0, spi) uint8_t tx_buffer[2] = { PINNACLE_WRITE | addr, val }; uint8_t rx_buffer[2]; @@ -65,9 +69,7 @@ static int pinnacle_write(const struct device *dev, const uint8_t addr, const ui .buffers = rx_buf, .count = 1, }; - const struct pinnacle_data *data = dev->data; - const struct pinnacle_config *config = dev->config; - const int ret = spi_transceive(data->spi, &config->spi_config, &tx, &rx); + const int ret = spi_transceive_dt(&config->bus, &tx, &rx); if (rx_buffer[1] != 0xFB) { LOG_ERR("bad ret val"); return -EIO; @@ -76,6 +78,9 @@ static int pinnacle_write(const struct device *dev, const uint8_t addr, const ui LOG_ERR("spi ret: %d", ret); } return ret; +#elif DT_INST_ON_BUS(0, i2c) + return i2c_reg_write_byte_dt(&config->bus, PINNACLE_WRITE | addr, val); +#endif } static int pinnacle_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { @@ -117,7 +122,7 @@ static int pinnacle_sample_fetch(const struct device *dev, enum sensor_channel c #ifdef CONFIG_PINNACLE_TRIGGER static void set_int(const struct device *dev, const bool en) { const struct pinnacle_config *config = dev->config; - int ret = gpio_pin_interrupt_configure(config->dr_port, config->dr_pin, en ? GPIO_INT_LEVEL_ACTIVE : GPIO_INT_DISABLE); + int ret = gpio_pin_interrupt_configure_dt(&config->dr, en ? GPIO_INT_LEVEL_ACTIVE : GPIO_INT_DISABLE); if (ret < 0) { LOG_ERR("can't set interrupt"); } @@ -178,7 +183,6 @@ static void pinnacle_gpio_cb(const struct device *port, struct gpio_callback *cb static int pinnacle_init(const struct device *dev) { struct pinnacle_data *data = dev->data; const struct pinnacle_config *config = dev->config; - data->spi = DEVICE_DT_GET(SPI_BUS); pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear CC pinnacle_write(dev, PINNACLE_Z_IDLE, 0); // No Z-Idle packets @@ -201,9 +205,9 @@ static int pinnacle_init(const struct device *dev) { #ifdef CONFIG_PINNACLE_TRIGGER data->dev = dev; - gpio_pin_configure(config->dr_port, config->dr_pin, GPIO_INPUT | config->dr_flags); - gpio_init_callback(&data->gpio_cb, pinnacle_gpio_cb, BIT(config->dr_pin)); - int ret = gpio_add_callback(config->dr_port, &data->gpio_cb); + gpio_pin_configure_dt(&config->dr, GPIO_INPUT); + gpio_init_callback(&data->gpio_cb, pinnacle_gpio_cb, BIT(config->dr.pin)); + int ret = gpio_add_callback(config->dr.port, &data->gpio_cb); if (ret < 0) { LOG_ERR("Failed to set DR callback: %d", ret); return -EIO; @@ -220,6 +224,7 @@ static int pinnacle_init(const struct device *dev) { #endif pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1); #endif + LOG_WRN("inited"); return 0; } @@ -234,26 +239,17 @@ static const struct sensor_driver_api pinnacle_driver_api = { static struct pinnacle_data pinnacle_data; static const struct pinnacle_config pinnacle_config = { - .spi_cs = { - .gpio_dev = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(SPI_BUS, cs_gpios, SPI_REG)), - .gpio_pin = DT_GPIO_PIN_BY_IDX(SPI_BUS, cs_gpios, SPI_REG), - .delay = 0, - .gpio_dt_flags = DT_GPIO_FLAGS_BY_IDX(SPI_BUS, cs_gpios, SPI_REG), - }, - .spi_config = { - .cs = &pinnacle_config.spi_cs, - .frequency = DT_INST_PROP(0, spi_max_frequency), - .slave = DT_INST_REG_ADDR(0), - .operation = (SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB), - }, +#if DT_INST_ON_BUS(0, i2c) + .bus = I2C_DT_SPEC_INST_GET(0), +#elif DT_INST_ON_BUS(0, spi) + .bus = SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0), +#endif .invert_x = DT_INST_PROP(0, invert_x), .invert_y = DT_INST_PROP(0, invert_y), .sleep_en = DT_INST_PROP(0, sleep), .no_taps = DT_INST_PROP(0, no_taps), #ifdef CONFIG_PINNACLE_TRIGGER - .dr_port = DEVICE_DT_GET(DT_GPIO_CTLR(DT_DRV_INST(0), dr_gpios)), - .dr_pin = DT_INST_GPIO_PIN(0, dr_gpios), - .dr_flags = DT_INST_GPIO_FLAGS(0, dr_gpios), + .dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios), #endif }; diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h index 95c01a01ce1..c0569fb240c 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #define PINNACLE_READ 0xA0 #define PINNACLE_WRITE 0x80 @@ -50,7 +52,6 @@ #define PINNACLE_PACKET0_Y_SIGN BIT(5) // Y delta sign struct pinnacle_data { - const struct device *spi; int16_t dx, dy; int8_t wheel; uint8_t btn; @@ -70,11 +71,13 @@ struct pinnacle_data { }; struct pinnacle_config { - struct spi_cs_control spi_cs; - struct spi_config spi_config; +#if DT_INST_ON_BUS(0, i2c) + const struct i2c_dt_spec bus; +#elif DT_INST_ON_BUS(0, spi) + const struct spi_dt_spec bus; +#endif bool invert_x, invert_y, sleep_en, no_taps; #ifdef CONFIG_PINNACLE_TRIGGER - const struct device *dr_port; - uint8_t dr_pin, dr_flags; + const struct gpio_dt_spec dr; #endif }; diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml new file mode 100644 index 00000000000..b38645886d6 --- /dev/null +++ b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml @@ -0,0 +1,12 @@ +properties: + dr-gpios: + type: phandle-array + description: Data ready pin for the trackpad + invert-x: + type: boolean + invert-y: + type: boolean + sleep: + type: boolean + no-taps: + type: boolean diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-i2c.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-i2c.yaml new file mode 100644 index 00000000000..da2603a73b0 --- /dev/null +++ b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-i2c.yaml @@ -0,0 +1,6 @@ +description: | + Sensor driver for the Cirque Pinnacle trackpad ASICs, using the I2C interface + +compatible: "cirque,pinnacle" + +include: ["i2c-device.yaml", "cirque,pinnacle-common.yaml"] diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-spi.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-spi.yaml new file mode 100644 index 00000000000..0bd70ee15d4 --- /dev/null +++ b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-spi.yaml @@ -0,0 +1,6 @@ +description: | + Sensor driver for the Cirque Pinnacle trackpad ASICs, using the SPI interface + +compatible: "cirque,pinnacle" + +include: ["spi-device.yaml", "cirque,pinnacle-common.yaml"] diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml deleted file mode 100644 index 62a8c5ab15f..00000000000 --- a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle.yaml +++ /dev/null @@ -1,27 +0,0 @@ -description: | - Sensor driver for the Cirque Pinnacle trackpad ASICs - -compatible: "cirque,pinnacle" - -include: spi-device.yaml - -on-bus: spi - -properties: - spi-max-frequency: - type: int - required: true - description: | - Maximum SPI clock speed supported by the device, in Hz. - dr-gpios: - type: phandle-array - required: true - description: Data ready pin for the trackpad - invert-x: - type: boolean - invert-y: - type: boolean - sleep: - type: boolean - no-taps: - type: boolean From e72d668648857cc383a560bd6451c16bc06af6fc Mon Sep 17 00:00:00 2001 From: crides Date: Fri, 25 Nov 2022 23:37:29 -0600 Subject: [PATCH 04/11] fix dep, multi insts --- app/drivers/sensor/cirque_trackpad/Kconfig | 2 +- .../sensor/cirque_trackpad/cirque_trackpad.c | 30 ++++++++----------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/app/drivers/sensor/cirque_trackpad/Kconfig b/app/drivers/sensor/cirque_trackpad/Kconfig index 16a4792482c..908f812dc25 100644 --- a/app/drivers/sensor/cirque_trackpad/Kconfig +++ b/app/drivers/sensor/cirque_trackpad/Kconfig @@ -4,7 +4,7 @@ menuconfig PINNACLE bool "PINNACLE Incremental Encoder Sensor" depends on GPIO - depends on SPI + depends on SPI || I2C help Enable driver for Cirque Pinnacle trackpads diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c index 975811e67f6..9332dc2411d 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c @@ -237,20 +237,16 @@ static const struct sensor_driver_api pinnacle_driver_api = { .attr_set = pinnacle_attr_set, }; -static struct pinnacle_data pinnacle_data; -static const struct pinnacle_config pinnacle_config = { -#if DT_INST_ON_BUS(0, i2c) - .bus = I2C_DT_SPEC_INST_GET(0), -#elif DT_INST_ON_BUS(0, spi) - .bus = SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0), -#endif - .invert_x = DT_INST_PROP(0, invert_x), - .invert_y = DT_INST_PROP(0, invert_y), - .sleep_en = DT_INST_PROP(0, sleep), - .no_taps = DT_INST_PROP(0, no_taps), -#ifdef CONFIG_PINNACLE_TRIGGER - .dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios), -#endif -}; - -DEVICE_DT_INST_DEFINE(0, pinnacle_init, device_pm_control_nop, &pinnacle_data, &pinnacle_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); +#define CIRQUE_INST(n) \ + static struct pinnacle_data pinnacle_data_##n; \ + static const struct pinnacle_config pinnacle_config_##n = { \ + .bus = COND_CODE_1(DT_INST_ON_BUS(0, i2c), I2C_DT_SPEC_INST_GET(0), (SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0))), \ + .invert_x = DT_INST_PROP(0, invert_x), \ + .invert_y = DT_INST_PROP(0, invert_y), \ + .sleep_en = DT_INST_PROP(0, sleep), \ + .no_taps = DT_INST_PROP(0, no_taps), \ + COND_CODE_1(CONFIG_PINNACLE_TRIGGER, (.dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios),), ) \ + }; \ + DEVICE_DT_INST_DEFINE(n, pinnacle_init, device_pm_control_nop, &pinnacle_data_##n, &pinnacle_config_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(CIRQUE_INST) From ecf60a316c396c97fe1f93b11351eb62cef3d309 Mon Sep 17 00:00:00 2001 From: crides Date: Sun, 27 Nov 2022 19:53:02 -0600 Subject: [PATCH 05/11] Remove attr set --- .../sensor/cirque_trackpad/cirque_trackpad.c | 15 +-------------- app/include/zmk/sensors.h | 7 ------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c index 9332dc2411d..44ed81fa5eb 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c @@ -2,7 +2,6 @@ #include #include -#include #include #include "cirque_trackpad.h" @@ -94,17 +93,6 @@ static int pinnacle_channel_get(const struct device *dev, enum sensor_channel ch return 0; } -static int pinnacle_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { - const struct pinnacle_config *config = dev->config; - if (attr == SENSOR_ATTR_PINNACLE_GE) { - const uint8_t ge_set = val->val1 ? 0 : PINNACLE_FEED_CFG2_DIS_GE; - const uint8_t taps_set = config->no_taps ? PINNACLE_FEED_CFG2_DIS_TAP : 0; - pinnacle_write(dev, PINNACLE_FEED_CFG2, ge_set | taps_set); - return 0; - } - return -ENOTSUP; -} - static int pinnacle_sample_fetch(const struct device *dev, enum sensor_channel chan) { uint8_t packet[3]; int res = pinnacle_seq_read(dev, PINNACLE_2_2_PACKET0, packet, 3); @@ -234,13 +222,12 @@ static const struct sensor_driver_api pinnacle_driver_api = { #endif .sample_fetch = pinnacle_sample_fetch, .channel_get = pinnacle_channel_get, - .attr_set = pinnacle_attr_set, }; #define CIRQUE_INST(n) \ static struct pinnacle_data pinnacle_data_##n; \ static const struct pinnacle_config pinnacle_config_##n = { \ - .bus = COND_CODE_1(DT_INST_ON_BUS(0, i2c), I2C_DT_SPEC_INST_GET(0), (SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0))), \ + .bus = COND_CODE_1(DT_INST_ON_BUS(0, i2c), (I2C_DT_SPEC_INST_GET(0)), (SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0))), \ .invert_x = DT_INST_PROP(0, invert_x), \ .invert_y = DT_INST_PROP(0, invert_y), \ .sleep_en = DT_INST_PROP(0, sleep), \ diff --git a/app/include/zmk/sensors.h b/app/include/zmk/sensors.h index 09fbd5f69bc..8c6c28b3848 100644 --- a/app/include/zmk/sensors.h +++ b/app/include/zmk/sensors.h @@ -10,10 +10,3 @@ #define ZMK_KEYMAP_HAS_SENSORS DT_NODE_HAS_STATUS(ZMK_KEYMAP_SENSORS_NODE, okay) #define ZMK_KEYMAP_SENSORS_LEN DT_PROP_LEN(ZMK_KEYMAP_SENSORS_NODE, sensors) #define ZMK_KEYMAP_SENSORS_BY_IDX(idx) DT_PHANDLE_BY_IDX(ZMK_KEYMAP_SENSORS_NODE, sensors, idx) - -#include - -enum { - // Cirque Pinnacle Glide Extend - SENSOR_ATTR_PINNACLE_GE = SENSOR_ATTR_PRIV_START, -}; From 1e6185439a4e39df774492970888c5542fd25505 Mon Sep 17 00:00:00 2001 From: crides Date: Sun, 27 Nov 2022 20:19:39 -0600 Subject: [PATCH 06/11] fix dr clear, bit cleanup --- app/drivers/sensor/cirque_trackpad/cirque_trackpad.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c index 44ed81fa5eb..58b50112356 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c @@ -150,7 +150,7 @@ static void pinnacle_thread(void *arg) { static void pinnacle_work_cb(struct k_work *work) { struct pinnacle_data *data = CONTAINER_OF(work, struct pinnacle_data, work); pinnacle_int_cb(data->dev); - pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR + pinnacle_write(data->dev, PINNACLE_STATUS1, 0); // Clear SW_DR } #endif @@ -165,9 +165,6 @@ static void pinnacle_gpio_cb(const struct device *port, struct gpio_callback *cb } #endif -#define SPI_BUS DT_BUS(DT_DRV_INST(0)) -#define SPI_REG DT_REG_ADDR(DT_DRV_INST(0)) - static int pinnacle_init(const struct device *dev) { struct pinnacle_data *data = dev->data; const struct pinnacle_config *config = dev->config; From 52b43a72e8bdda6ad93419a50a9c4a6a4ccdff72 Mon Sep 17 00:00:00 2001 From: crides Date: Sun, 5 Feb 2023 02:22:19 -0600 Subject: [PATCH 07/11] f trackpad: drop wheel, check error, drop invert x y, add rotate 90 --- .../sensor/cirque_trackpad/cirque_trackpad.c | 58 ++++++++++---- .../sensor/cirque_trackpad/cirque_trackpad.h | 77 +++++++++---------- .../sensor/cirque,pinnacle-common.yaml | 4 +- 3 files changed, 81 insertions(+), 58 deletions(-) diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c index 58b50112356..a6c88016aa1 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c @@ -110,7 +110,7 @@ static int pinnacle_sample_fetch(const struct device *dev, enum sensor_channel c #ifdef CONFIG_PINNACLE_TRIGGER static void set_int(const struct device *dev, const bool en) { const struct pinnacle_config *config = dev->config; - int ret = gpio_pin_interrupt_configure_dt(&config->dr, en ? GPIO_INT_LEVEL_ACTIVE : GPIO_INT_DISABLE); + int ret = gpio_pin_interrupt_configure_dt(&config->dr, en ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE); if (ret < 0) { LOG_ERR("can't set interrupt"); } @@ -156,7 +156,6 @@ static void pinnacle_work_cb(struct k_work *work) { static void pinnacle_gpio_cb(const struct device *port, struct gpio_callback *cb, uint32_t pins) { struct pinnacle_data *data = CONTAINER_OF(cb, struct pinnacle_data, gpio_cb); - const struct device *dev = data->dev; #if defined(CONFIG_PINNACLE_TRIGGER_OWN_THREAD) k_sem_give(&data->gpio_sem); #elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) @@ -169,30 +168,58 @@ static int pinnacle_init(const struct device *dev) { struct pinnacle_data *data = dev->data; const struct pinnacle_config *config = dev->config; - pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear CC - pinnacle_write(dev, PINNACLE_Z_IDLE, 0); // No Z-Idle packets + LOG_WRN("pinnacle start"); + int ret; + ret = pinnacle_write(dev, PINNACLE_STATUS1, PINNACLE_SYS_CFG_RESET); + if (ret < 0) { + LOG_ERR("can't reset %d", ret); + return ret; + } + k_msleep(20); + ret = pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear CC + if (ret < 0) { + LOG_ERR("can't write %d", ret); + return ret; + } + k_usleep(50); + ret = pinnacle_write(dev, PINNACLE_Z_IDLE, 0); // No Z-Idle packets + if (ret < 0) { + LOG_ERR("can't write %d", ret); + return ret; + } if (config->sleep_en) { - pinnacle_write(dev, PINNACLE_SYS_CFG, PINNACLE_SYS_CFG_EN_SLEEP); + ret = pinnacle_write(dev, PINNACLE_SYS_CFG, PINNACLE_SYS_CFG_EN_SLEEP); + if (ret < 0) { + LOG_ERR("can't write %d", ret); + return ret; + } } + uint8_t feed_cfg2 = PINNACLE_FEED_CFG2_EN_IM; if (config->no_taps) { - pinnacle_write(dev, PINNACLE_FEED_CFG2, PINNACLE_FEED_CFG2_DIS_TAP); + feed_cfg2 |= PINNACLE_FEED_CFG2_DIS_TAP; } - uint8_t feed_cfg1 = PINNACLE_FEED_CFG1_EN_FEED; - if (config->invert_x) { - feed_cfg1 |= PINNACLE_FEED_CFG1_INV_X; + if (config->rotate_90) { + feed_cfg2 |= PINNACLE_FEED_CFG2_ROTATE_90; } - if (config->invert_y) { - feed_cfg1 |= PINNACLE_FEED_CFG1_INV_Y; + ret = pinnacle_write(dev, PINNACLE_FEED_CFG2, feed_cfg2); + if (ret < 0) { + LOG_ERR("can't write %d", ret); + return ret; } + uint8_t feed_cfg1 = PINNACLE_FEED_CFG1_EN_FEED; if (feed_cfg1) { - pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1); + ret = pinnacle_write(dev, PINNACLE_FEED_CFG1, feed_cfg1); + } + if (ret < 0) { + LOG_ERR("can't write %d", ret); + return ret; } #ifdef CONFIG_PINNACLE_TRIGGER data->dev = dev; gpio_pin_configure_dt(&config->dr, GPIO_INPUT); gpio_init_callback(&data->gpio_cb, pinnacle_gpio_cb, BIT(config->dr.pin)); - int ret = gpio_add_callback(config->dr.port, &data->gpio_cb); + ret = gpio_add_callback(config->dr.port, &data->gpio_cb); if (ret < 0) { LOG_ERR("Failed to set DR callback: %d", ret); return -EIO; @@ -225,12 +252,11 @@ static const struct sensor_driver_api pinnacle_driver_api = { static struct pinnacle_data pinnacle_data_##n; \ static const struct pinnacle_config pinnacle_config_##n = { \ .bus = COND_CODE_1(DT_INST_ON_BUS(0, i2c), (I2C_DT_SPEC_INST_GET(0)), (SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0))), \ - .invert_x = DT_INST_PROP(0, invert_x), \ - .invert_y = DT_INST_PROP(0, invert_y), \ + .rotate_90 = DT_INST_PROP(0, rotate_90), \ .sleep_en = DT_INST_PROP(0, sleep), \ .no_taps = DT_INST_PROP(0, no_taps), \ COND_CODE_1(CONFIG_PINNACLE_TRIGGER, (.dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios),), ) \ }; \ - DEVICE_DT_INST_DEFINE(n, pinnacle_init, device_pm_control_nop, &pinnacle_data_##n, &pinnacle_config_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); + DEVICE_DT_INST_DEFINE(n, pinnacle_init, NULL, &pinnacle_data_##n, &pinnacle_config_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); DT_INST_FOREACH_STATUS_OKAY(CIRQUE_INST) diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h index c0569fb240c..25d3bd8b884 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h +++ b/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h @@ -11,49 +11,48 @@ #define PINNACLE_DUMMY 0xFB // Registers -#define PINNACLE_FW_ID 0x00 // ASIC ID. -#define PINNACLE_FW_VER 0x01 // Firmware Version Firmware revision number. -#define PINNACLE_STATUS1 0x02 // Contains status flags about the state of Pinnacle. -#define PINNACLE_SYS_CFG 0x03 // Contains system operation and configuration bits. -#define PINNACLE_SYS_CFG_EN_SLEEP BIT(2) -#define PINNACLE_SYS_CFG_SHUTDOWN BIT(1) -#define PINNACLE_SYS_CFG_RESET BIT(0) +#define PINNACLE_FW_ID 0x00 // ASIC ID. +#define PINNACLE_FW_VER 0x01 // Firmware Version Firmware revision number. +#define PINNACLE_STATUS1 0x02 // Contains status flags about the state of Pinnacle. +#define PINNACLE_SYS_CFG 0x03 // Contains system operation and configuration bits. +#define PINNACLE_SYS_CFG_EN_SLEEP BIT(2) +#define PINNACLE_SYS_CFG_SHUTDOWN BIT(1) +#define PINNACLE_SYS_CFG_RESET BIT(0) -#define PINNACLE_FEED_CFG1 0x04 // Contains feed operation and configuration bits. -#define PINNACLE_FEED_CFG1_EN_FEED BIT(0) -#define PINNACLE_FEED_CFG1_ABS_MODE BIT(1) -#define PINNACLE_FEED_CFG1_DIS_FILT BIT(2) -#define PINNACLE_FEED_CFG1_DIS_X BIT(3) -#define PINNACLE_FEED_CFG1_DIS_Y BIT(4) -#define PINNACLE_FEED_CFG1_INV_X BIT(6) -#define PINNACLE_FEED_CFG1_INV_Y BIT(7) -#define PINNACLE_FEED_CFG2 0x05 // Contains feed operation and configuration bits. -#define PINNACLE_FEED_CFG2_EN_IM BIT(0) // Intellimouse -#define PINNACLE_FEED_CFG2_DIS_TAP BIT(1) // Disable all taps -#define PINNACLE_FEED_CFG2_DIS_SEC BIT(2) // Disable secondary tap -#define PINNACLE_FEED_CFG2_DIS_SCRL BIT(3) // Disable scroll -#define PINNACLE_FEED_CFG2_DIS_GE BIT(4) // Disable GlideExtend -#define PINNACLE_FEED_CFG2_SWAP_XY BIT(7) // Swap X & Y -#define PINNACLE_CAL_CFG 0x07 // Contains calibration configuration bits. -#define PINNACLE_PS2_AUX 0x08 // Contains Data register for PS/2 Aux Control. -#define PINNACLE_SAMPLE 0x09 // Sample Rate Number of samples generated per second. -#define PINNACLE_Z_IDLE 0x0A // Number of Z=0 packets sent when Z goes from >0 to 0. -#define PINNACLE_Z_SCALER 0x0B // Contains the pen Z_On threshold. -#define PINNACLE_SLEEP_INTERVAL 0x0C // Sleep Interval -#define PINNACLE_SLEEP_TIMER 0x0D // Sleep Timer -#define PINNACLE_AG_PACKET0 0x10 // trackpad Data (Pinnacle AG) -#define PINNACLE_2_2_PACKET0 0x12 // trackpad Data -#define PINNACLE_REG_COUNT 0x18 +#define PINNACLE_FEED_CFG1 0x04 // Contains feed operation and configuration bits. +#define PINNACLE_FEED_CFG1_EN_FEED BIT(0) +#define PINNACLE_FEED_CFG1_ABS_MODE BIT(1) +#define PINNACLE_FEED_CFG1_DIS_FILT BIT(2) +#define PINNACLE_FEED_CFG1_DIS_X BIT(3) +#define PINNACLE_FEED_CFG1_DIS_Y BIT(4) +#define PINNACLE_FEED_CFG1_INV_X BIT(6) +#define PINNACLE_FEED_CFG1_INV_Y BIT(7) +#define PINNACLE_FEED_CFG2 0x05 // Contains feed operation and configuration bits. +#define PINNACLE_FEED_CFG2_EN_IM BIT(0) // Intellimouse +#define PINNACLE_FEED_CFG2_DIS_TAP BIT(1) // Disable all taps +#define PINNACLE_FEED_CFG2_DIS_SEC BIT(2) // Disable secondary tap +#define PINNACLE_FEED_CFG2_DIS_SCRL BIT(3) // Disable scroll +#define PINNACLE_FEED_CFG2_DIS_GE BIT(4) // Disable GlideExtend +#define PINNACLE_FEED_CFG2_ROTATE_90 BIT(7) // Swap X & Y +#define PINNACLE_CAL_CFG 0x07 // Contains calibration configuration bits. +#define PINNACLE_PS2_AUX 0x08 // Contains Data register for PS/2 Aux Control. +#define PINNACLE_SAMPLE 0x09 // Sample Rate Number of samples generated per second. +#define PINNACLE_Z_IDLE 0x0A // Number of Z=0 packets sent when Z goes from >0 to 0. +#define PINNACLE_Z_SCALER 0x0B // Contains the pen Z_On threshold. +#define PINNACLE_SLEEP_INTERVAL 0x0C // Sleep Interval +#define PINNACLE_SLEEP_TIMER 0x0D // Sleep Timer +#define PINNACLE_AG_PACKET0 0x10 // trackpad Data (Pinnacle AG) +#define PINNACLE_2_2_PACKET0 0x12 // trackpad Data +#define PINNACLE_REG_COUNT 0x18 -#define PINNACLE_PACKET0_BTN_PRIM BIT(0) // Primary button -#define PINNACLE_PACKET0_BTN_SEC BIT(1) // Secondary button -#define PINNACLE_PACKET0_BTN_AUX BIT(2) // Auxiliary (middle?) button -#define PINNACLE_PACKET0_X_SIGN BIT(4) // X delta sign -#define PINNACLE_PACKET0_Y_SIGN BIT(5) // Y delta sign +#define PINNACLE_PACKET0_BTN_PRIM BIT(0) // Primary button +#define PINNACLE_PACKET0_BTN_SEC BIT(1) // Secondary button +#define PINNACLE_PACKET0_BTN_AUX BIT(2) // Auxiliary (middle?) button +#define PINNACLE_PACKET0_X_SIGN BIT(4) // X delta sign +#define PINNACLE_PACKET0_Y_SIGN BIT(5) // Y delta sign struct pinnacle_data { int16_t dx, dy; - int8_t wheel; uint8_t btn; #ifdef CONFIG_PINNACLE_TRIGGER const struct device *dev; @@ -76,7 +75,7 @@ struct pinnacle_config { #elif DT_INST_ON_BUS(0, spi) const struct spi_dt_spec bus; #endif - bool invert_x, invert_y, sleep_en, no_taps; + bool rotate_90, sleep_en, no_taps; #ifdef CONFIG_PINNACLE_TRIGGER const struct gpio_dt_spec dr; #endif diff --git a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml index b38645886d6..0798ba0106d 100644 --- a/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml +++ b/app/drivers/zephyr/dts/bindings/sensor/cirque,pinnacle-common.yaml @@ -2,9 +2,7 @@ properties: dr-gpios: type: phandle-array description: Data ready pin for the trackpad - invert-x: - type: boolean - invert-y: + rotate-90: type: boolean sleep: type: boolean From 4b5efc0278502856b91134b6b569184bd12c807a Mon Sep 17 00:00:00 2001 From: crides Date: Thu, 16 Feb 2023 20:52:51 -0600 Subject: [PATCH 08/11] rename --- .../sensor/{cirque_trackpad => pinnacle}/CMakeLists.txt | 2 +- app/drivers/sensor/{cirque_trackpad => pinnacle}/Kconfig | 2 +- .../cirque_trackpad.c => pinnacle/pinnacle.c} | 6 +++--- .../cirque_trackpad.h => pinnacle/pinnacle.h} | 0 4 files changed, 5 insertions(+), 5 deletions(-) rename app/drivers/sensor/{cirque_trackpad => pinnacle}/CMakeLists.txt (74%) rename app/drivers/sensor/{cirque_trackpad => pinnacle}/Kconfig (95%) rename app/drivers/sensor/{cirque_trackpad/cirque_trackpad.c => pinnacle/pinnacle.c} (98%) rename app/drivers/sensor/{cirque_trackpad/cirque_trackpad.h => pinnacle/pinnacle.h} (100%) diff --git a/app/drivers/sensor/cirque_trackpad/CMakeLists.txt b/app/drivers/sensor/pinnacle/CMakeLists.txt similarity index 74% rename from app/drivers/sensor/cirque_trackpad/CMakeLists.txt rename to app/drivers/sensor/pinnacle/CMakeLists.txt index 92b6744cc53..ef674040f22 100644 --- a/app/drivers/sensor/cirque_trackpad/CMakeLists.txt +++ b/app/drivers/sensor/pinnacle/CMakeLists.txt @@ -5,4 +5,4 @@ zephyr_include_directories(.) zephyr_library() -zephyr_library_sources(cirque_trackpad.c) +zephyr_library_sources(pinnacle.c) diff --git a/app/drivers/sensor/cirque_trackpad/Kconfig b/app/drivers/sensor/pinnacle/Kconfig similarity index 95% rename from app/drivers/sensor/cirque_trackpad/Kconfig rename to app/drivers/sensor/pinnacle/Kconfig index 908f812dc25..34810bacd9b 100644 --- a/app/drivers/sensor/cirque_trackpad/Kconfig +++ b/app/drivers/sensor/pinnacle/Kconfig @@ -2,7 +2,7 @@ # SPDX-License-Identifier: MIT menuconfig PINNACLE - bool "PINNACLE Incremental Encoder Sensor" + bool "Cirque Pinnacle trackpads" depends on GPIO depends on SPI || I2C help diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c b/app/drivers/sensor/pinnacle/pinnacle.c similarity index 98% rename from app/drivers/sensor/cirque_trackpad/cirque_trackpad.c rename to app/drivers/sensor/pinnacle/pinnacle.c index a6c88016aa1..23a36142190 100644 --- a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.c +++ b/app/drivers/sensor/pinnacle/pinnacle.c @@ -4,7 +4,7 @@ #include #include -#include "cirque_trackpad.h" +#include "pinnacle.h" LOG_MODULE_REGISTER(pinnacle, CONFIG_SENSOR_LOG_LEVEL); @@ -248,7 +248,7 @@ static const struct sensor_driver_api pinnacle_driver_api = { .channel_get = pinnacle_channel_get, }; -#define CIRQUE_INST(n) \ +#define PINNACLE_INST(n) \ static struct pinnacle_data pinnacle_data_##n; \ static const struct pinnacle_config pinnacle_config_##n = { \ .bus = COND_CODE_1(DT_INST_ON_BUS(0, i2c), (I2C_DT_SPEC_INST_GET(0)), (SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE | SPI_TRANSFER_MSB, 0))), \ @@ -259,4 +259,4 @@ static const struct sensor_driver_api pinnacle_driver_api = { }; \ DEVICE_DT_INST_DEFINE(n, pinnacle_init, NULL, &pinnacle_data_##n, &pinnacle_config_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); -DT_INST_FOREACH_STATUS_OKAY(CIRQUE_INST) +DT_INST_FOREACH_STATUS_OKAY(PINNACLE_INST) diff --git a/app/drivers/sensor/cirque_trackpad/cirque_trackpad.h b/app/drivers/sensor/pinnacle/pinnacle.h similarity index 100% rename from app/drivers/sensor/cirque_trackpad/cirque_trackpad.h rename to app/drivers/sensor/pinnacle/pinnacle.h From 9edbced5b71a0a39c2c49a38645df7e543162aaf Mon Sep 17 00:00:00 2001 From: crides Date: Sat, 18 Feb 2023 02:22:42 -0600 Subject: [PATCH 09/11] fix no dr error --- app/drivers/sensor/pinnacle/pinnacle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/drivers/sensor/pinnacle/pinnacle.c b/app/drivers/sensor/pinnacle/pinnacle.c index 23a36142190..b54ad093079 100644 --- a/app/drivers/sensor/pinnacle/pinnacle.c +++ b/app/drivers/sensor/pinnacle/pinnacle.c @@ -255,7 +255,7 @@ static const struct sensor_driver_api pinnacle_driver_api = { .rotate_90 = DT_INST_PROP(0, rotate_90), \ .sleep_en = DT_INST_PROP(0, sleep), \ .no_taps = DT_INST_PROP(0, no_taps), \ - COND_CODE_1(CONFIG_PINNACLE_TRIGGER, (.dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios),), ) \ + COND_CODE_1(CONFIG_PINNACLE_TRIGGER, (.dr = GPIO_DT_SPEC_GET(DT_DRV_INST(0), dr_gpios),), ()) \ }; \ DEVICE_DT_INST_DEFINE(n, pinnacle_init, NULL, &pinnacle_data_##n, &pinnacle_config_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &pinnacle_driver_api); From d76df014aa6f07f04875aa46eb964ae3fe68d906 Mon Sep 17 00:00:00 2001 From: crides Date: Thu, 16 Mar 2023 20:45:19 -0500 Subject: [PATCH 10/11] fix dr? --- app/drivers/sensor/pinnacle/pinnacle.c | 35 ++++++++++++++++++++------ app/drivers/sensor/pinnacle/pinnacle.h | 3 +++ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/app/drivers/sensor/pinnacle/pinnacle.c b/app/drivers/sensor/pinnacle/pinnacle.c index b54ad093079..f8aa34f90e6 100644 --- a/app/drivers/sensor/pinnacle/pinnacle.c +++ b/app/drivers/sensor/pinnacle/pinnacle.c @@ -95,15 +95,31 @@ static int pinnacle_channel_get(const struct device *dev, enum sensor_channel ch static int pinnacle_sample_fetch(const struct device *dev, enum sensor_channel chan) { uint8_t packet[3]; - int res = pinnacle_seq_read(dev, PINNACLE_2_2_PACKET0, packet, 3); - if (res < 0) { - LOG_ERR("res: %d", res); - return res; + int ret; + ret = pinnacle_seq_read(dev, PINNACLE_STATUS1, packet, 0); + if (ret < 0) { + LOG_ERR("read status: %d", ret); + return ret; + } + if (!(packet[0] & PINNACLE_STATUS1_SW_DR)) { + return -EAGAIN; + } + ret = pinnacle_seq_read(dev, PINNACLE_2_2_PACKET0, packet, 3); + if (ret < 0) { + LOG_ERR("read packet: %d", ret); + return ret; } struct pinnacle_data *data = dev->data; data->btn = packet[0] & PINNACLE_PACKET0_BTN_PRIM; data->dx = (int16_t) (int8_t) packet[1]; data->dy = (int16_t) (int8_t) packet[2]; + if (!data->in_int) { + ret = pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR + if (ret < 0) { + LOG_ERR("clear dr: %d", ret); + return ret; + } + } return 0; } @@ -133,6 +149,11 @@ static void pinnacle_int_cb(const struct device *dev) { struct pinnacle_data *data = dev->data; data->data_ready_handler(dev, data->data_ready_trigger); set_int(dev, true); + int ret = pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR + if (ret < 0) { + LOG_ERR("clear dr: %d", ret); + } + data->in_int = false; } #ifdef CONFIG_PINNACLE_TRIGGER_OWN_THREAD @@ -143,19 +164,18 @@ static void pinnacle_thread(void *arg) { while (1) { k_sem_take(&data->gpio_sem, K_FOREVER); pinnacle_int_cb(dev); - pinnacle_write(dev, PINNACLE_STATUS1, 0); // Clear SW_DR } } #elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) static void pinnacle_work_cb(struct k_work *work) { struct pinnacle_data *data = CONTAINER_OF(work, struct pinnacle_data, work); pinnacle_int_cb(data->dev); - pinnacle_write(data->dev, PINNACLE_STATUS1, 0); // Clear SW_DR } #endif static void pinnacle_gpio_cb(const struct device *port, struct gpio_callback *cb, uint32_t pins) { struct pinnacle_data *data = CONTAINER_OF(cb, struct pinnacle_data, gpio_cb); + data->in_int = true; #if defined(CONFIG_PINNACLE_TRIGGER_OWN_THREAD) k_sem_give(&data->gpio_sem); #elif defined(CONFIG_PINNACLE_TRIGGER_GLOBAL_THREAD) @@ -169,8 +189,9 @@ static int pinnacle_init(const struct device *dev) { const struct pinnacle_config *config = dev->config; LOG_WRN("pinnacle start"); + data->in_int = false; int ret; - ret = pinnacle_write(dev, PINNACLE_STATUS1, PINNACLE_SYS_CFG_RESET); + ret = pinnacle_write(dev, PINNACLE_SYS_CFG, PINNACLE_SYS_CFG_RESET); if (ret < 0) { LOG_ERR("can't reset %d", ret); return ret; diff --git a/app/drivers/sensor/pinnacle/pinnacle.h b/app/drivers/sensor/pinnacle/pinnacle.h index 25d3bd8b884..1b74e902342 100644 --- a/app/drivers/sensor/pinnacle/pinnacle.h +++ b/app/drivers/sensor/pinnacle/pinnacle.h @@ -14,6 +14,8 @@ #define PINNACLE_FW_ID 0x00 // ASIC ID. #define PINNACLE_FW_VER 0x01 // Firmware Version Firmware revision number. #define PINNACLE_STATUS1 0x02 // Contains status flags about the state of Pinnacle. +#define PINNACLE_STATUS1_SW_DR BIT(2) +#define PINNACLE_STATUS1_SW_CC BIT(3) #define PINNACLE_SYS_CFG 0x03 // Contains system operation and configuration bits. #define PINNACLE_SYS_CFG_EN_SLEEP BIT(2) #define PINNACLE_SYS_CFG_SHUTDOWN BIT(1) @@ -54,6 +56,7 @@ struct pinnacle_data { int16_t dx, dy; uint8_t btn; + bool in_int; #ifdef CONFIG_PINNACLE_TRIGGER const struct device *dev; const struct sensor_trigger *data_ready_trigger; From c09183a92625620fc136a349e6d0fd035e3a1e88 Mon Sep 17 00:00:00 2001 From: crides Date: Wed, 26 Apr 2023 21:46:48 -0500 Subject: [PATCH 11/11] oops --- app/drivers/sensor/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/drivers/sensor/Kconfig b/app/drivers/sensor/Kconfig index 01a8c49169d..e13c4e8ed56 100644 --- a/app/drivers/sensor/Kconfig +++ b/app/drivers/sensor/Kconfig @@ -3,4 +3,4 @@ rsource "battery/Kconfig" rsource "ec11/Kconfig" -rsource "cirque_trackpad/Kconfig" +rsource "pinnacle/Kconfig"