From 1a024aad2ea6d3193ef352ec3e18d974d248e3a6 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 14 May 2022 18:36:12 +0200 Subject: [PATCH 1/8] improvements for Cirque Pinnacle trackpads * read Software Data Ready bit before actually reading data to avoid useless work * throttle data feed to 10ms by default, which is the fastest that Pinnacle supports * set RESET for Pinnacle on QMK pointing device driver init * first step towards relative mode (only data parsing for now) * cleanup unused register values when in absolute mode * added code comments and bit definitions for all registers and config options --- drivers/sensors/cirque_pinnacle.c | 94 ++++++++++++++++++++------- drivers/sensors/cirque_pinnacle.h | 15 ++++- drivers/sensors/cirque_pinnacle_i2c.c | 2 +- drivers/sensors/cirque_pinnacle_spi.c | 2 +- quantum/pointing_device_drivers.c | 32 ++++++--- 5 files changed, 108 insertions(+), 37 deletions(-) diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c index 670b96f2fb40..19038afe3f5c 100644 --- a/drivers/sensors/cirque_pinnacle.c +++ b/drivers/sensors/cirque_pinnacle.c @@ -1,8 +1,13 @@ // Copyright (c) 2018 Cirque Corp. Restrictions apply. See: www.cirque.com/sw-license +// based on https://github.com/cirque-corp/Cirque_Pinnacle_1CA027/tree/master/Circular_Trackpad +// with modifications and changes for QMK +// refer to documentation: Gen2 and Gen3 (Pinnacle ASIC) at https://www.cirque.com/documentation + #include "cirque_pinnacle.h" #include "print.h" #include "debug.h" #include "wait.h" +#include "timer.h" // Registers for RAP // clang-format off @@ -41,12 +46,6 @@ #ifndef CIRQUE_PINNACLE_ATTENUATION # define CIRQUE_PINNACLE_ATTENUATION ADC_ATTENUATE_4X #endif - -// 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; @@ -195,7 +194,7 @@ void cirque_pinnacle_tune_edge_sensitivity(void) { ERA_ReadBytes(0x0168, &temp, 1); } -/* Pinnacle-based TM040040 Functions */ +/* Pinnacle-based TM040040/TM035035/TM023023 Functions */ void cirque_pinnacle_init(void) { #if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi) spi_init(); @@ -204,18 +203,44 @@ void cirque_pinnacle_init(void) { #endif touchpad_init = true; + // Host clears SW_CC flag cirque_pinnacle_clear_flags(); - // Host configures bits of registers 0x03 and 0x05 - RAP_Write(SYSCONFIG_1, SYSCONFIG_1_VALUE); - RAP_Write(FEEDCONFIG_2, FEEDCONFIG_2_VALUE); - - // Host enables preferred output mode (absolute) - RAP_Write(FEEDCONFIG_1, FEEDCONFIG_1_VALUE); + // SysConfig1 (Low Power Mode) + // Bit 0: Reset, 1=Reset + // Bit 1: Shutdown, 1=Shutdown, 0=Active + // Bit 2: Sleep Enable, 1=low power mode, 0=normal mode + // send a RESET command now, in case QMK had a soft-reset without a power cycle + RAP_Write(SYSCONFIG_1, 0x01); + wait_ms(20); // Pinnacle needs 10-15ms to boot, so wait long enough before configuring + RAP_Write(SYSCONFIG_1, 0x00); + wait_us(50); - // Host sets z-idle packet count to 5 (default is 30) - RAP_Write(Z_IDLE_COUNT, Z_IDLE_COUNT_VALUE); + // FeedConfig2 (Feature flags for Relative Mode Only) + // Bit 0: IntelliMouse Enable, 1=enable, 0=disable + // Bit 1: All Taps Disable, 1=disable, 0=enable + // Bit 2: Secondary Tap Disable, 1=disable, 0=enable + // Bit 3: Scroll Disable, 1=disable, 0=enable + // Bit 4: GlideExtend® Disable, 1=disable, 0=enable + // Bit 5: reserved + // Bit 6: reserved + // Bit 7: Swap X & Y, 1=90° rotation, 0=0° rotation + RAP_Write(FEEDCONFIG_2, 0x00); + + // FeedConfig1 (Data Output Flags) + // Bit 0: Feed enable, 1=feed, 0=no feed + // Bit 1: Data mode, 1=absolute, 0=relative + // Bit 2: Filter disable, 1=no filter, 0=filter + // Bit 3: X disable, 1=no X data, 0=X data + // Bit 4: Y disable, 1=no Y data, 0=Y data + // Bit 5: reserved + // Bit 6: X data Invert, 1=X max to 0, 0=0 to Y max + // Bit 7: Y data Invert, 1=Y max to 0, 0=0 to Y max + RAP_Write(FEEDCONFIG_1, CIRQUE_PINNACLE_POSITION_MODE << 1); + + // Host sets z-idle packet count to 5 (default is 0x1F/30) + RAP_Write(Z_IDLE_COUNT, 5); cirque_pinnacle_set_adc_attenuation(CIRQUE_PINNACLE_ATTENUATION); @@ -223,21 +248,40 @@ void cirque_pinnacle_init(void) { cirque_pinnacle_enable_feed(true); } -// Reads XYZ data from Pinnacle registers 0x14 through 0x17 -// Stores result in pinnacle_data_t struct with xValue, yValue, and zValue members pinnacle_data_t cirque_pinnacle_read_data(void) { - uint8_t data[6] = {0}; - pinnacle_data_t result = {0}; + uint8_t data_ready = 0; + uint8_t data[6] = {0}; + pinnacle_data_t result = {0}; + + // Check if there is valid data available + RAP_ReadBytes(STATUS_1, &data_ready, 1); // bit2 is Software Data Ready, bit3 is Command Complete, bit0 and bit1 are reserved/unused + if ((data_ready & 0x04) == 0) { + // no data available yet + return result; + } + + // Read all data bytes RAP_ReadBytes(PACKET_BYTE_0, data, 6); + // Get ready for the next data sample cirque_pinnacle_clear_flags(); - result.buttonFlags = data[0] & 0x3F; - result.xValue = data[2] | ((data[4] & 0x0F) << 8); - result.yValue = data[3] | ((data[4] & 0xF0) << 4); - result.zValue = data[5] & 0x3F; - - result.touchDown = (result.xValue != 0 || result.yValue != 0); +#if CIRQUE_PINNACLE_POSITION_MODE + // Decode data for absolute mode + // Register 0x13 is unused in this mode (palm detection area) + result.buttonFlags = data[0] & 0x3F; // bit0 to bit5 are switch 0-5, only hardware button presses (from input pin on the Pinnacle chip) + result.xValue = data[2] | ((data[4] & 0x0F) << 8); // merge high and low bits for X + result.yValue = data[3] | ((data[4] & 0xF0) << 4); // merge high and low bits for Y + result.zValue = data[5] & 0x3F; // Z is only lower 6 bits, upper 2 bits are reserved/unused + result.touchDown = (result.xValue != 0 || result.yValue != 0); // (0,0) is a "magic coordinate" to indicate "finger touched down" +#else + // Decode data for relative mode + // Registers 0x16 and 0x17 are unused in this mode + result.buttons = data[0] & 0x07; // bit0 = primary button, bit1 = secondary button, bit2 = auxilary button, if Taps enabled then also software-recognized taps are reported + result.xDelta = data[1]; + result.yDelta = data[2]; + result.wheelCount = data[3]; +#endif return result; } diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h index c8cb360e0388..933606abd0e3 100644 --- a/drivers/sensors/cirque_pinnacle.h +++ b/drivers/sensors/cirque_pinnacle.h @@ -12,6 +12,10 @@ typedef struct { uint16_t zValue; uint8_t buttonFlags; bool touchDown; + uint8_t xDelta; + uint8_t yDelta; + uint8_t wheelCount; + uint8_t buttons; } pinnacle_data_t; void cirque_pinnacle_init(void); @@ -24,6 +28,12 @@ void cirque_pinnacle_set_scale(uint16_t scale); # define CIRQUE_PINNACLE_TIMEOUT 20 #endif +#define CIRQUE_PINNACLE_ABSOLUTE_MODE 1 +#define CIRQUE_PINNACLE_RELATIVE_MODE 0 +#ifndef CIRQUE_PINNACLE_POSITION_MODE +# define CIRQUE_PINNACLE_POSITION_MODE CIRQUE_PINNACLE_ABSOLUTE_MODE +#endif + // Coordinate scaling values #ifndef CIRQUE_PINNACLE_X_LOWER # define CIRQUE_PINNACLE_X_LOWER 127 // min "reachable" X value @@ -43,7 +53,10 @@ void cirque_pinnacle_set_scale(uint16_t scale); #ifndef CIRQUE_PINNACLE_Y_RANGE # define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER) #endif - +#if !defined(POINTING_DEVICE_TASK_THROTTLE_MS) || POINTING_DEVICE_TASK_THROTTLE_MS < 10 +# undef POINTING_DEVICE_TASK_THROTTLE_MS +# define POINTING_DEVICE_TASK_THROTTLE_MS 10 // Cirque Pinnacle at most will have fresh data every 10ms +#endif #if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) # include "i2c_master.h" // Cirque's 7-bit I2C Slave Address diff --git a/drivers/sensors/cirque_pinnacle_i2c.c b/drivers/sensors/cirque_pinnacle_i2c.c index 8a38f1dcea0e..9d645ba64fbb 100644 --- a/drivers/sensors/cirque_pinnacle_i2c.c +++ b/drivers/sensors/cirque_pinnacle_i2c.c @@ -19,7 +19,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) { i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, NULL, 0, CIRQUE_PINNACLE_TIMEOUT); if (i2c_readReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, data, count, CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) { #ifdef CONSOLE_ENABLE - dprintf("error right touchpad\n"); + dprintf("error cirque_pinnacle i2c_readReg\n"); #endif touchpad_init = false; } diff --git a/drivers/sensors/cirque_pinnacle_spi.c b/drivers/sensors/cirque_pinnacle_spi.c index 34c77df07be7..7786249b904d 100644 --- a/drivers/sensors/cirque_pinnacle_spi.c +++ b/drivers/sensors/cirque_pinnacle_spi.c @@ -25,7 +25,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) { } } else { #ifdef CONSOLE_ENABLE - dprintf("error right touchpad\n"); + dprintf("error cirque_pinnacle spi_start\n"); #endif touchpad_init = false; } diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c index 41d7018c8669..5cfa1055b9c2 100644 --- a/quantum/pointing_device_drivers.c +++ b/quantum/pointing_device_drivers.c @@ -50,6 +50,7 @@ const pointing_device_driver_t pointing_device_driver = { .get_cpi = adns5050_get_cpi, }; // clang-format on + #elif defined(POINTING_DEVICE_DRIVER_adns9800) report_mouse_t adns9800_get_report_driver(report_mouse_t mouse_report) { @@ -69,6 +70,7 @@ const pointing_device_driver_t pointing_device_driver = { .get_cpi = adns9800_get_cpi }; // clang-format on + #elif defined(POINTING_DEVICE_DRIVER_analog_joystick) report_mouse_t analog_joystick_get_report(report_mouse_t mouse_report) { report_analog_joystick_t data = analog_joystick_read(); @@ -93,6 +95,7 @@ const pointing_device_driver_t pointing_device_driver = { .get_cpi = NULL }; // clang-format on + #elif defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) || defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_spi) # ifndef CIRQUE_PINNACLE_TAPPING_TERM # include "action.h" @@ -109,17 +112,14 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { mouse_xy_report_t report_x = 0, report_y = 0; static bool is_z_down = false; - cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); // Scale coordinates to arbitrary X, Y resolution - - if (x && y && touchData.xValue && touchData.yValue) { - report_x = (mouse_xy_report_t)(touchData.xValue - x); - report_y = (mouse_xy_report_t)(touchData.yValue - y); +# if CONSOLE_ENABLE + if (debug_mouse && touchData.touchDown) { + dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue); } - x = touchData.xValue; - y = touchData.yValue; +# endif - if ((bool)touchData.zValue != is_z_down) { - is_z_down = (bool)touchData.zValue; + if (touchData.touchDown != is_z_down) { + is_z_down = touchData.touchDown; if (!touchData.zValue) { if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) { mouse_report.buttons = pointing_device_handle_buttons(mouse_report.buttons, true, POINTING_DEVICE_BUTTON1); @@ -138,6 +138,16 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { if (timer_elapsed(mouse_timer) > (CIRQUE_PINNACLE_TOUCH_DEBOUNCE)) { mouse_timer = 0; } + + // Scale coordinates to arbitrary X, Y resolution + cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); + + if (x && y && touchData.xValue && touchData.yValue) { + report_x = (int8_t)(touchData.xValue - x); + report_y = (int8_t)(touchData.yValue - y); + } + x = touchData.xValue; + y = touchData.yValue; mouse_report.x = report_x; mouse_report.y = report_y; @@ -210,6 +220,7 @@ const pointing_device_driver_t pointing_device_driver = { .get_cpi = pimoroni_trackball_get_cpi }; // clang-format on + #elif defined(POINTING_DEVICE_DRIVER_pmw3360) static void pmw3360_device_init(void) { pmw3360_init(0); @@ -248,6 +259,7 @@ const pointing_device_driver_t pointing_device_driver = { .get_cpi = pmw3360_get_cpi }; // clang-format on + #elif defined(POINTING_DEVICE_DRIVER_pmw3389) static void pmw3389_device_init(void) { pmw3389_init(); @@ -286,6 +298,7 @@ const pointing_device_driver_t pointing_device_driver = { .get_cpi = pmw3389_get_cpi }; // clang-format on + #else __attribute__((weak)) void pointing_device_driver_init(void) {} __attribute__((weak)) report_mouse_t pointing_device_driver_get_report(report_mouse_t mouse_report) { @@ -304,4 +317,5 @@ const pointing_device_driver_t pointing_device_driver = { .set_cpi = pointing_device_driver_set_cpi }; // clang-format on + #endif From 9926f097394ce6524ac7a1ae6001ef5b2c3aa28c Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 16 May 2022 21:28:05 +0200 Subject: [PATCH 2/8] cirque: use the register defines --- drivers/sensors/cirque_pinnacle.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c index 19038afe3f5c..b15c361af545 100644 --- a/drivers/sensors/cirque_pinnacle.c +++ b/drivers/sensors/cirque_pinnacle.c @@ -113,16 +113,14 @@ void cirque_pinnacle_clear_flags() { // Enables/Disables the feed void cirque_pinnacle_enable_feed(bool feedEnable) { uint8_t temp; - RAP_ReadBytes(FEEDCONFIG_1, &temp, 1); // Store contents of FeedConfig1 register if (feedEnable) { temp |= 0x01; // Set Feed Enable bit - RAP_Write(0x04, temp); } else { temp &= ~0x01; // Clear Feed Enable bit - RAP_Write(0x04, temp); } + RAP_Write(FEEDCONFIG_1, temp); } /* ERA (Extended Register Access) Functions */ From a9ef396c871bd36b4eaadd3af9558f96d31a6855 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 16 May 2022 21:30:35 +0200 Subject: [PATCH 3/8] cirque: fail compilation if relative mode configured only partially implemented so far --- quantum/pointing_device_drivers.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c index 5cfa1055b9c2..7e36a2fab364 100644 --- a/quantum/pointing_device_drivers.c +++ b/quantum/pointing_device_drivers.c @@ -112,6 +112,10 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { mouse_xy_report_t report_x = 0, report_y = 0; static bool is_z_down = false; +# if !CIRQUE_PINNACLE_POSITION_MODE +# error Cirque Pinnacle with relative mode not implemented yet. +# endif + # if CONSOLE_ENABLE if (debug_mouse && touchData.touchDown) { dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue); From b7e6fb3cc794b9e6ff26d02f378ba2815d440d13 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 16 May 2022 21:29:51 +0200 Subject: [PATCH 4/8] cirque: add valid data flag and do not process invalid data --- drivers/sensors/cirque_pinnacle.c | 2 ++ drivers/sensors/cirque_pinnacle.h | 42 +++++++++++++++++-------------- quantum/pointing_device_drivers.c | 6 ++++- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c index b15c361af545..4faa335b7de9 100644 --- a/drivers/sensors/cirque_pinnacle.c +++ b/drivers/sensors/cirque_pinnacle.c @@ -255,6 +255,7 @@ pinnacle_data_t cirque_pinnacle_read_data(void) { RAP_ReadBytes(STATUS_1, &data_ready, 1); // bit2 is Software Data Ready, bit3 is Command Complete, bit0 and bit1 are reserved/unused if ((data_ready & 0x04) == 0) { // no data available yet + result.valid = false; // be explicit return result; } @@ -281,5 +282,6 @@ pinnacle_data_t cirque_pinnacle_read_data(void) { result.wheelCount = data[3]; #endif + result.valid = true; return result; } diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h index 933606abd0e3..67b86a7e5c6f 100644 --- a/drivers/sensors/cirque_pinnacle.h +++ b/drivers/sensors/cirque_pinnacle.h @@ -5,25 +5,6 @@ #include #include -// Convenient way to store and access measurements -typedef struct { - uint16_t xValue; - uint16_t yValue; - uint16_t zValue; - uint8_t buttonFlags; - bool touchDown; - uint8_t xDelta; - uint8_t yDelta; - uint8_t wheelCount; - uint8_t buttons; -} pinnacle_data_t; - -void cirque_pinnacle_init(void); -pinnacle_data_t cirque_pinnacle_read_data(void); -void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution); -uint16_t cirque_pinnacle_get_scale(void); -void cirque_pinnacle_set_scale(uint16_t scale); - #ifndef CIRQUE_PINNACLE_TIMEOUT # define CIRQUE_PINNACLE_TIMEOUT 20 #endif @@ -85,3 +66,26 @@ void cirque_pinnacle_set_scale(uint16_t scale); # endif # endif #endif + +// Convenient way to store and access measurements +typedef struct { + bool valid; // true if valid data was read, false if no data was ready +#if CIRQUE_PINNACLE_POSITION_MODE + uint16_t xValue; + uint16_t yValue; + uint16_t zValue; + uint8_t buttonFlags; + bool touchDown; +#else + uint8_t xDelta; + uint8_t yDelta; + uint8_t wheelCount; + uint8_t buttons; +#endif +} pinnacle_data_t; + +void cirque_pinnacle_init(void); +pinnacle_data_t cirque_pinnacle_read_data(void); +void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution); +uint16_t cirque_pinnacle_get_scale(void); +void cirque_pinnacle_set_scale(uint16_t scale); diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c index 7e36a2fab364..8bc21abc9ae1 100644 --- a/quantum/pointing_device_drivers.c +++ b/quantum/pointing_device_drivers.c @@ -122,7 +122,7 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { } # endif - if (touchData.touchDown != is_z_down) { + if (touchData.valid && touchData.touchDown != is_z_down) { is_z_down = touchData.touchDown; if (!touchData.zValue) { if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) { @@ -143,6 +143,10 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { mouse_timer = 0; } + if (!touchData.valid) { + return mouse_report; + } + // Scale coordinates to arbitrary X, Y resolution cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); From 1f2991cc49a0bdebce120fd154357c396ef9712f Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Mon, 16 May 2022 22:59:23 +0200 Subject: [PATCH 5/8] cirque: first do coordinates, then tap detection --- quantum/pointing_device_drivers.c | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c index 8bc21abc9ae1..c2bbf93fecd5 100644 --- a/quantum/pointing_device_drivers.c +++ b/quantum/pointing_device_drivers.c @@ -116,13 +116,29 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { # error Cirque Pinnacle with relative mode not implemented yet. # endif + if (!touchData.valid) { + return mouse_report; + } + # if CONSOLE_ENABLE if (debug_mouse && touchData.touchDown) { dprintf("cirque_pinnacle touchData x=%4d y=%4d z=%2d\n", touchData.xValue, touchData.yValue, touchData.zValue); } # endif - if (touchData.valid && touchData.touchDown != is_z_down) { + // Scale coordinates to arbitrary X, Y resolution + cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); + + if (x && y && touchData.xValue && touchData.yValue) { + report_x = (int8_t)(touchData.xValue - x); + report_y = (int8_t)(touchData.yValue - y); + } + x = touchData.xValue; + y = touchData.yValue; + mouse_report.x = report_x; + mouse_report.y = report_y; + + if (touchData.touchDown != is_z_down) { is_z_down = touchData.touchDown; if (!touchData.zValue) { if (timer_elapsed(mouse_timer) < CIRQUE_PINNACLE_TAPPING_TERM && mouse_timer != 0) { @@ -143,22 +159,6 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { mouse_timer = 0; } - if (!touchData.valid) { - return mouse_report; - } - - // Scale coordinates to arbitrary X, Y resolution - cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); - - if (x && y && touchData.xValue && touchData.yValue) { - report_x = (int8_t)(touchData.xValue - x); - report_y = (int8_t)(touchData.yValue - y); - } - x = touchData.xValue; - y = touchData.yValue; - mouse_report.x = report_x; - mouse_report.y = report_y; - return mouse_report; } From afab84cf9c083d7427a4b2271f36e1e14661f5c5 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Tue, 17 May 2022 21:19:00 +0200 Subject: [PATCH 6/8] cirque: update config options and docs --- docs/feature_pointing_device.md | 23 ++++++++++++++--------- drivers/sensors/cirque_pinnacle.c | 4 +++- drivers/sensors/cirque_pinnacle.h | 9 ++++++--- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md index 5dacc9f5ab64..377103d6b753 100644 --- a/docs/feature_pointing_device.md +++ b/docs/feature_pointing_device.md @@ -89,15 +89,17 @@ POINTING_DEVICE_DRIVER = cirque_pinnacle_spi This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the TM040040, TM035035 and the TM023023 trackpads. These are I2C or SPI compatible, and both configurations are supported. -| Setting | Description | Default | -|---------------------------------|---------------------------------------------------------------------------------|-----------------------| -|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` | -|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` | -|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` | -|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` | -|`CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `ADC_ATTENUATE_4X` | -|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | -|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | +| Setting | Description | Default | +|-------------------------------------|--------------------------------------------------------------------------------------------------|---------------------------------| +|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` | +|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` | +|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` | +|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` | +|`CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `ADC_ATTENUATE_4X` | +|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | +|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | +|`CIRQUE_PINNACLE_RESET_ON_INIT_WAIT` | (Optional) Wait time in milliseconds after sending reset during init. Use 0 to skip. | `30` | +|`CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Absolute or Relative positioning mode. Use `CIRQUE_PINNACLE_{ABSOLUTE,RELATIVE}_MODE` | `CIRQUE_PINNACLE_ABSOLUTE_MODE` | **`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be. @@ -122,6 +124,9 @@ Default attenuation is set to 4X, although if you are using a thicker overlay (s Default Scaling/CPI is 1024. +Also see the `POINTING_DEVICE_TASK_THROTTLE_MS`, which defaults to 10ms when using Cirque Pinnacle, which matches the internal update rate of the position registers (in standard configuration). Advanced configuration for pen/stylus usage might require lower values. + + ### Pimoroni Trackball To use the Pimoroni Trackball module, add this to your `rules.mk`: diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c index 4faa335b7de9..9df42487b76c 100644 --- a/drivers/sensors/cirque_pinnacle.c +++ b/drivers/sensors/cirque_pinnacle.c @@ -210,8 +210,10 @@ void cirque_pinnacle_init(void) { // Bit 1: Shutdown, 1=Shutdown, 0=Active // Bit 2: Sleep Enable, 1=low power mode, 0=normal mode // send a RESET command now, in case QMK had a soft-reset without a power cycle +#if CIRQUE_PINNACLE_RESET_ON_INIT_WAIT > 0 RAP_Write(SYSCONFIG_1, 0x01); - wait_ms(20); // Pinnacle needs 10-15ms to boot, so wait long enough before configuring + wait_ms(CIRQUE_PINNACLE_RESET_ON_INIT_WAIT); +#endif RAP_Write(SYSCONFIG_1, 0x00); wait_us(50); diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h index 67b86a7e5c6f..13aa72631385 100644 --- a/drivers/sensors/cirque_pinnacle.h +++ b/drivers/sensors/cirque_pinnacle.h @@ -6,7 +6,10 @@ #include #ifndef CIRQUE_PINNACLE_TIMEOUT -# define CIRQUE_PINNACLE_TIMEOUT 20 +# define CIRQUE_PINNACLE_TIMEOUT 20 // I2C timeout in milliseconds +#endif +#ifndef CIRQUE_PINNACLE_RESET_ON_INIT_WAIT +# define CIRQUE_PINNACLE_RESET_ON_INIT_WAIT 30 // milliseconds to wait after setting reset bit. Pinnacle needs 15-20ms to boot, increase if needed. Set to 0 to skip reset-on-init. #endif #define CIRQUE_PINNACLE_ABSOLUTE_MODE 1 @@ -34,9 +37,9 @@ #ifndef CIRQUE_PINNACLE_Y_RANGE # define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER) #endif -#if !defined(POINTING_DEVICE_TASK_THROTTLE_MS) || POINTING_DEVICE_TASK_THROTTLE_MS < 10 +#if !defined(POINTING_DEVICE_TASK_THROTTLE_MS) # undef POINTING_DEVICE_TASK_THROTTLE_MS -# define POINTING_DEVICE_TASK_THROTTLE_MS 10 // Cirque Pinnacle at most will have fresh data every 10ms +# define POINTING_DEVICE_TASK_THROTTLE_MS 10 // Cirque Pinnacle in normal operation produces data every 10ms. Advanced configuration for pen/stylus usage might require lower values. #endif #if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) # include "i2c_master.h" From dfb491b8a8d22c9c165c70ba759696cfd21e7d63 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 25 Jun 2022 16:42:28 +0200 Subject: [PATCH 7/8] cirque: cleanup and adapt to recent changes --- docs/feature_pointing_device.md | 1 - drivers/sensors/cirque_pinnacle.h | 1 - drivers/sensors/cirque_pinnacle_i2c.c | 2 +- drivers/sensors/cirque_pinnacle_spi.c | 4 ++-- quantum/pointing_device_drivers.c | 13 +++++++------ 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md index 377103d6b753..87ce125e0d18 100644 --- a/docs/feature_pointing_device.md +++ b/docs/feature_pointing_device.md @@ -99,7 +99,6 @@ This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the |`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | |`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | |`CIRQUE_PINNACLE_RESET_ON_INIT_WAIT` | (Optional) Wait time in milliseconds after sending reset during init. Use 0 to skip. | `30` | -|`CIRQUE_PINNACLE_POSITION_MODE` | (Optional) Absolute or Relative positioning mode. Use `CIRQUE_PINNACLE_{ABSOLUTE,RELATIVE}_MODE` | `CIRQUE_PINNACLE_ABSOLUTE_MODE` | **`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be. diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h index 13aa72631385..fc94519bc26f 100644 --- a/drivers/sensors/cirque_pinnacle.h +++ b/drivers/sensors/cirque_pinnacle.h @@ -38,7 +38,6 @@ # define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER) #endif #if !defined(POINTING_DEVICE_TASK_THROTTLE_MS) -# undef POINTING_DEVICE_TASK_THROTTLE_MS # define POINTING_DEVICE_TASK_THROTTLE_MS 10 // Cirque Pinnacle in normal operation produces data every 10ms. Advanced configuration for pen/stylus usage might require lower values. #endif #if defined(POINTING_DEVICE_DRIVER_cirque_pinnacle_i2c) diff --git a/drivers/sensors/cirque_pinnacle_i2c.c b/drivers/sensors/cirque_pinnacle_i2c.c index 9d645ba64fbb..b328dd9a7a3b 100644 --- a/drivers/sensors/cirque_pinnacle_i2c.c +++ b/drivers/sensors/cirque_pinnacle_i2c.c @@ -34,7 +34,7 @@ void RAP_Write(uint8_t address, uint8_t data) { if (touchpad_init) { if (i2c_writeReg(CIRQUE_PINNACLE_ADDR << 1, cmdByte, &data, sizeof(data), CIRQUE_PINNACLE_TIMEOUT) != I2C_STATUS_SUCCESS) { #ifdef CONSOLE_ENABLE - dprintf("error right touchpad\n"); + dprintf("error cirque_pinnacle i2c_writeReg\n"); #endif touchpad_init = false; } diff --git a/drivers/sensors/cirque_pinnacle_spi.c b/drivers/sensors/cirque_pinnacle_spi.c index 7786249b904d..bd980fc86334 100644 --- a/drivers/sensors/cirque_pinnacle_spi.c +++ b/drivers/sensors/cirque_pinnacle_spi.c @@ -25,7 +25,7 @@ void RAP_ReadBytes(uint8_t address, uint8_t* data, uint8_t count) { } } else { #ifdef CONSOLE_ENABLE - dprintf("error cirque_pinnacle spi_start\n"); + dprintf("error cirque_pinnacle spi_start read\n"); #endif touchpad_init = false; } @@ -43,7 +43,7 @@ void RAP_Write(uint8_t address, uint8_t data) { spi_write(data); } else { #ifdef CONSOLE_ENABLE - dprintf("error right touchpad\n"); + dprintf("error cirque_pinnacle spi_start write\n"); #endif touchpad_init = false; } diff --git a/quantum/pointing_device_drivers.c b/quantum/pointing_device_drivers.c index c2bbf93fecd5..435fcabf7cc9 100644 --- a/quantum/pointing_device_drivers.c +++ b/quantum/pointing_device_drivers.c @@ -107,10 +107,11 @@ const pointing_device_driver_t pointing_device_driver = { # endif report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { - pinnacle_data_t touchData = cirque_pinnacle_read_data(); - static uint16_t x = 0, y = 0, mouse_timer = 0; - mouse_xy_report_t report_x = 0, report_y = 0; - static bool is_z_down = false; + pinnacle_data_t touchData = cirque_pinnacle_read_data(); + mouse_xy_report_t report_x = 0, report_y = 0; + static mouse_xy_report_t x = 0, y = 0; + static uint16_t mouse_timer = 0; + static bool is_z_down = false; # if !CIRQUE_PINNACLE_POSITION_MODE # error Cirque Pinnacle with relative mode not implemented yet. @@ -130,8 +131,8 @@ report_mouse_t cirque_pinnacle_get_report(report_mouse_t mouse_report) { cirque_pinnacle_scale_data(&touchData, cirque_pinnacle_get_scale(), cirque_pinnacle_get_scale()); if (x && y && touchData.xValue && touchData.yValue) { - report_x = (int8_t)(touchData.xValue - x); - report_y = (int8_t)(touchData.yValue - y); + report_x = (mouse_xy_report_t)(touchData.xValue - x); + report_y = (mouse_xy_report_t)(touchData.yValue - y); } x = touchData.xValue; y = touchData.yValue; From 9aae2b1b54c0e6990d4aaf9970d16ce52e90f587 Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Sat, 25 Jun 2022 20:46:56 +0200 Subject: [PATCH 8/8] cirque: hard-code reset-on-init wait time --- docs/feature_pointing_device.md | 19 +++++++++---------- drivers/sensors/cirque_pinnacle.c | 4 +--- drivers/sensors/cirque_pinnacle.h | 3 --- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/docs/feature_pointing_device.md b/docs/feature_pointing_device.md index 87ce125e0d18..264362ea77fa 100644 --- a/docs/feature_pointing_device.md +++ b/docs/feature_pointing_device.md @@ -89,16 +89,15 @@ POINTING_DEVICE_DRIVER = cirque_pinnacle_spi This supports the Cirque Pinnacle 1CA027 Touch Controller, which is used in the TM040040, TM035035 and the TM023023 trackpads. These are I2C or SPI compatible, and both configurations are supported. -| Setting | Description | Default | -|-------------------------------------|--------------------------------------------------------------------------------------------------|---------------------------------| -|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` | -|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` | -|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` | -|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` | -|`CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `ADC_ATTENUATE_4X` | -|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | -|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | -|`CIRQUE_PINNACLE_RESET_ON_INIT_WAIT` | (Optional) Wait time in milliseconds after sending reset during init. Use 0 to skip. | `30` | +| Setting | Description | Default | +|-------------------------------- |-----------------------------------------------------------------------|--------------------- | +|`CIRQUE_PINNACLE_X_LOWER` | (Optional) The minimum reachable X value on the sensor. | `127` | +|`CIRQUE_PINNACLE_X_UPPER` | (Optional) The maximum reachable X value on the sensor. | `1919` | +|`CIRQUE_PINNACLE_Y_LOWER` | (Optional) The minimum reachable Y value on the sensor. | `63` | +|`CIRQUE_PINNACLE_Y_UPPER` | (Optional) The maximum reachable Y value on the sensor. | `1471` | +|`CIRQUE_PINNACLE_ATTENUATION` | (Optional) Sets the attenuation of the sensor data. | `ADC_ATTENUATE_4X` | +|`CIRQUE_PINNACLE_TAPPING_TERM` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | +|`CIRQUE_PINNACLE_TOUCH_DEBOUNCE` | (Optional) Length of time that a touch can be to be considered a tap. | `TAPPING_TERM`/`200` | **`CIRQUE_PINNACLE_ATTENUATION`** is a measure of how much data is suppressed in regards to sensitivity. The higher the attenuation, the less sensitive the touchpad will be. diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c index 9df42487b76c..1d1e4ccfc6c6 100644 --- a/drivers/sensors/cirque_pinnacle.c +++ b/drivers/sensors/cirque_pinnacle.c @@ -210,10 +210,8 @@ void cirque_pinnacle_init(void) { // Bit 1: Shutdown, 1=Shutdown, 0=Active // Bit 2: Sleep Enable, 1=low power mode, 0=normal mode // send a RESET command now, in case QMK had a soft-reset without a power cycle -#if CIRQUE_PINNACLE_RESET_ON_INIT_WAIT > 0 RAP_Write(SYSCONFIG_1, 0x01); - wait_ms(CIRQUE_PINNACLE_RESET_ON_INIT_WAIT); -#endif + wait_ms(30); // Pinnacle needs 10-15ms to boot, so wait long enough before configuring RAP_Write(SYSCONFIG_1, 0x00); wait_us(50); diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h index fc94519bc26f..d65bdb41b640 100644 --- a/drivers/sensors/cirque_pinnacle.h +++ b/drivers/sensors/cirque_pinnacle.h @@ -8,9 +8,6 @@ #ifndef CIRQUE_PINNACLE_TIMEOUT # define CIRQUE_PINNACLE_TIMEOUT 20 // I2C timeout in milliseconds #endif -#ifndef CIRQUE_PINNACLE_RESET_ON_INIT_WAIT -# define CIRQUE_PINNACLE_RESET_ON_INIT_WAIT 30 // milliseconds to wait after setting reset bit. Pinnacle needs 15-20ms to boot, increase if needed. Set to 0 to skip reset-on-init. -#endif #define CIRQUE_PINNACLE_ABSOLUTE_MODE 1 #define CIRQUE_PINNACLE_RELATIVE_MODE 0