diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 6caaa3d4ad..17b767ec89 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -154,7 +154,6 @@ if(CMAKE_CROSSCOMPILING) set_property(TARGET asf4-drivers PROPERTY INTERFACE_LINK_LIBRARIES "") find_library(QTOUCHLIB_A qtm_acq_samd51_0x000f PATHS asf4-drivers/qtouch/lib/gcc NO_CMAKE_FIND_ROOT_PATH) - find_library(QTOUCHLIB_B qtm_binding_layer_cm4_0x0005 PATHS asf4-drivers/qtouch/lib/gcc NO_CMAKE_FIND_ROOT_PATH) find_library(QTOUCHLIB_T qtm_touch_key_cm4_0x0002 PATHS asf4-drivers/qtouch/lib/gcc NO_CMAKE_FIND_ROOT_PATH) add_library(cryptoauthlib diff --git a/external/asf4-drivers/Config/hpl_gclk_config.h b/external/asf4-drivers/Config/hpl_gclk_config.h index e62eab55bc..331ec261e2 100644 --- a/external/asf4-drivers/Config/hpl_gclk_config.h +++ b/external/asf4-drivers/Config/hpl_gclk_config.h @@ -387,7 +387,7 @@ // Indicates whether generic clock 5 configuration is enabled or not // enable_gclk_gen_5 #ifndef CONF_GCLK_GENERATOR_5_CONFIG -#define CONF_GCLK_GENERATOR_5_CONFIG 0 +#define CONF_GCLK_GENERATOR_5_CONFIG 1 #endif // Generic Clock Generator Control @@ -404,7 +404,7 @@ // This defines the clock source for generic clock generator 5 // gclk_gen_5_oscillator #ifndef CONF_GCLK_GEN_5_SOURCE -#define CONF_GCLK_GEN_5_SOURCE GCLK_GENCTRL_SRC_GCLKGEN1 +#define CONF_GCLK_GEN_5_SOURCE GCLK_GENCTRL_SRC_DFLL #endif // Run in Standby @@ -446,7 +446,7 @@ // Indicates whether Generic Clock Generator Enable is enabled or not // gclk_arch_gen_5_enable #ifndef CONF_GCLK_GEN_5_GENEN -#define CONF_GCLK_GEN_5_GENEN 0 +#define CONF_GCLK_GEN_5_GENEN 1 #endif // @@ -454,7 +454,7 @@ // Generic clock generator 5 division <0x0000-0xFFFF> // gclk_gen_5_div #ifndef CONF_GCLK_GEN_5_DIV -#define CONF_GCLK_GEN_5_DIV 62 +#define CONF_GCLK_GEN_5_DIV 6 #endif // // diff --git a/external/asf4-drivers/Config/peripheral_clk_config.h b/external/asf4-drivers/Config/peripheral_clk_config.h index d557fe9e81..8e6eb0cf22 100644 --- a/external/asf4-drivers/Config/peripheral_clk_config.h +++ b/external/asf4-drivers/Config/peripheral_clk_config.h @@ -33,7 +33,7 @@ // Select the clock source for ADC. #ifndef CONF_GCLK_ADC0_SRC -#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK2_Val +#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK5_Val #endif /** @@ -41,7 +41,7 @@ * \brief ADC0's Clock frequency */ #ifndef CONF_GCLK_ADC0_FREQUENCY -#define CONF_GCLK_ADC0_FREQUENCY 12000000 +#define CONF_GCLK_ADC0_FREQUENCY 8000000 #endif /** diff --git a/external/asf4-drivers/qtouch/include/qtm_acq_same54_0x000f_api.h b/external/asf4-drivers/qtouch/include/qtm_acq_same54_0x000f_api.h index a75fbcce22..9e03ecb380 100644 --- a/external/asf4-drivers/qtouch/include/qtm_acq_same54_0x000f_api.h +++ b/external/asf4-drivers/qtouch/include/qtm_acq_same54_0x000f_api.h @@ -80,14 +80,14 @@ typedef enum tag_gain_t { GAIN_1, GAIN_2, GAIN_4, GAIN_8, GAIN_16 } gain_t; * */ typedef enum tag_prsc_div_sel_t { - PRSC_DIV_SEL_1, PRSC_DIV_SEL_2, PRSC_DIV_SEL_4, PRSC_DIV_SEL_8, PRSC_DIV_SEL_16, PRSC_DIV_SEL_32, PRSC_DIV_SEL_64, - PRSC_DIV_SEL_128 + PRSC_DIV_SEL_128, + PRSC_DIV_SEL_256 } prsc_div_sel_t; /** diff --git a/external/asf4-drivers/qtouch/include/qtm_binding_layer_0x0005_api.h b/external/asf4-drivers/qtouch/include/qtm_binding_layer_0x0005_api.h deleted file mode 100644 index 7e4950e1c9..0000000000 --- a/external/asf4-drivers/qtouch/include/qtm_binding_layer_0x0005_api.h +++ /dev/null @@ -1,226 +0,0 @@ -/*============================================================================ -Filename : qtm_binding_layer_api.h -Project : QTouch Modular Library -Purpose : Binds the acquisition and post processing modules and provides callback ------------------------------------------------------------------------------- -Copyright (c) 2017 Microchip. All rights reserved. ------------------------------------------------------------------------------- -============================================================================*/ - -/** @file */ - -/** \defgroup Misra Misra Compliance report */ - -/** - * \addtogroup Misra - * Complaiance:
- * the module code is compiled using IARs Embedded workbench for AVR
- * MISRA 2004 compliance is selected with all required options selected
- * any rule which has been violated will be documented and the rule switched off
- *
- *
- */ - -#ifndef TOUCH_API_BINDING_LAYER_H -#define TOUCH_API_BINDING_LAYER_H - -/* Include files */ -#include -#include "qtm_common_components_api.h" - -/*---------------------------------------------------------------------------- -manifest constants -----------------------------------------------------------------------------*/ -#define null '\0' - -/*---------------------------------------------------------------------------- - * type definitions - *----------------------------------------------------------------------------*/ - -/* Modular Library state */ -typedef enum QT_Modular_lib_state_tag { uninitialised, config_initialised, ready, busy, processing, error } qtm_state_t; - -typedef enum QT_ModLib_Status_flags { - time_to_measure_touch, - node_pp_request, - reburst_request, - reserved_flag_pos_3, - - reserved_flag_pos_4, - reserved_flag_pos_5, - reserved_flag_pos_6, - reserved_flag_pos_7, -} qtm_flags; - -typedef void (*qtm_measure_complete_t)(void); -typedef void (*qtm_library_init_complete_t)(void); -typedef void (*qtm_pre_process_callback_t)(uint8_t *callback); -typedef void (*qtm_error_callback_t)(uint8_t error_code); -typedef void (*qtm_post_process_callback_t)(void); - -typedef void *(*module_init_t)(void *data_model); -typedef void *(*module_proc_t)(void *data_model); -typedef void *(*module_init_inline_t)(void *data_model); -typedef void *(*module_inline_t)(void *data_model); -typedef void *(*module_conf_t)(void *data_model); -typedef void *(*module_acq_t)(void *data_model, void (*callback)(void)); - -/* this should take an arqument */ -typedef touch_ret_t(qtm_acq_pp_t)(void); - -typedef void *module_arg_t; - -/*---------------------------------------------------------------------------- - * Structure Declarations - *----------------------------------------------------------------------------*/ - -/* ---------------------------------------------------------------------------------------- */ -/* Key sensor run-time data - api common */ -/* ---------------------------------------------------------------------------------------- */ - -/* Container */ -/** - * @brief a collection of controls for the binding layer - */ -typedef struct qtm_control_tag /*!< Control structure for the bonsding layer */ -{ - uint8_t binding_layer_flags; /*!< Some Flags */ - - module_init_t *library_modules_init; /*!< List of function pointers to acquisition sets */ - module_proc_t *library_modules_proc; /*!< List of function pointers to post processing modules */ - module_acq_t * library_modules_acq; - - module_arg_t *library_module_init_data_model; /*!< Data Model for Acquisition modules */ - module_arg_t *library_module_proc_data_model; /*!< Data Model for post processing modules */ - module_arg_t *library_modules_acq_dm; /*!< Data model for inline module processes */ - - qtm_acq_pp_t *qtm_acq_pp; /*!< Post porcessing pointer */ - - /*******************************/ - /* Callbacks for Binding layer */ - /*******************************/ - qtm_library_init_complete_t qtm_init_complete_callback; - qtm_error_callback_t qtm_error_callback; - qtm_measure_complete_t qtm_measure_complete_callback; - qtm_pre_process_callback_t qtm_pre_process_callback; - qtm_post_process_callback_t qtm_post_process_callback; - -} qtm_control_t; - -/*---------------------------------------------------------------------------- - * prototypes - *----------------------------------------------------------------------------*/ - -/** - * @brief Returns a pointer to the binding layer control structure - * - * This function is never used in the example code, but it is included here - * in case the user would like to get a (qtm_control_t) - * - * This function accepts no inputs - * - * @return &qtm_control, this is a pointer to the binding layer control structure - */ -qtm_control_t *qmt_get_binding_layer_ptr(void); - -/** - * Initialises the binding layer, there are two possible outcomes - * - * - * 1). There were no errors - * \msc - * a [label="User Application"],b [label="Modular Library"]; - * a=>>b [label="qtm_lib_init(&qtm_control);"]; - * b=>b; - * a<<=b [label="qtm_init_complete_callback();"]; - * \endmsc - * - * 2). There were errors detected - * \msc - * a [label="User Application"],b [label="Modular Library"]; - * a=>>b [label="qtm_lib_init(&qtm_control);"]; - * b=>b; - * a<<=b [label="qtm_error_callback(error_code);"]; - * \endmsc - */ - -/** - * @see qtm_state_t for a state diagram - * @param qtm_control This is the control structure to the binding layer - */ - -/** - * Typical Application flow. - * - * @msc - * a [label="User Application"],b [label="Modular Library"]; - * a=>>b [label="qtm_lib_init(&qtm_control);"]; - * b=>b; - * a<<=b [label="qtm_init_complete_callback();"]; - * a=>>b [label="qtm_calibrate_hardware();"]; - * --- [ label = "library setup, Start normal acquisition" ]; - * a=>>b [label="qtm_lib_start_acquisition();"]; - * b=>b; - * a<<=b [label="qtm_measure_complete_callback();"]; - * ...; - * a=>>b [label="qtm_lib_start_acquisition();"]; - * b=>b; - * a<<=b [label="qtm_measure_complete_callback();"]; - * ...; - * a=>>b [label="qtm_lib_start_acquisition();"]; - * b=>b; - * a<<=b [label="qtm_measure_complete_callback();"]; - * ...; - * a=>>b [label="qtm_lib_start_acquisition();"]; - * b=>b; - * a<<=b [label="qtm_measure_complete_callback();"]; - * ...; - * @endmsc - */ - -void qtm_binding_layer_init(qtm_control_t *qtm_control); - -/** - * @brief Starts the Modular library on the first acquisition set - * - * An Acquisition set is defined in the Acquisition Module documentation, but - * essentially an acquisition set is a group of node with a common property, - * the common property can be, Acquisition Type: Self or Mutual, or proximity or - * spatial displacement to or from another. - * - * @return the library state, @see qtm_state_t - */ -touch_ret_t qtm_lib_start_acquisition(uint8_t set_id); - -/*qtm_state_t qtm_post_process(void);*/ -touch_ret_t qtm_lib_post_process(void); - -/** - * @brief Gets the library state - * - * some tasks cannot happen if the library is not in the correct state - * if the library is requesting a start acquisition when there is an - * ongoing acquisition then the binding layer will move to the error - * state, checking the library state before acquisition will prevent - * errors like this. - * - * @return the library state, - * @see qtm_state_t - */ -qtm_state_t qtm_lib_get_state(void); - -touch_ret_t qtm_lib_acq_process(void); - -uint16_t qtm_get_binding_layer_module_id(void); - -/*============================================================================ -uint8_t get_qtm_m328pb_acq_module_version(void) ------------------------------------------------------------------------------- -Purpose: Returns the module Firmware version -Input : none -Output : Module ID - Upper nibble major / Lower nibble minor -Notes : none -============================================================================*/ -uint8_t qtm_get_binding_layer_module_version(void); - -#endif /* TOUCH_API_BINDING_LAYER_H */ diff --git a/external/asf4-drivers/qtouch/include/qtm_scroller_0x000b_api.h b/external/asf4-drivers/qtouch/include/qtm_scroller_0x000b_api.h deleted file mode 100644 index 3079b90362..0000000000 --- a/external/asf4-drivers/qtouch/include/qtm_scroller_0x000b_api.h +++ /dev/null @@ -1,151 +0,0 @@ -/*============================================================================ -Filename : qtm_scroller_api.h -Project : QTouch Modular Library -Purpose : Structs and definitions for use within modules ------------------------------------------------------------------------------- -Copyright (c) 2017 Microchip. All rights reserved. ------------------------------------------------------------------------------- -============================================================================*/ - -#ifndef TOUCH_API_SCROLLER_H -#define TOUCH_API_SCROLLER_H - -/* Include files */ -#include -#include "qtm_common_components_api.h" - -/* Scroller status bits */ -#define TOUCH_ACTIVE (uint8_t)((uint8_t)1 << 0u) /* Bit 0 */ -#define POSITION_CHANGE (uint8_t)((uint8_t)1 << 1u) /* Bit 1 */ -#define SCROLLER_REBURST (uint8_t)((uint8_t)1 << 7u) /* Bit 7 */ - -/* Extract Resolution / Deadband */ -#define SCR_RESOLUTION(m) (uint8_t)(((m)&0xF0u) >> 4u) -#define SCR_DEADBAND(m) (uint8_t)((m)&0x0Fu) - -/* Combine Resolution / Deadband */ -#define SCR_RESOL_DEADBAND(r, p) (uint8_t)(((r) << 4u) | (p)) - -/* scroller resolution setting */ -typedef enum tag_resolution_t { - RESOL_2_BIT = 2, - RESOL_3_BIT, - RESOL_4_BIT, - RESOL_5_BIT, - RESOL_6_BIT, - RESOL_7_BIT, - RESOL_8_BIT, - RESOL_9_BIT, - RESOL_10_BIT, - RESOL_11_BIT, - RESOL_12_BIT -} scr_resolution_t; - -/* scroller deadband percentage setting */ -typedef enum tag_deadband_t { - DB_NONE, - DB_1_PERCENT, - DB_2_PERCENT, - DB_3_PERCENT, - DB_4_PERCENT, - DB_5_PERCENT, - DB_6_PERCENT, - DB_7_PERCENT, - DB_8_PERCENT, - DB_9_PERCENT, - DB_10_PERCENT, - DB_11_PERCENT, - DB_12_PERCENT, - DB_13_PERCENT, - DB_14_PERCENT, - DB_15_PERCENT -} scr_deadband_t; - -/*---------------------------------------------------------------------------- - * Structure Declarations - *----------------------------------------------------------------------------*/ - -/* Configuration - Group of scrollers */ -typedef struct { - qtm_touch_key_data_t *qtm_touch_key_data; - uint8_t num_scrollers; -} qtm_scroller_group_config_t; - -/* Data - Group of scrollers */ -typedef struct { - uint8_t scroller_group_status; -} qtm_scroller_group_data_t; - -/* Configuration - Each slider / wheel */ -typedef struct { - uint8_t type; - uint16_t start_key; - uint8_t number_of_keys; - uint8_t resol_deadband; - uint8_t position_hysteresis; - uint16_t contact_min_threshold; -} qtm_scroller_config_t; - -/* Data Each - slider / wheel */ -typedef struct { - uint8_t scroller_status; - uint8_t right_hyst; - uint8_t left_hyst; - uint16_t raw_position; - uint16_t position; - uint16_t contact_size; -} qtm_scroller_data_t; - -/* Container */ -typedef struct { - qtm_scroller_group_data_t * qtm_scroller_group_data; - qtm_scroller_group_config_t *qtm_scroller_group_config; - qtm_scroller_data_t * qtm_scroller_data; - qtm_scroller_config_t * qtm_scroller_config; -} qtm_scroller_control_t; - -/*---------------------------------------------------------------------------- - * prototypes - *----------------------------------------------------------------------------*/ - -/*============================================================================ -touch_ret_t qtm_init_scroller_module(qtm_scroller_control_t *qtm_scroller_control) ------------------------------------------------------------------------------- -Purpose: Initialize a scroller -Input : Pointer to scroller group control data -Output : TOUCH_SUCCESS -Notes : none -============================================================================*/ -touch_ret_t qtm_init_scroller_module(qtm_scroller_control_t *qtm_scroller_control); - -/*============================================================================ -touch_ret_t qtm_scroller_process(qtm_scroller_control_t *qtm_scroller_control) ------------------------------------------------------------------------------- -Purpose: Scroller position calculation and filtering -Input : Pointer to scroller group control data -Output : TOUCH_SUCCESS -Notes : none -============================================================================*/ -touch_ret_t qtm_scroller_process(qtm_scroller_control_t *qtm_scroller_control); - -/*============================================================================ -uint16_t qtm_get_scroller_module_id(void) ------------------------------------------------------------------------------- -Purpose: Returns the module ID -Input : none -Output : Module ID -Notes : none -============================================================================*/ -uint16_t qtm_get_scroller_module_id(void); - -/*============================================================================ -uint8_t qtm_get_scroller_module_ver(void) ------------------------------------------------------------------------------- -Purpose: Returns the module Firmware version -Input : none -Output : Module ID - Upper nibble major / Lower nibble minor -Notes : none -============================================================================*/ -uint8_t qtm_get_scroller_module_ver(void); - -#endif /* TOUCH_API_SCROLLER_H */ diff --git a/external/asf4-drivers/qtouch/include/touch_api_ptc.h b/external/asf4-drivers/qtouch/include/touch_api_ptc.h index 15f693cf42..2ea3b45585 100644 --- a/external/asf4-drivers/qtouch/include/touch_api_ptc.h +++ b/external/asf4-drivers/qtouch/include/touch_api_ptc.h @@ -32,30 +32,32 @@ extern "C" { #include "hal_timer.h" -#include "qtm_common_components_api.h" -#include "qtm_binding_layer_0x0005_api.h" #include "qtm_acq_samd51_0x000f_api.h" +#include "qtm_common_components_api.h" #include "qtm_touch_key_0x0002_api.h" -#include "qtm_scroller_0x000b_api.h" /*---------------------------------------------------------------------------- * prototypes *----------------------------------------------------------------------------*/ /* Application Helper API's */ uint16_t qtouch_get_sensor_node_signal(uint16_t sensor_node); -uint16_t qtouch_get_sensor_node_reference(uint16_t sensor_node); +void qtouch_update_sensor_node_signal(uint16_t sensor_node, uint16_t new_signal); uint16_t qtouch_get_sensor_node_signal_filtered(uint16_t sensor_node); +uint16_t qtouch_get_sensor_node_reference(uint16_t sensor_node); +void qtouch_update_sensor_node_reference(uint16_t sensor_node, uint16_t new_reference); uint16_t qtouch_get_sensor_cc_val(uint16_t sensor_node); +void qtouch_update_sensor_cc_val(uint16_t sensor_node, uint16_t new_cc_value); uint8_t qtouch_get_sensor_state(uint16_t sensor_node); +void qtouch_update_sensor_state(uint16_t sensor_node, uint8_t new_state); +void qtouch_calibrate_node(uint16_t sensor_node); +uint8_t qtouch_get_scroller_state(uint16_t sensor_node); bool qtouch_is_scroller_active(uint16_t sensor_node); uint16_t qtouch_get_scroller_position(uint16_t sensor_node); void qtouch_timer_handler(void); void qtouch_init(void); void qtouch_process(void); -void qtouch_force_calibrate(void); -void qtimer_task_cb(const struct timer_task *const timer_task); void qtouch_timer_config(void); #ifdef __cplusplus diff --git a/external/asf4-drivers/qtouch/lib/gcc/libqtm_binding_layer_cm4_0x0005.a b/external/asf4-drivers/qtouch/lib/gcc/libqtm_binding_layer_cm4_0x0005.a deleted file mode 100644 index c6658cc462..0000000000 Binary files a/external/asf4-drivers/qtouch/lib/gcc/libqtm_binding_layer_cm4_0x0005.a and /dev/null differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 93daee2cf7..4d0f99fc56 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -506,7 +506,7 @@ if(CMAKE_CROSSCOMPILING) foreach(bootloader ${DEVDEVICE-BOOTLOADERS} ${BOOTLOADERS-BITBOX02PLUS}) set(elf ${bootloader}.elf) - target_link_libraries(${elf} PRIVATE ${QTOUCHLIB_A} ${QTOUCHLIB_B} ${QTOUCHLIB_T}) + target_link_libraries(${elf} PRIVATE ${QTOUCHLIB_A} ${QTOUCHLIB_T}) target_sources(${elf} PRIVATE ${QTOUCH-SOURCES}) endforeach(bootloader) @@ -571,7 +571,7 @@ if(CMAKE_CROSSCOMPILING) target_link_libraries(${elf} PRIVATE -Wl,--defsym=STACK_SIZE=${STACK_SIZE} -Wl,-defsym=HEAP_SIZE=${HEAP_SIZE}) target_link_libraries(${elf} PRIVATE secp256k1) - target_link_libraries(${elf} PRIVATE ${QTOUCHLIB_A} ${QTOUCHLIB_B} ${QTOUCHLIB_T}) + target_link_libraries(${elf} PRIVATE ${QTOUCHLIB_A} ${QTOUCHLIB_T}) # Select the smaller version of libc called nano. target_compile_options(${elf} PRIVATE --specs=nano.specs) diff --git a/src/bootloader/bootloader.c b/src/bootloader/bootloader.c index 3791fe4e72..4b69f01865 100644 --- a/src/bootloader/bootloader.c +++ b/src/bootloader/bootloader.c @@ -363,7 +363,6 @@ extern uint8_t bootloader_pairing_code_bytes[4]; void bootloader_render_ble_confirm_screen(bool confirmed) { - qtouch_force_calibrate(); bootloader_pairing_request = true; uint32_t pairing_code_int = (*(uint32_t*)&bootloader_pairing_code_bytes[0]) % 1000000; char code_str[10] = {0}; diff --git a/src/qtouch/qtouch.c b/src/qtouch/qtouch.c index f6ad8f57eb..46c8e338cf 100644 --- a/src/qtouch/qtouch.c +++ b/src/qtouch/qtouch.c @@ -18,63 +18,51 @@ Support: Visit http://www.microchip.com/support/hottopics.aspx Copyright (c) 2017 Microchip. All rights reserved. ------------------------------------------------------------------------------ ============================================================================*/ - #ifndef TOUCH_C #define TOUCH_C /*---------------------------------------------------------------------------- * include files *----------------------------------------------------------------------------*/ -#include "qtouch.h" +#include + #include "license.h" -#include "touch_api_ptc.h" -#include "util.h" -#include -#include +#include "qtouch.h" + +// #include "datastreamer.h" /*---------------------------------------------------------------------------- * prototypes *----------------------------------------------------------------------------*/ -/*! \brief configure binding layer config parameter - */ -static void build_qtm_config(qtm_control_t* qtm); - /*! \brief configure keys, wheels and sliders. */ static touch_ret_t touch_sensors_config(void); -/*! \brief Init complete callback function prototype. - */ -static void init_complete_callback(void); - /*! \brief Touch measure complete callback function example prototype. */ static void qtm_measure_complete_callback(void); -/*! \brief Touch post process complete callback function prototype. - */ -static void qtm_post_process_complete(void); - /*! \brief Touch Error callback function prototype. */ -static void qtm_error_callback(uint8_t err); +static void qtm_error_callback(uint8_t error); -/*! \brief Calculate scroller positions based on custom filter. +/* Update our scroller implementation */ -static void qtouch_process_scroller_positions(void); +void qtouch_process_scroller_positions(scroller_control_t* scrollers); /*---------------------------------------------------------------------------- * Global Variables *----------------------------------------------------------------------------*/ -/* Binding layer control */ -qtm_control_t qtm_control; -qtm_control_t* p_qtm_control; -qtm_state_t qstate; +/* Flag to indicate time for touch measurement */ +volatile uint8_t time_to_measure_touch_flag = 0; + +/* postporcess request flag */ +volatile uint8_t touch_postprocess_request = 0; /* Measurement Done Touch Flag */ -volatile bool measurement_done_touch = false; +volatile uint8_t measurement_done_touch = 0; /* Error Handling */ uint8_t module_error_code = 0; @@ -110,17 +98,6 @@ qtm_acquisition_control_t qtlib_acq_set1 = { &ptc_seq_node_cfg1[0], &ptc_qtlib_node_stat1[0]}; -/* Stores recent unfiltered scroller positions for custom filter */ -__extension__ static uint16_t scroller_previous_position[][DEF_SCROLLER_NUM_PREV_POS] = { - [0 ...(DEF_NUM_SCROLLERS - 1)][0 ...(DEF_SCROLLER_NUM_PREV_POS - 1)] = 0}; - -/* Current scroller position consisting of a moving-average of preceding positions for custom filter - */ -__extension__ static uint16_t scroller_position[] = {[0 ...(DEF_NUM_SCROLLERS - 1)] = 0}; - -/* Whether or not scroller reading exceeds threshold for custom filter */ -__extension__ static bool scroller_active[DEF_NUM_SCROLLERS] = {[0 ...(DEF_NUM_SCROLLERS - 1)] = 0}; - /**********************************************************/ /*********************** Keys Module **********************/ /**********************************************************/ @@ -152,6 +129,7 @@ qtm_touch_key_config_t qtlib_key_configs_set1[DEF_NUM_SENSORS] = { KEY_5_PARAMS, KEY_6_PARAMS, KEY_7_PARAMS}; + /* Container */ qtm_touch_key_control_t qtlib_key_set1 = { &qtlib_key_grp_data_set1, @@ -171,75 +149,35 @@ qtm_touch_key_control_t qtlib_key_set1 = { * fast responsiveness. */ -/**********************************************************/ -/**************** Binding Layer Module ******************/ -/**********************************************************/ -#define LIB_MODULES_INIT_LIST {(module_init_t) & qtm_ptc_init_acquisition_module, null} - -#define LIB_MODULES_PROC_LIST {(module_proc_t) & qtm_key_sensors_process, null} - -#define LIB_INIT_DATA_MODELS_LIST {(void*)&qtlib_acq_set1, null} - -#define LIB_DATA_MODELS_PROC_LIST {(void*)&qtlib_key_set1, null} - -#define LIB_MODULES_ACQ_ENGINES_LIST {(module_acq_t) & qtm_ptc_start_measurement_seq, null} - -#define LIB_MODULES_ACQ_ENGINES_LIST_DM {(void*)&qtlib_acq_set1, null} - -/* QTM run time options */ -module_init_t library_modules_init[] = LIB_MODULES_INIT_LIST; -module_proc_t library_modules_proc[] = LIB_MODULES_PROC_LIST; -module_arg_t library_module_init_data_models[] = LIB_INIT_DATA_MODELS_LIST; -module_acq_t library_modules_acq_engines[] = LIB_MODULES_ACQ_ENGINES_LIST; - -module_arg_t library_module_acq_engine_data_model[] = LIB_MODULES_ACQ_ENGINES_LIST_DM; -module_arg_t library_module_proc_data_model[] = LIB_DATA_MODELS_PROC_LIST; - -/*---------------------------------------------------------------------------- - * function definitions - *----------------------------------------------------------------------------*/ - -/*============================================================================ -static void build_qtm_config(qtm_control_t *qtm) ------------------------------------------------------------------------------- -Purpose: Initialization of binding layer module -Input : Pointer of binding layer container data structure -Output : none -Notes : -============================================================================*/ -static void build_qtm_config(qtm_control_t* qtm) -{ - /* Initialise the Flags by clearing them */ - qtm->binding_layer_flags = 0x00U; - - /*!< List of function pointers to acquisition sets */ - qtm->library_modules_init = library_modules_init; - - /*!< List of function pointers to post processing modules */ - qtm->library_modules_proc = library_modules_proc; - - /*!< List of Acquisition Engines (Acq Modules one per AcqSet */ - qtm->library_modules_acq = library_modules_acq_engines; - - /*!< Data Model for Acquisition modules */ - qtm->library_module_init_data_model = library_module_init_data_models; - - /*!< Data Model for post processing modules */ - qtm->library_module_proc_data_model = library_module_proc_data_model; - - /*!< Data model for inline module processes */ - qtm->library_modules_acq_dm = library_module_acq_engine_data_model; - - /*!< Post porcessing pointer */ - qtm->qtm_acq_pp = qtm_acquisition_process; - - /* Register Binding layer callbacks */ - qtm->qtm_init_complete_callback = init_complete_callback; - qtm->qtm_error_callback = qtm_error_callback; - qtm->qtm_measure_complete_callback = qtm_measure_complete_callback; - qtm->qtm_pre_process_callback = null; - qtm->qtm_post_process_callback = qtm_post_process_complete; -} +/* Holds preceding touch key deltas (signal - reference) */ +__extension__ int16_t scroller_deltas[DEF_NUM_SENSORS] = {0}; + +scroller_config_t scroller_config[2] = { + [0] = + {DEF_SCROLLER_OFFSET_0, + DEF_SCROLLER_NUM_CHANNELS, + DEF_SCROLLER_RESOLUTION, + DEF_SCROLLER_TOUCH_THRESHOLD, + DEF_SCROLLER_UNTOUCH_THRESHOLD, + DEF_SCROLLER_DEADBAND, + DEF_SCROLLER_HYSTERESIS, + DEF_SCROLLER_TOUCH_DRIFT_IN}, + [1] = + {DEF_SCROLLER_OFFSET_1, + DEF_SCROLLER_NUM_CHANNELS, + DEF_SCROLLER_RESOLUTION, + DEF_SCROLLER_TOUCH_THRESHOLD, + DEF_SCROLLER_UNTOUCH_THRESHOLD, + DEF_SCROLLER_DEADBAND, + DEF_SCROLLER_HYSTERESIS, + DEF_SCROLLER_TOUCH_DRIFT_IN}, +}; +scroller_data_t scroller_data[2] = {0}; + +scroller_control_t scroller_control[2] = { + [0] = {&scroller_config[0], &scroller_data[0]}, + [1] = {&scroller_config[1], &scroller_data[1]}, +}; /*============================================================================ static touch_ret_t touch_sensors_config(void) @@ -249,69 +187,37 @@ Input : none Output : none Notes : ============================================================================*/ -/* Touch sensors config - assign nodes to buttons / wheels / sliders / surfaces / water level / etc - */ +/* Touch sensors config - assign nodes to buttons / wheels / sliders / surfaces + * / water level / etc */ static touch_ret_t touch_sensors_config(void) { uint16_t sensor_nodes; touch_ret_t touch_ret = TOUCH_SUCCESS; + /* Init acquisition module */ + qtm_ptc_init_acquisition_module(&qtlib_acq_set1); + /* Init pointers to DMA sequence memory */ qtm_ptc_qtlib_assign_signal_memory(&touch_acq_signals_raw[0]); /* Initialize sensor nodes */ - for (sensor_nodes = 0U; sensor_nodes < DEF_NUM_CHANNELS; sensor_nodes++) { + for (sensor_nodes = 0u; sensor_nodes < DEF_NUM_CHANNELS; sensor_nodes++) { /* Enable each node for measurement and mark for calibration */ qtm_enable_sensor_node(&qtlib_acq_set1, sensor_nodes); qtm_calibrate_sensor_node(&qtlib_acq_set1, sensor_nodes); } /* Enable sensor keys and assign nodes */ - for (sensor_nodes = 0U; sensor_nodes < DEF_NUM_CHANNELS; sensor_nodes++) { + for (sensor_nodes = 0u; sensor_nodes < DEF_NUM_CHANNELS; sensor_nodes++) { qtm_init_sensor_key(&qtlib_key_set1, sensor_nodes, &ptc_qtlib_node_stat1[sensor_nodes]); } return (touch_ret); } -/* - * Force calibrate - * - * Call this function when the user "probably" isn't touching the device to reset all the - * calibration values. It will only reset inputs that are not considered to be in "touched" states - */ -void qtouch_force_calibrate(void) -{ - qtm_touch_key_data_t* key; - for (uint16_t i = 0U; i < DEF_NUM_CHANNELS; i++) { - key = &qtlib_key_data_set1[i]; - uint16_t value = key->node_data_struct_ptr->node_acq_signals; - uint16_t reference = key->channel_reference; - int32_t diff = (int32_t)reference - (int32_t)value; - if (!(key->sensor_state & KEY_TOUCHED_MASK) && diff > KEY_FORCE_CALIBRATE_THRESHOLD) { - key->channel_reference = key->node_data_struct_ptr->node_acq_signals; - } - } -} - -/*============================================================================ -static void init_complete_callback(void) ------------------------------------------------------------------------------- -Purpose: Callback function from binding layer called after the completion of - acquisition module initialization. -Input : none -Output : none -Notes : -============================================================================*/ -static void init_complete_callback(void) -{ - /* Configure touch sensors with Application specific settings */ - touch_sensors_config(); -} - /*============================================================================ static void qtm_measure_complete_callback( void ) ------------------------------------------------------------------------------ -Purpose: Callback function from binding layer called after the completion of +Purpose: this function is called after the completion of measurement cycle. This function sets the post processing request flag to trigger the post processing. Input : none @@ -320,109 +226,50 @@ Notes : ============================================================================*/ static void qtm_measure_complete_callback(void) { - qtm_control.binding_layer_flags |= (1 << node_pp_request); -} - -/*============================================================================ -static void qtm_post_process_complete(void) ------------------------------------------------------------------------------- -Purpose: Callback function from binding layer called after the completion of - post processing. This function sets the reburst flag based on the - key sensor group status, calls the datastreamer output function to - display the module data. -Input : none -Output : none -Notes : -============================================================================*/ -static void qtm_post_process_complete(void) -{ - { - // This block is a workaround for a rare touch issue. - // - // After boot, reburst is required until the sensors are calibrated (see reburst_request - // below). Afterwards, they are calibrated and the sensor signal and reference values can be - // used to figure out touch gestures. - // - // Normally, calibration finishes quickly (tests showed in about 12 loop iterations). - // Afterwards, reference and signal values are non-zero. In very rare cases, a sensor can - // have a reference value of 0 until it is physically touched, meaning that touch is - // required to finish calibration. This could be due to a hardware or production quirk. In - // this case, reburst would be requested until that sensor is touched, and gesture detection - // would not start until then. In this csae, a user could not interact with the device at - // all until they first touched the faulty sensor. - // - // As a workaround for this, if we have sensors with a zero reference value of 0 after 30 - // iterations, we assume that all other sensors are calibrated and allow gesture detection - // and user interaction. When the user then touches the weird sensor with a zero reference - // value in normal use of the device, it too would be calibrated and start working normally. - static int counter = 0; - if (counter == 30 && !measurement_done_touch) { - for (uint16_t i = 0; i < DEF_NUM_SENSORS; i++) { - if (qtouch_get_sensor_node_reference(i) == 0) { - measurement_done_touch = true; - break; - } - } - } - counter++; - } - - if ((0U != (qtlib_key_set1.qtm_touch_key_group_data->qtm_keys_status & 0x80U))) { - p_qtm_control->binding_layer_flags |= (1U << reburst_request); - } else { - measurement_done_touch = true; - } - - if (measurement_done_touch) { - qtouch_process_scroller_positions(); // Run the custom filter - } + touch_postprocess_request = 1u; } /*============================================================================ static void qtm_error_callback(uint8_t error) ------------------------------------------------------------------------------ -Purpose: Callback function from binding layer called after the completion of - post processing. This function is called only when there is error. +Purpose: this function is used to report error in the modules. Input : error code Output : decoded module error code Notes : -Error Handling supported by Binding layer module: - Acquisition Module Error codes: 0x8 - 0x81 - Qtm init - 0x82 - start acq - 0x83 - cal sensors - 0x84 - cal hardware - - Post processing Modules error codes: 0x4 - 0x40, 0x41, 0x42, ... - process_id is the sequence of process IDs listed in #define LIB_MODULES_PROC_LIST macro. - Process IDs start from zero and maximum is 15 - - Examples: - 0x40 -> error in post processing module 1 - 0x42 -> error in post processing module 3 - Derived Module_error_codes: - Acquisition module error =1 - post processing module1 error = 2 - post processing module2 error = 3 - ... and so on + Acquisition module error =1 + post processing module1 error = 2 + post processing module2 error = 3 + ... and so on ============================================================================*/ -static void qtm_error_callback(uint8_t err) +static void qtm_error_callback(uint8_t error) +{ + module_error_code = error + 1u; + +#if DEF_TOUCH_DATA_STREAMER_ENABLE == 1 + datastreamer_output(); +#endif +} + +static void scroller_init(void) { - module_error_code = 0; - if (err & 0x80) { - module_error_code = 1; - } else if (err & 0x40) { - module_error_code = (err & 0x0F) + 2; + for (int i = 0; i < DEF_NUM_SCROLLERS; i++) { + scroller_config_t* config = scroller_control[i].config; + scroller_data_t* data = scroller_control[i].data; + data->deltas = &scroller_deltas[config->start_key]; + data->hyst_left = config->hysteresis / 2; + data->hyst_right = config->hysteresis / 2; + data->position = 0; + data->raw_position = 0; + data->touch_area = 0; } } /*============================================================================ -void qtouch_init(void) +void touch_init(void) ------------------------------------------------------------------------------ -Purpose: Initialization of touch library. PTC, timer, binding layer and +Purpose: Initialization of touch library. PTC, timer, and datastreamer modules are initialized in this function. Input : none Output : none @@ -432,16 +279,19 @@ void qtouch_init(void) { qtouch_timer_config(); - build_qtm_config(&qtm_control); + /* Configure touch sensors with Application specific settings */ + touch_sensors_config(); - qtm_binding_layer_init(&qtm_control); + /* Configure scrollers */ + scroller_init(); - /* get a pointer to the binding layer control */ - p_qtm_control = qmt_get_binding_layer_ptr(); +#if DEF_TOUCH_DATA_STREAMER_ENABLE == 1 + datastreamer_init(); +#endif } /*============================================================================ -void qtouch_process(void) +void touch_process(void) ------------------------------------------------------------------------------ Purpose: Main processing function of touch library. This function initiates the acquisition, calls post processing after the acquistion complete and @@ -454,44 +304,53 @@ void qtouch_process(void) { touch_ret_t touch_ret; - /* check the time_to_measure_touch flag for Touch Acquisition */ - if (p_qtm_control->binding_layer_flags & (1U << time_to_measure_touch)) { + /* check the time_to_measure_touch_flag flag for Touch Acquisition */ + if (time_to_measure_touch_flag == 1u) { /* Do the acquisition */ - touch_ret = qtm_lib_start_acquisition(0); + touch_ret = qtm_ptc_start_measurement_seq(&qtlib_acq_set1, qtm_measure_complete_callback); /* if the Acquistion request was successful then clear the request flag */ if (TOUCH_SUCCESS == touch_ret) { /* Clear the Measure request flag */ - p_qtm_control->binding_layer_flags &= (uint8_t) ~(1U << time_to_measure_touch); + time_to_measure_touch_flag = 0u; } } /* check the flag for node level post processing */ - if (p_qtm_control->binding_layer_flags & (1U << node_pp_request)) { - /* Run Acquisition moudle level post pocessing*/ - touch_ret = qtm_lib_acq_process(); + if (touch_postprocess_request == 1u) { + /* Reset the flags for node_level_post_processing */ + touch_postprocess_request = 0u; + + /* Run Acquisition module level post processing*/ + touch_ret = qtm_acquisition_process(); /* Check the return value */ if (TOUCH_SUCCESS == touch_ret) { /* Returned with success: Start module level post processing */ - qtm_lib_post_process(); + touch_ret = qtm_key_sensors_process(&qtlib_key_set1); + if (TOUCH_SUCCESS != touch_ret) { + qtm_error_callback(1); + } + qtouch_process_scroller_positions(scroller_control); } else { /* Acq module Eror Detected: Issue an Acq module common error code 0x80 */ - qtm_error_callback(0x80); + qtm_error_callback(0); } - /* Reset the flags for node_level_post_processing */ - p_qtm_control->binding_layer_flags &= (uint8_t) ~(1U << node_pp_request); - - if (p_qtm_control->binding_layer_flags & (1U << reburst_request)) { - p_qtm_control->binding_layer_flags |= (1U << time_to_measure_touch); - p_qtm_control->binding_layer_flags &= ~(1U << reburst_request); + if ((0u != (qtlib_key_set1.qtm_touch_key_group_data->qtm_keys_status & 0x80u))) { + time_to_measure_touch_flag = 1u; + } else { + measurement_done_touch = 1u; } + +#if DEF_TOUCH_DATA_STREAMER_ENABLE == 1 + datastreamer_output(); +#endif } } /*============================================================================ -void qtouch_timer_handler(void) +void touch_timer_handler(void) ------------------------------------------------------------------------------ Purpose: This function updates the time elapsed to the touch key module to synchronize the internal time counts used by the module. @@ -502,11 +361,11 @@ Notes : void qtouch_timer_handler(void) { /* Count complete - Measure touch sensors */ - qtm_control.binding_layer_flags |= (1U << time_to_measure_touch); + time_to_measure_touch_flag = 1u; qtm_update_qtlib_timer(DEF_TOUCH_MEASUREMENT_PERIOD_MS); } -static void qtouch_timer_task_cb(const struct timer_task* const timer_task) +static void Timer_task_cb(const struct timer_task* const timer_task) { (void)timer_task; qtouch_timer_handler(); @@ -515,11 +374,22 @@ static void qtouch_timer_task_cb(const struct timer_task* const timer_task) void qtouch_timer_config(void) { static struct timer_task Timer_task; + static uint8_t timer_task_added = 0; + + if (timer_task_added) { + timer_remove_task(&TIMER_0, &Timer_task); + } +#if (KRONO_GESTURE_ENABLE == 1u) + Timer_task.interval = 1; +#else Timer_task.interval = DEF_TOUCH_MEASUREMENT_PERIOD_MS; - Timer_task.cb = qtouch_timer_task_cb; +#endif + Timer_task.cb = Timer_task_cb; Timer_task.mode = TIMER_TASK_REPEAT; timer_add_task(&TIMER_0, &Timer_task); + timer_task_added = 1; + timer_start(&TIMER_0); } uint16_t qtouch_get_sensor_node_signal(uint16_t sensor_node) @@ -527,171 +397,193 @@ uint16_t qtouch_get_sensor_node_signal(uint16_t sensor_node) return (ptc_qtlib_node_stat1[sensor_node].node_acq_signals); } +void qtouch_update_sensor_node_signal(uint16_t sensor_node, uint16_t new_signal) +{ + ptc_qtlib_node_stat1[sensor_node].node_acq_signals = new_signal; +} + uint16_t qtouch_get_sensor_node_reference(uint16_t sensor_node) { return (qtlib_key_data_set1[sensor_node].channel_reference); } +void qtouch_update_sensor_node_reference(uint16_t sensor_node, uint16_t new_reference) +{ + qtlib_key_data_set1[sensor_node].channel_reference = new_reference; +} + uint16_t qtouch_get_sensor_cc_val(uint16_t sensor_node) { return (ptc_qtlib_node_stat1[sensor_node].node_comp_caps); } +void qtouch_update_sensor_cc_val(uint16_t sensor_node, uint16_t new_cc_value) +{ + ptc_qtlib_node_stat1[sensor_node].node_comp_caps = new_cc_value; +} + uint8_t qtouch_get_sensor_state(uint16_t sensor_node) { return (qtlib_key_set1.qtm_touch_key_data[sensor_node].sensor_state); } -/* Holds preceding unfiltered scroller positions */ -static uint16_t sensor_previous_filtered_reading[DEF_NUM_SENSORS][DEF_SENSOR_NUM_PREV_POS] = {0}; - -/* Custom sensor signal filter. */ -uint16_t qtouch_get_sensor_node_signal_filtered(uint16_t sensor_node) +void qtouch_update_sensor_state(uint16_t sensor_node, uint8_t new_state) { - // Filter the sensor signal. - // - // Smooth it out and saturate it so that values never go beyond DEF_SENSOR_CEILING. - // This helps to mitigate 'jumpy' channels that exist at higher sensor readings when - // in noisy environments. - // - uint16_t X; - uint16_t sensor_raw = qtouch_get_sensor_node_signal(sensor_node); - uint16_t sensor_reference = qtouch_get_sensor_node_reference(sensor_node); - - if (sensor_reference == 0) { - // If a sensor reference is 0, it means that the sensor is not yet calibrated (or dead). - // The signal can be high anyway, which makes it look like the sensor is being touched when - // it isn't. - return 0; - } - X = sensor_raw < sensor_reference ? 0 : sensor_raw - sensor_reference; - // Add more weight to edge buttons because they are physically smaller (smaller readings). - if ((sensor_node == DEF_SCROLLER_OFFSET_0) || (sensor_node == DEF_SCROLLER_OFFSET_1) || - (sensor_node == DEF_SCROLLER_OFFSET_0 + DEF_SCROLLER_NUM_CHANNELS - 1) || - (sensor_node == DEF_SCROLLER_OFFSET_1 + DEF_SCROLLER_NUM_CHANNELS - 1)) { - X = (uint16_t)((double)X * (1 + DEF_SENSOR_EDGE_WEIGHT)); - } - // Saturate out-of-range readings. - X = (X > DEF_SENSOR_CEILING) ? DEF_SENSOR_CEILING : X; - - // Calculate sensor readout using a moving average - // The moving average wieghts previous N readings twice current reading - uint16_t moving_average_cummulative_weight = 1; // Add one for current reading calculated above - uint16_t X_ave = X; - for (size_t j = 0; j < DEF_SENSOR_NUM_PREV_POS; j++) { - moving_average_cummulative_weight += 2; - X_ave += sensor_previous_filtered_reading[sensor_node][j] * 2; - } - X_ave = X_ave / moving_average_cummulative_weight; - - // Update recorded previous positions - for (size_t j = 0; j < DEF_SENSOR_NUM_PREV_POS - 1; j++) { - sensor_previous_filtered_reading[sensor_node][j] = - sensor_previous_filtered_reading[sensor_node][j + 1]; - } - sensor_previous_filtered_reading[sensor_node][DEF_SENSOR_NUM_PREV_POS - 1] = X; - - return X_ave; + qtlib_key_set1.qtm_touch_key_data[sensor_node].sensor_state = new_state; } bool qtouch_is_scroller_active(uint16_t scroller) { - return scroller_active[scroller]; + return scroller_control[scroller].data->active; } - -uint16_t qtouch_get_scroller_position(uint16_t sensor_node) +uint16_t qtouch_get_scroller_position(uint16_t scroller) { - return scroller_position[sensor_node]; + return scroller_control[scroller].data->position; } -void qtouch_process_scroller_positions(void) +void qtouch_process_scroller_positions(scroller_control_t* scrollers) { - for (uint8_t scroller = 0; scroller < DEF_NUM_SCROLLERS; scroller++) { - uint8_t i, j; - uint16_t sum = 0; - uint16_t max_sensor_reading = 0; - uint16_t min_sensor_reading = DEF_SENSOR_CEILING; - uint16_t weighted_sum = 0; - uint16_t filtered_readings[DEF_SCROLLER_NUM_CHANNELS] = {0}; - uint16_t sensor_location[DEF_SCROLLER_NUM_CHANNELS] = { - 1, // Offset by `1` because a `0` location cannot be weight-averaged - DEF_SCROLLER_RESOLUTION / 3, - DEF_SCROLLER_RESOLUTION / 3 * 2, - DEF_SCROLLER_RESOLUTION}; - - for (i = 0; i < DEF_SCROLLER_NUM_CHANNELS; i++) { - filtered_readings[i] = qtouch_get_sensor_node_signal_filtered( - i + (scroller ? DEF_SCROLLER_OFFSET_1 : DEF_SCROLLER_OFFSET_0)); - min_sensor_reading = (filtered_readings[i] < min_sensor_reading) ? filtered_readings[i] - : min_sensor_reading; - max_sensor_reading = (filtered_readings[i] > max_sensor_reading) ? filtered_readings[i] - : max_sensor_reading; + scroller_control_t* scroller; + scroller_control_t* scrollers_end = scrollers + DEF_NUM_SCROLLERS; + for (scroller = scrollers; scroller < scrollers_end; scroller++) { + scroller_config_t* config = scroller->config; + scroller_data_t* data = scroller->data; + int node_max = -1; + int16_t node_max_value = INT16_MIN; + data->touch_area = 0; + bool key_active = 0; + bool scroller_active = data->active; + + for (int i = 0; i < config->number_of_keys; i++) { + uint8_t node = config->start_key + i; + int16_t delta = max( + 0, qtouch_get_sensor_node_signal(node) - qtouch_get_sensor_node_reference(node)); + // delta = max(0, delta - qtlib_key_configs_set1[node].channel_threshold); + // multiply inner sensors with 1.50 (The ones at the edges have higher PTC gain) + if (i > 0 && i < config->number_of_keys - 1) { + // data->deltas[i] += + // (data->deltas[i] >> 1) + (data->deltas[i] >> 2) + (data->deltas[i] >> 3); + // data->deltas[i] += (data->deltas[i] >> 1) + (data->deltas[i] >> 3); + data->deltas[i] += data->deltas[i] >> 1; + } + + // Apply weighted moving average if it was active + data->deltas[i] = (2 * delta + data->deltas[i]) / 3; + // If any key is in touch, the scroller is considered in touch + if (qtouch_get_sensor_state(node) == QTM_KEY_STATE_DETECT) { + key_active = 1; + } + // Find the node with the highest signal to determine how to calculate touch area. + if (data->deltas[i] > node_max_value) { + node_max = i; + node_max_value = data->deltas[i]; + } } - // Read filterd data and weight by sensor physical location - // Reduce the value by the min_sensor_reading to improve positional accuracy. - // Touch position is calculated with a weighted average of the sensor readings. - // If properly calibrated, sensors on the opposite end of a finger touch would - // be zero and thus make no contribution to the weighted average. If the baseline - // sensor readings are elevated, the sensors on the opposite edge DO contribute - // to the weighted average making a positional artifact (i.e. the position is more - // central than it should be in reality). This artifact is higher when the finger - // is a bit distant while approaching and lower/negligible when the finger is - // fully touching the device. This can cause the position to move enough to enter - // "slide" mode and disable "tap" events being emitted. - for (i = 0; i < DEF_SCROLLER_NUM_CHANNELS; i++) { - sum += filtered_readings[i] - min_sensor_reading; - weighted_sum += (filtered_readings[i] - min_sensor_reading) * sensor_location[i]; + switch (node_max) { + case 0: + data->touch_area = data->deltas[0] + (data->deltas[1] >> 1); + break; + case 1: + data->touch_area = (data->deltas[0] >> 1) + data->deltas[1] + (data->deltas[2] >> 1); + break; + case 2: + data->touch_area = (data->deltas[1] >> 1) + data->deltas[2] + (data->deltas[3] >> 1); + break; + case 3: + data->touch_area = (data->deltas[2] >> 1) + data->deltas[3]; + break; + default: + break; } - // Compensate for deadband (i.e. when only a single edge button gives a reading and - // neighbors do not) - uint16_t scaled_value = weighted_sum / sum; - scaled_value = - (scaled_value < DEF_SCROLLER_DEADBAND) ? DEF_SCROLLER_DEADBAND : (weighted_sum / sum); - scaled_value = (scaled_value > (DEF_SCROLLER_RESOLUTION - DEF_SCROLLER_DEADBAND)) - ? (DEF_SCROLLER_RESOLUTION - DEF_SCROLLER_DEADBAND) - : scaled_value; - scaled_value = ((scaled_value - DEF_SCROLLER_DEADBAND) * (DEF_SCROLLER_RESOLUTION - 1)) / - (DEF_SCROLLER_RESOLUTION - 2 * DEF_SCROLLER_DEADBAND); - - // Calculate scroller position using a moving average - // The moving average wieghts previous N readings twice current reading - if (sum >= DEF_SCROLLER_DET_THRESHOLD) { - uint16_t moving_average_cummulative_weight = 0; - scroller_position[scroller] = 0; - for (j = 0; j < DEF_SCROLLER_NUM_PREV_POS; j++) { - if (scroller_previous_position[scroller][j] != DEF_SCROLLER_OFF) { - moving_average_cummulative_weight += 2; - scroller_position[scroller] += scroller_previous_position[scroller][j] * 2; - } + // In case no single node is in touch, but multiple nodes together are, treat that as in + // touch + if (data->touch_area > config->touch_threshold) { + data->touch_count_in = min(255, data->touch_count_in + 1); + if (data->touch_count_in > config->touch_count_in) { + scroller_active = 1; } - scroller_position[scroller] += - scaled_value; // Most recent signal is half weight of others to help avoid bounce - // when finger is released - scroller_position[scroller] = - scroller_position[scroller] / (moving_average_cummulative_weight + 1); + } + if (data->touch_area < config->untouch_threshold) { + scroller_active = 0; + data->touch_count_in = 0; } - // Update recorded previous positions and scroller active state - for (j = 0; j < DEF_SCROLLER_NUM_PREV_POS - 1; j++) { - scroller_previous_position[scroller][j] = scroller_previous_position[scroller][j + 1]; + bool active = key_active | scroller_active; + + // offset all calculations to increase precision + uint32_t fp_offset = 2; + uint32_t raw_pos = 0; + uint32_t weight_sum = 0; + uint32_t sum = 0; + for (int i = 0; i < config->number_of_keys; ++i) { + int32_t delta = data->deltas[i]; + sum += delta; + int32_t weight = (i << (config->resolution + fp_offset)) / (config->number_of_keys - 1); + raw_pos += delta * weight; + weight_sum += weight; } - if (sum >= DEF_SCROLLER_DET_THRESHOLD) { - scroller_previous_position[scroller][DEF_SCROLLER_NUM_PREV_POS - 1] = scaled_value; + raw_pos /= sum; + raw_pos >>= fp_offset; + + raw_pos = (data->raw_position + 4 * raw_pos) / 5; + + if (active) { + int32_t pos = data->position; + + // use weighted moving average on raw position if it was active + if (data->active) { + int32_t raw_pos_delta = raw_pos - pos; + if (raw_pos_delta < -data->hyst_left || raw_pos_delta > data->hyst_right) { + pos = raw_pos; + + /* handle hysterisis, when finger changes direction */ + if (pos < data->position) { + data->hyst_left = 0; + data->hyst_right = config->hysteresis; + } + if (pos > data->position) { + data->hyst_left = config->hysteresis; + data->hyst_right = 0; + } + } + } else { + pos = raw_pos; + } + + /* Handle deadband (close to 0 and close to max resolution) */ + if (raw_pos < config->deadband) { + pos = 0; + data->hyst_left = 0; + data->hyst_right = config->hysteresis / 2; + } + if (raw_pos >= (uint32_t)((1 << config->resolution) - 1) - config->deadband) { + pos = (1 << config->resolution) - 1; + data->hyst_left = config->hysteresis / 2; + data->hyst_right = 0; + } + + data->position = pos; + data->raw_position = raw_pos; } else { - scroller_previous_position[scroller][DEF_SCROLLER_NUM_PREV_POS - 1] = DEF_SCROLLER_OFF; - } - // Use the maximum value of all sensor readings as an estimate of pressure. - // Put a threshold on this to detect whether we're touching or not. - if (max_sensor_reading >= DEF_SCROLLER_TOUCH_THRESHOLD) { - scroller_active[scroller] = true; - } else if (max_sensor_reading <= DEF_SCROLLER_UNTOUCH_THRESHOLD) { - scroller_active[scroller] = false; + // data->position = data->raw_position; + data->raw_position = raw_pos; + data->hyst_left = config->hysteresis / 2; + data->hyst_right = config->hysteresis / 2; } + data->active = active; } } +void qtouch_calibrate_node(uint16_t sensor_node) +{ + /* Calibrate Node */ + qtm_calibrate_sensor_node(&qtlib_acq_set1, sensor_node); + /* Initialize key */ + qtm_init_sensor_key(&qtlib_key_set1, sensor_node, &ptc_qtlib_node_stat1[sensor_node]); +} + /*============================================================================ ISR(ADC0_RESRDY_vect) ------------------------------------------------------------------------------ @@ -702,10 +594,8 @@ Notes : none ============================================================================*/ void ADC0_1_Handler(void) { - CRITICAL_SECTION_ENTER() - ADC0->INTFLAG.reg |= 1U; + ADC0->INTFLAG.reg |= 1u; qtm_samd51_ptc_handler(); - CRITICAL_SECTION_LEAVE() } #endif /* TOUCH_C */ diff --git a/src/qtouch/qtouch.h b/src/qtouch/qtouch.h index f119d06b00..26a9ecda72 100644 --- a/src/qtouch/qtouch.h +++ b/src/qtouch/qtouch.h @@ -30,6 +30,33 @@ extern "C" { #include "touch_api_ptc.h" +typedef struct { + uint16_t start_key; + uint8_t number_of_keys; + uint8_t resolution; + uint16_t touch_threshold; + uint16_t untouch_threshold; + uint8_t deadband; + uint8_t hysteresis; + uint8_t touch_count_in; +} scroller_config_t; + +typedef struct { + int16_t* deltas; + uint16_t touch_area; + uint16_t raw_position; + uint16_t position; + uint8_t active; + uint8_t hyst_left; + uint8_t hyst_right; + uint8_t touch_count_in; +} scroller_data_t; + +typedef struct { + scroller_config_t* config; + scroller_data_t* data; +} scroller_control_t; + /**********************************************************/ /******************* Acquisition controls *****************/ /**********************************************************/ @@ -37,21 +64,22 @@ extern "C" { * Range: 1 to 255. * Default value: 20. */ -#define DEF_TOUCH_MEASUREMENT_PERIOD_MS 20 +#define DEF_TOUCH_MEASUREMENT_PERIOD_MS 10 /* Defines the Type of sensor * Default value: NODE_MUTUAL. */ #define DEF_SENSOR_TYPE NODE_SELFCAP -/* Set sensor calibration mode for charge share delay ,Prescaler or series resistor. - * Range: CAL_AUTO_TUNE_NONE / CAL_AUTO_TUNE_RSEL / CAL_AUTO_TUNE_PRSC / CAL_AUTO_TUNE_CSD - * Default value: CAL_AUTO_TUNE_NONE. +/* Set sensor calibration mode for charge share delay ,Prescaler or series + * resistor. Range: CAL_AUTO_TUNE_NONE / CAL_AUTO_TUNE_RSEL / CAL_AUTO_TUNE_PRSC + * / CAL_AUTO_TUNE_CSD Default value: CAL_AUTO_TUNE_NONE. */ #define DEF_PTC_CAL_OPTION CAL_AUTO_TUNE_NONE -/* Defines the interrupt priority for the PTC. Set low priority to PTC interrupt for applications - * having interrupt time constraints. Range: 0 to 2 Default: 2 (Lowest Priority) +/* Defines the interrupt priority for the PTC. Set low priority to PTC interrupt + * for applications having interrupt time constraints. Range: 0 to 2 Default: 2 + * (Lowest Priority) */ #define DEF_PTC_INTERRUPT_PRIORITY 2 @@ -65,7 +93,7 @@ extern "C" { * Range: FREQ_SEL_0 - FREQ_SEL_15 , FREQ_SEL_SPREAD * Default value: FREQ_SEL_0. */ -#define DEF_SEL_FREQ_INIT FREQ_SEL_8 +#define DEF_SEL_FREQ_INIT FREQ_SEL_0 /*---------------------------------------------------------------------------- * defines @@ -81,68 +109,26 @@ extern "C" { */ #define DEF_NUM_CHANNELS (8) -/* Defines node parameter setting - * {X-line, Y-line, Charge Share Delay, NODE_RSEL_PRSC(series resistor, prescaler), NODE_G(Analog - * Gain , Digital Gain), filter level} - */ -// Slider 1 buttons -#define NODE_0_PARAMS \ - {X_NONE, \ - Y_LINE(26), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -#define NODE_1_PARAMS \ - {X_NONE, \ - Y_LINE(27), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -#define NODE_2_PARAMS \ - {X_NONE, \ - Y_LINE(28), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -#define NODE_3_PARAMS \ - {X_NONE, \ - Y_LINE(29), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -// Slider 0 buttons -#define NODE_4_PARAMS \ - {X_NONE, \ - Y_LINE(30), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -#define NODE_5_PARAMS \ - {X_NONE, \ - Y_LINE(31), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -#define NODE_6_PARAMS \ - {X_NONE, \ - Y_LINE(20), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} -#define NODE_7_PARAMS \ - {X_NONE, \ - Y_LINE(21), \ - 0, \ - NODE_RSEL_PRSC(RSEL_VAL_20, PRSC_DIV_SEL_1), \ - NODE_GAIN(GAIN_4, GAIN_4), \ - FILTER_LEVEL_512} +/* Defines self-cap node parameter setting + * {X-line, Y-line, Charge Share Delay, Prescaler, NODE_G(Analog Gain , Digital + * Gain), filter level} + */ +#define NODE_0_PARAMS \ + {X_NONE, Y_LINE(26), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_2, GAIN_8), FILTER_LEVEL_64} +#define NODE_1_PARAMS \ + {X_NONE, Y_LINE(27), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_1, GAIN_8), FILTER_LEVEL_64} +#define NODE_2_PARAMS \ + {X_NONE, Y_LINE(28), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_1, GAIN_8), FILTER_LEVEL_64} +#define NODE_3_PARAMS \ + {X_NONE, Y_LINE(29), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_2, GAIN_8), FILTER_LEVEL_64} +#define NODE_4_PARAMS \ + {X_NONE, Y_LINE(30), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_1, GAIN_8), FILTER_LEVEL_64} +#define NODE_5_PARAMS \ + {X_NONE, Y_LINE(31), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_1, GAIN_8), FILTER_LEVEL_64} +#define NODE_6_PARAMS \ + {X_NONE, Y_LINE(20), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_1, GAIN_8), FILTER_LEVEL_64} +#define NODE_7_PARAMS \ + {X_NONE, Y_LINE(21), 0, PRSC_DIV_SEL_4, NODE_GAIN(GAIN_2, GAIN_8), FILTER_LEVEL_64} /**********************************************************/ /***************** Key Params ******************/ @@ -151,39 +137,37 @@ extern "C" { * Range: 1 to 65535. * Default value: 1 */ -#define DEF_NUM_SENSORS (DEF_NUM_CHANNELS) +#define DEF_NUM_SENSORS (8) /* Defines Key Sensor setting * {Sensor Threshold, Sensor Hysterisis, Sensor AKS} */ -// 0..3 higher Slider left to right 4..7 lower Slider right to left -#define KEY_0_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_1_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_2_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_3_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_4_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_5_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_6_PARAMS {16, HYST_50, NO_AKS_GROUP} -#define KEY_7_PARAMS {16, HYST_50, NO_AKS_GROUP} +#define KEY_0_PARAMS {15, HYST_25, AKS_GROUP_1} +#define KEY_1_PARAMS {15, HYST_25, AKS_GROUP_1} +#define KEY_2_PARAMS {15, HYST_25, AKS_GROUP_1} +#define KEY_3_PARAMS {21, HYST_25, AKS_GROUP_1} +#define KEY_4_PARAMS {12, HYST_25, AKS_GROUP_2} +#define KEY_5_PARAMS {15, HYST_25, AKS_GROUP_2} +#define KEY_6_PARAMS {16, HYST_25, AKS_GROUP_2} +#define KEY_7_PARAMS {21, HYST_25, AKS_GROUP_2} /* De-bounce counter for additional measurements to confirm touch detection * Range: 0 to 255. * Default value: 4. */ -#define DEF_TOUCH_DET_INT 0 +#define DEF_TOUCH_DET_INT 1 -/* De-bounce counter for additional measurements to confirm away from touch signal - * to initiate Away from touch re-calibration. - * Range: 0 to 255. - * Default value: 5. +/* De-bounce counter for additional measurements to confirm away from touch + * signal to initiate Away from touch re-calibration. Range: 0 to 255. Default + * value: 5. */ -#define DEF_ANTI_TCH_DET_INT 0 +#define DEF_ANTI_TCH_DET_INT 1 /* Threshold beyond with automatic sensor recalibration is initiated. * Range: RECAL_100/ RECAL_50 / RECAL_25 / RECAL_12_5 / RECAL_6_25 / MAX_RECAL * Default value: RECAL_100. */ -#define DEF_ANTI_TCH_RECAL_THRSHLD RECAL_50 +#define DEF_ANTI_TCH_RECAL_THRSHLD RECAL_100 /* Rate at which sensor reference value is adjusted towards sensor signal value * when signal value is greater than reference. @@ -191,7 +175,7 @@ extern "C" { * Range: 0-255 * Default value: 20u = 4 seconds. */ -#define DEF_TCH_DRIFT_RATE 20 +#define DEF_TCH_DRIFT_RATE 1 /* Rate at which sensor reference value is adjusted towards sensor signal value * when signal value is less than reference. @@ -199,14 +183,14 @@ extern "C" { * Range: 0-255 * Default value: 5u = 1 second. */ -#define DEF_ANTI_TCH_DRIFT_RATE 5 +#define DEF_ANTI_TCH_DRIFT_RATE 1 /* Time to restrict drift on all sensor when one or more sensors are activated. * Units: 200ms * Range: 0-255 * Default value: 20u = 4 seconds. */ -#define DEF_DRIFT_HOLD_TIME 20 +#define DEF_DRIFT_HOLD_TIME 1 /* Set mode for additional sensor measurements based on touch activity. * Range: REBURST_NONE / REBURST_UNRESOLVED / REBURST_ALL @@ -220,13 +204,6 @@ extern "C" { */ #define DEF_MAX_ON_DURATION 0 -/* - * The count that the reference value must be above the measured value to - * allow the force calibrate procedure to overwrite the reference to the - * current measured value. - */ -#define KEY_FORCE_CALIBRATE_THRESHOLD 10 - /**********************************************************/ /***************** Slider/Wheel Parameters ****************/ /**********************************************************/ @@ -237,26 +214,26 @@ extern "C" { * This allows low noise button readings while keeping * fast responsiveness. */ + #define DEF_NUM_SCROLLERS 2 // Number of scrollers (sliders or wheels) #define DEF_SCROLLER_NUM_CHANNELS 4 // Number of channels per scroller #define DEF_SCROLLER_OFFSET_0 4 // Index of first button in scroller #define DEF_SCROLLER_OFFSET_1 0 // Index of first button in scroller -#define DEF_SCROLLER_RESOLUTION 256 // Scroller resolution in bits -#define DEF_SCROLLER_DET_THRESHOLD 25 // Scroller detect threshold -#define DEF_SCROLLER_TOUCH_THRESHOLD 25 // Scroller active threshold -#define DEF_SCROLLER_UNTOUCH_THRESHOLD 20 // Scroller active threshold -#define DEF_SCROLLER_DEADBAND 13 // 13 bits = 5% of 256-bit range -#define DEF_SCROLLER_NUM_PREV_POS \ - 4 // Number of previous scroller positions to remember; used in a simple filter -#define DEF_SCROLLER_OFF \ - 0xFFFF // Marker for indicating scroller reading does not exceed detection threshold -#define DEF_SENSOR_EDGE_WEIGHT \ - 0.15 // Percent added weight to edge sensors, which are physically smaller -#define DEF_SENSOR_NUM_PREV_POS \ - 4 // Number of previous sensor positions to remember; used in a simple filter -#define DEF_SENSOR_CEILING \ - 50 // Maximum sensor reading. Mitigates 'jumpy' channels that exist at higher - // sensor readings when in noisy environments. +#define DEF_SCROLLER_RESOLUTION 8 // Scroller resolution in bits +#define DEF_SCROLLER_TOUCH_THRESHOLD 32 // Scroller active threshold +#define DEF_SCROLLER_UNTOUCH_THRESHOLD 16 // Scroller active threshold +#define DEF_SCROLLER_DEADBAND \ + 5 // everything below deadband is locked to 0 and above max-deadband is locked to max +#define DEF_SCROLLER_HYSTERESIS 20 // Position needs to move at least this much +#define DEF_SCROLLER_TOUCH_DRIFT_IN 2 // number of counts in touch before being active + +/**********************************************************/ +/***************** Communication - Data Streamer ******************/ +/**********************************************************/ + +#define DEF_TOUCH_DATA_STREAMER_ENABLE 0u +#define DATA_STREAMER_BOARD_TYPE USER_BOARD +#define KRONO_GESTURE_ENABLE 0 #ifdef __cplusplus } diff --git a/src/touch/gestures.h b/src/touch/gestures.h index 47198104bc..93fdbbe758 100644 --- a/src/touch/gestures.h +++ b/src/touch/gestures.h @@ -24,7 +24,7 @@ #include "qtouch.h" #define TOUCH_NUM_BUTTONS DEF_NUM_CHANNELS #define TOUCH_NUM_SLIDERS DEF_NUM_SCROLLERS -#define MAX_SLIDER_POS (DEF_SCROLLER_RESOLUTION - 1) +#define MAX_SLIDER_POS ((1 << DEF_SCROLLER_RESOLUTION) - 1) #else #define TOUCH_NUM_BUTTONS (8) #define TOUCH_NUM_SLIDERS (2) diff --git a/src/ui/components/orientation_arrows.c b/src/ui/components/orientation_arrows.c index 5689f32f4d..d6843c563b 100644 --- a/src/ui/components/orientation_arrows.c +++ b/src/ui/components/orientation_arrows.c @@ -130,7 +130,6 @@ static void _render(component_t* component) } data->enable_touch = true; } - qtouch_force_calibrate(); data->screen_count++; }