From 0b726a437b8906fb52662504ccb6e4f052890f3c Mon Sep 17 00:00:00 2001 From: Drzony Date: Sat, 30 Jul 2022 06:20:34 +0200 Subject: Implement relative mode for Cirque trackpad (#17760) --- drivers/sensors/cirque_pinnacle.c | 83 +++++++++++++++++++++++++----- drivers/sensors/cirque_pinnacle.h | 51 +++++++++++------- drivers/sensors/cirque_pinnacle_gestures.c | 12 +++-- drivers/sensors/cirque_pinnacle_gestures.h | 5 +- drivers/sensors/cirque_pinnacle_regdefs.h | 2 +- 5 files changed, 115 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/sensors/cirque_pinnacle.c b/drivers/sensors/cirque_pinnacle.c index c50d5a2525..8bd4eb736e 100644 --- a/drivers/sensors/cirque_pinnacle.c +++ b/drivers/sensors/cirque_pinnacle.c @@ -9,6 +9,8 @@ #include "wait.h" #include "timer.h" +#include + #ifndef CIRQUE_PINNACLE_ATTENUATION # ifdef CIRQUE_PINNACLE_CURVED_OVERLAY # define CIRQUE_PINNACLE_ATTENUATION EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_2X @@ -31,6 +33,7 @@ void print_byte(uint8_t byte) { } #endif +#if CIRQUE_PINNACLE_POSITION_MODE /* Logical Scaling Functions */ // Clips raw coordinates to "reachable" window of sensor // NOTE: values outside this window can only appear as a result of noise @@ -46,6 +49,7 @@ void ClipCoordinates(pinnacle_data_t* coordinates) { coordinates->yValue = CIRQUE_PINNACLE_Y_UPPER; } } +#endif uint16_t cirque_pinnacle_get_scale(void) { return scale_data; @@ -56,6 +60,7 @@ void cirque_pinnacle_set_scale(uint16_t scale) { // Scales data to desired X & Y resolution void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResolution, uint16_t yResolution) { +#if CIRQUE_PINNACLE_POSITION_MODE uint32_t xTemp = 0; uint32_t yTemp = 0; @@ -71,6 +76,22 @@ void cirque_pinnacle_scale_data(pinnacle_data_t* coordinates, uint16_t xResoluti // 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); +#else + int32_t xTemp = 0, yTemp = 0; + ldiv_t temp; + static int32_t xRemainder, yRemainder; + + temp = ldiv(((int32_t)coordinates->xDelta) * (int32_t)xResolution + xRemainder, (int32_t)CIRQUE_PINNACLE_X_RANGE); + xTemp = temp.quot; + xRemainder = temp.rem; + + temp = ldiv(((int32_t)coordinates->yDelta) * (int32_t)yResolution + yRemainder, (int32_t)CIRQUE_PINNACLE_Y_RANGE); + yTemp = temp.quot; + yRemainder = temp.rem; + + coordinates->xDelta = (int16_t)xTemp; + coordinates->yDelta = (int16_t)yTemp; +#endif } // Clears Status1 register flags (SW_CC and SW_DR) @@ -142,14 +163,20 @@ void ERA_WriteByte(uint16_t address, uint8_t data) { cirque_pinnacle_clear_flags(); } -void cirque_pinnacle_set_adc_attenuation(uint8_t adcGain) { +bool cirque_pinnacle_set_adc_attenuation(uint8_t adcGain) { uint8_t adcconfig = 0x00; ERA_ReadBytes(EXTREG__TRACK_ADCCONFIG, &adcconfig, 1); - adcconfig &= EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_MASK; + adcGain &= EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_MASK; + if (adcGain == (adcconfig & EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_MASK)) { + return false; + } + adcconfig &= ~EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_MASK; adcconfig |= adcGain; ERA_WriteByte(EXTREG__TRACK_ADCCONFIG, adcconfig); ERA_ReadBytes(EXTREG__TRACK_ADCCONFIG, &adcconfig, 1); + + return true; } // Changes thresholds to improve detection of fingers @@ -207,30 +234,52 @@ void cirque_pinnacle_init(void) { touchpad_init = true; - // Host clears SW_CC flag - cirque_pinnacle_clear_flags(); - // send a RESET command now, in case QMK had a soft-reset without a power cycle RAP_Write(HOSTREG__SYSCONFIG1, HOSTREG__SYSCONFIG1__RESET); wait_ms(30); // Pinnacle needs 10-15ms to boot, so wait long enough before configuring RAP_Write(HOSTREG__SYSCONFIG1, HOSTREG__SYSCONFIG1_DEFVAL); wait_us(50); - // FeedConfig2 (Feature flags for Relative Mode Only) + // Host clears SW_CC flag + cirque_pinnacle_clear_flags(); + +#if CIRQUE_PINNACLE_POSITION_MODE RAP_Write(HOSTREG__FEEDCONFIG2, HOSTREG__FEEDCONFIG2_DEFVAL); +#else + // FeedConfig2 (Feature flags for Relative Mode Only) + uint8_t feedconfig2 = HOSTREG__FEEDCONFIG2__GLIDE_EXTEND_DISABLE | HOSTREG__FEEDCONFIG2__INTELLIMOUSE_MODE; +# if !defined(CIRQUE_PINNACLE_TAP_ENABLE) + feedconfig2 |= HOSTREG__FEEDCONFIG2__ALL_TAP_DISABLE; +# endif +# if !defined(CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE) + feedconfig2 |= HOSTREG__FEEDCONFIG2__SECONDARY_TAP_DISABLE; +# elif !defined(CIRQUE_PINNACLE_TAP_ENABLE) +# error CIRQUE_PINNACLE_TAP_ENABLE must be defined for CIRQUE_PINNACLE_SECONDARY_TAP_ENABLE to work +# endif +# if !defined(CIRQUE_PINNACLE_SIDE_SCROLL_ENABLE) + feedconfig2 |= HOSTREG__FEEDCONFIG2__SCROLL_DISABLE; +# endif + RAP_Write(HOSTREG__FEEDCONFIG2, feedconfig2); +#endif // FeedConfig1 (Data Output Flags) RAP_Write(HOSTREG__FEEDCONFIG1, CIRQUE_PINNACLE_POSITION_MODE ? HOSTREG__FEEDCONFIG1__DATA_TYPE__REL0_ABS1 : HOSTREG__FEEDCONFIG1_DEFVAL); +#if CIRQUE_PINNACLE_POSITION_MODE // Host sets z-idle packet count to 5 (default is 0x1E/30) RAP_Write(HOSTREG__ZIDLE, 5); +#endif + + bool calibrate = cirque_pinnacle_set_adc_attenuation(CIRQUE_PINNACLE_ATTENUATION); - cirque_pinnacle_set_adc_attenuation(CIRQUE_PINNACLE_ATTENUATION); #ifdef CIRQUE_PINNACLE_CURVED_OVERLAY cirque_pinnacle_tune_edge_sensitivity(); + calibrate = true; #endif - // Force a calibration after setting ADC attenuation - cirque_pinnacle_calibrate(); + if (calibrate) { + // Force a calibration after setting ADC attenuation + cirque_pinnacle_calibrate(); + } cirque_pinnacle_enable_feed(true); } @@ -265,10 +314,18 @@ pinnacle_data_t cirque_pinnacle_read_data(void) { #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]; + result.buttons = data[0] & 0x07; // Only three buttons are supported + if ((data[0] & 0x10) && data[1] != 0) { + result.xDelta = -((int16_t)256 - (int16_t)(data[1])); + } else { + result.xDelta = data[1]; + } + if ((data[0] & 0x20) && data[2] != 0) { + result.yDelta = ((int16_t)256 - (int16_t)(data[2])); + } else { + result.yDelta = -((int16_t)data[2]); + } + result.wheelCount = ((int8_t*)data)[3]; #endif result.valid = true; diff --git a/drivers/sensors/cirque_pinnacle.h b/drivers/sensors/cirque_pinnacle.h index 1c9bf06fd3..e9bb9621e4 100644 --- a/drivers/sensors/cirque_pinnacle.h +++ b/drivers/sensors/cirque_pinnacle.h @@ -21,24 +21,35 @@ # define CIRQUE_PINNACLE_DIAMETER_MM 40 #endif +#if CIRQUE_PINNACLE_POSITION_MODE // Coordinate scaling values -#ifndef CIRQUE_PINNACLE_X_LOWER -# define CIRQUE_PINNACLE_X_LOWER 127 // min "reachable" X value -#endif -#ifndef CIRQUE_PINNACLE_X_UPPER -# define CIRQUE_PINNACLE_X_UPPER 1919 // max "reachable" X value -#endif -#ifndef CIRQUE_PINNACLE_Y_LOWER -# define CIRQUE_PINNACLE_Y_LOWER 63 // min "reachable" Y value -#endif -#ifndef CIRQUE_PINNACLE_Y_UPPER -# define CIRQUE_PINNACLE_Y_UPPER 1471 // max "reachable" Y value -#endif -#ifndef CIRQUE_PINNACLE_X_RANGE -# define CIRQUE_PINNACLE_X_RANGE (CIRQUE_PINNACLE_X_UPPER - CIRQUE_PINNACLE_X_LOWER) -#endif -#ifndef CIRQUE_PINNACLE_Y_RANGE -# define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER) +# ifndef CIRQUE_PINNACLE_X_LOWER +# define CIRQUE_PINNACLE_X_LOWER 127 // min "reachable" X value +# endif +# ifndef CIRQUE_PINNACLE_X_UPPER +# define CIRQUE_PINNACLE_X_UPPER 1919 // max "reachable" X value +# endif +# ifndef CIRQUE_PINNACLE_Y_LOWER +# define CIRQUE_PINNACLE_Y_LOWER 63 // min "reachable" Y value +# endif +# ifndef CIRQUE_PINNACLE_Y_UPPER +# define CIRQUE_PINNACLE_Y_UPPER 1471 // max "reachable" Y value +# endif +# ifndef CIRQUE_PINNACLE_X_RANGE +# define CIRQUE_PINNACLE_X_RANGE (CIRQUE_PINNACLE_X_UPPER - CIRQUE_PINNACLE_X_LOWER) +# endif +# ifndef CIRQUE_PINNACLE_Y_RANGE +# define CIRQUE_PINNACLE_Y_RANGE (CIRQUE_PINNACLE_Y_UPPER - CIRQUE_PINNACLE_Y_LOWER) +# endif +# if defined(POINTING_DEVICE_GESTURE_SCROLL_ENABLE) +# define CIRQUE_PINNACLE_CIRCULAR_SCROLL_ENABLE +# endif +#else +# define CIRQUE_PINNACLE_X_RANGE 256 +# define CIRQUE_PINNACLE_Y_RANGE 256 +# if defined(POINTING_DEVICE_GESTURE_SCROLL_ENABLE) +# define CIRQUE_PINNACLE_SIDE_SCROLL_ENABLE +# endif #endif #if !defined(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. @@ -86,9 +97,9 @@ typedef struct { uint8_t buttonFlags; bool touchDown; #else - uint8_t xDelta; - uint8_t yDelta; - uint8_t wheelCount; + int16_t xDelta; + int16_t yDelta; + int8_t wheelCount; uint8_t buttons; #endif } pinnacle_data_t; diff --git a/drivers/sensors/cirque_pinnacle_gestures.c b/drivers/sensors/cirque_pinnacle_gestures.c index dc2f682a83..a73b745e59 100644 --- a/drivers/sensors/cirque_pinnacle_gestures.c +++ b/drivers/sensors/cirque_pinnacle_gestures.c @@ -24,11 +24,11 @@ # include "keyboard.h" #endif -#if defined(CIRQUE_PINNACLE_TAP_ENABLE) || defined(CIRQUE_PINNACLE_CIRCULAR_SCROLL_ENABLE) +#if (defined(CIRQUE_PINNACLE_TAP_ENABLE) || defined(CIRQUE_PINNACLE_CIRCULAR_SCROLL_ENABLE)) && CIRQUE_PINNACLE_POSITION_MODE static cirque_pinnacle_features_t features = {.tap_enable = true, .circular_scroll_enable = true}; #endif -#ifdef CIRQUE_PINNACLE_TAP_ENABLE +#if defined(CIRQUE_PINNACLE_TAP_ENABLE) && CIRQUE_PINNACLE_POSITION_MODE static trackpad_tap_context_t tap; static report_mouse_t trackpad_tap(report_mouse_t mouse_report, pinnacle_data_t touchData) { @@ -62,6 +62,9 @@ void cirque_pinnacle_enable_tap(bool enable) { #endif #ifdef CIRQUE_PINNACLE_CIRCULAR_SCROLL_ENABLE +# if !CIRQUE_PINNACLE_POSITION_MODE +# error "Circular scroll is not supported in relative mode" +# endif /* To set a trackpad exclusively as scroll wheel: outer_ring_pct = 100, trigger_px = 0, trigger_ang = 0 */ static circular_scroll_context_t scroll = {.config = {.outer_ring_pct = 33, .trigger_px = 16, @@ -213,6 +216,9 @@ bool cirque_pinnacle_gestures(report_mouse_t* mouse_report, pinnacle_data_t touc bool suppress_mouse_update = false; #ifdef CIRQUE_PINNACLE_CIRCULAR_SCROLL_ENABLE +# if !CIRQUE_PINNACLE_POSITION_MODE +# error "Circular scroll is not supported in relative mode" +# endif circular_scroll_t scroll_report; if (features.circular_scroll_enable) { scroll_report = circular_scroll(touchData); @@ -222,7 +228,7 @@ bool cirque_pinnacle_gestures(report_mouse_t* mouse_report, pinnacle_data_t touc } #endif -#ifdef CIRQUE_PINNACLE_TAP_ENABLE +#if defined(CIRQUE_PINNACLE_TAP_ENABLE) && CIRQUE_PINNACLE_POSITION_MODE if (features.tap_enable) { *mouse_report = trackpad_tap(*mouse_report, touchData); } diff --git a/drivers/sensors/cirque_pinnacle_gestures.h b/drivers/sensors/cirque_pinnacle_gestures.h index f39782b467..d2aa206b2b 100644 --- a/drivers/sensors/cirque_pinnacle_gestures.h +++ b/drivers/sensors/cirque_pinnacle_gestures.h @@ -24,7 +24,7 @@ typedef struct { bool circular_scroll_enable; } cirque_pinnacle_features_t; -#ifdef CIRQUE_PINNACLE_TAP_ENABLE +#if defined(CIRQUE_PINNACLE_TAP_ENABLE) && CIRQUE_PINNACLE_POSITION_MODE # ifndef CIRQUE_PINNACLE_TAPPING_TERM # include "action.h" # include "action_tapping.h" @@ -44,6 +44,9 @@ void cirque_pinnacle_enable_tap(bool enable); #endif #ifdef CIRQUE_PINNACLE_CIRCULAR_SCROLL_ENABLE +# if !CIRQUE_PINNACLE_POSITION_MODE +# error "Circular scroll is not supported in relative mode" +# endif typedef enum { SCROLL_UNINITIALIZED, SCROLL_DETECTING, diff --git a/drivers/sensors/cirque_pinnacle_regdefs.h b/drivers/sensors/cirque_pinnacle_regdefs.h index 993da1e757..fb9e09af6e 100644 --- a/drivers/sensors/cirque_pinnacle_regdefs.h +++ b/drivers/sensors/cirque_pinnacle_regdefs.h @@ -384,7 +384,7 @@ #define EXTREG__TRACK_ADCCONFIG 0x0187 // ADC-attenuation settings (held in BIT_7 and BIT_6) // 1X = most sensitive, 4X = least sensitive -# define EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_MASK 0x3F +# define EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_MASK 0xC0 # define EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_1X 0x00 # define EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_2X 0x40 # define EXTREG__TRACK_ADCCONFIG__ADC_ATTENUATE_3X 0x80 -- cgit v1.2.3