diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..605397f --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +CYPRESS END USER LICENSE AGREEMENT + +PLEASE READ THIS END USER LICENSE AGREEMENT ("Agreement") CAREFULLY BEFORE DOWNLOADING, INSTALLING, OR USING THIS SOFTWARE AND ACCOMPANYING DOCUMENTATION ("Software"). BY DOWNLOADING, INSTALLING, OR USING THE SOFTWARE, YOU ARE AGREEING TO BE BOUND BY THIS AGREEMENT. IF YOU DO NOT AGREE TO ALL OF THE TERMS OF THIS AGREEMENT, PROMPTLY RETURN AND DO NOT USE THE SOFTWARE. IF YOU HAVE PURCHASED THE SOFTWARE, YOUR RIGHT TO RETURN THE SOFTWARE EXPIRES 30 DAYS AFTER YOUR PURCHASE AND APPLIES ONLY TO THE ORIGINAL PURCHASER. + +License. Subject to the terms and conditions of this Agreement, Cypress Semiconductor Corporation ("Cypress") and its suppliers grant to you a non-exclusive, non-transferable license under its copyright rights to use the Software in object code form solely for the purpose of creating programming code for use on Cypress hardware products and transfering such programming code onto such hardware products ("Purpose"). For purposes of this Agreement, "Software" shall also include any upgrades, updates, bug fixes or modified versions provided to you by Cypress. You may make one backup copy of the Software. + +Free and Open Source Software. Portions of the Software may be licensed under free and/or open source licenses such as the GNU General Public License ("FOSS"). FOSS is subject to the applicable license agreement and not this Agreement. If you are entitled to receive the source code from Cypress for any FOSS included with the Software, either the source code will be included with the Software or you may obtain the source code at no charge from . The applicable license terms will accompany each source code package. To review the license terms applicable to any FOSS for which Cypress is not required to provide you with source code, please see the Software's installation directory on your computer. + +Source Code. The Software may include source code of Cypress or its suppliers that is used to create applications that execute on Cypress hardware products or on other platforms in order to program Cypress hardware products ("Cypress Source Code"). Applications that you create using the Software that execute on Cypress hardware products are referred to as "Firmware." Applications that you create using the Software that execute on other platforms in order to program, control, or communicate with Cypress hardware products are referred to "Host Applications." The Cypress Source Code, Host Applications, and Firmware are subject to the license granted in this paragraph and not the license granted in the paragraph entitled "License." Subject to the terms and conditions of this Agreement, Cypress grants you a non-exclusive, non-transferable license under its copyright rights to (i) copy, use, modify, and compile the Cypress Source Code, Host Applications, and Firmware solely for the Purpose, and (ii) distribute Firmware in binary code form only, only when installed onto a Cypress hardware product, and (iii) distribute Host Applications, in binary code form only, only when installed on a device that includes a Cypress hardware product that the Host Application is intended to program, control, or communicate with, and (iv) to freely distribute any hardware setup information file (.inf file) created by the Software to allow a Microsoft Windows operating system to install the driver for a Cypress hardware product. Cypress retains ownership of the Cypress Source Code and any compiled version thereof. Subject to Cypress' ownership of the underlying Cypress Source Code and Software, you retain ownership of any modifications you make to the Cypress Source Code. You agree not to remove any Cypress copyright or other notices from the Cypress Source Code and any modifications thereof. You agree to keep the Cypress Source Code confidential. Any reproduction, modification, translation, compilation, or representation of the Cypress Source Code except as permitted in this paragraph is prohibited without the express written permission of Cypress. + +Driver Files. The Software may include driver files in binary code form, to allow the use of a Cypress hardware product with a particular host operating system ("Driver"). Unless different license terms accompany a Driver, subject to the terms and conditions of this Agreement, Cypress grants you a non-exclusive, non-transferable license under its copyright rights to distribute the Driver, in binary code form only, only when installed on a device that includes the Cypress hardware product that the Driver is intended to enable. + +Proprietary Rights. The Software, including all intellectual property rights therein, is and will remain the sole and exclusive property of Cypress or its suppliers. Except as otherwise expressly provided in this Agreement, you may not: (i) modify, adapt, or create derivative works based upon the Software; (ii) copy the Software; (iii) except and only to the extent explicitly permitted by applicable law despite this limitation, decompile, translate, reverse engineer, disassemble or otherwise reduce the Software to human-readable form; or (iv) use the Software or any sample code other than for the Purpose. + +No Support. Cypress may, but is not required to, provide technical support for the Software. + +Term and Termination. This Agreement is effective until terminated, and either party may terminate this Agreement at any time with or without cause. Your license rights under this Agreement will terminate immediately without notice from Cypress if you fail to comply with any provision of this Agreement. Upon termination, you must destroy all copies of Software in your possession or control. The following paragraphs shall survive any termination of this Agreement: "Free and Open Source Software," "Proprietary Rights," "Compliance With Law," "Disclaimer," "Limitation of Liability," and "General." + +Compliance With Law. Each party agrees to comply with all applicable laws, rules and regulations in connection with its activities under this Agreement. Without limiting the foregoing, the Software may be subject to export control laws and regulations of the United States and other countries. You agree to comply strictly with all such laws and regulations and acknowledge that you have the responsibility to obtain licenses to export, re-export, or import the Software. + +Disclaimer. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, CYPRESS MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THE SOFTWARE, INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress reserves the right to make changes to the Software without notice. Cypress does not assume any liability arising out of the application or use of Software or any product or circuit described in the Software. Cypress does not authorize its products for use as critical components in life-support systems where a malfunction or failure may reasonably be expected to result in significant injury to the user. The inclusion of Cypress' product in a life-support system or application implies that the manufacturer of such system or application assumes all risk of such use and in doing so indemnifies Cypress against all charges. + +Limitation of Liability. IN NO EVENT WILL CYPRESS OR ITS SUPPLIERS, RESELLERS, OR DISTRIBUTORS BE LIABLE FOR ANY LOST REVENUE, PROFIT, OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL, OR PUNITIVE DAMAGES HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF CYPRESS OR ITS SUPPLIERS, RESELLERS, OR DISTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO EVENT SHALL CYPRESS' OR ITS SUPPLIERS', RESELLERS', OR DISTRIBUTORS' TOTAL LIABILITY TO YOU, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, EXCEED THE PRICE PAID BY YOU FOR THE SOFTWARE. THE FOREGOING LIMITATIONS SHALL APPLY EVEN IF THE ABOVE-STATED WARRANTY FAILS OF ITS ESSENTIAL PURPOSE. BECAUSE SOME STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU. + +Restricted Rights. The Software under this Agreement is commercial computer software as that term is described in 48 C.F.R. 252.227-7014(a)(1). If acquired by or on behalf of a civilian agency, the U.S. Government acquires this commercial computer software and/or commercial computer software documentation subject to the terms of this Agreement as specified in 48 C.F.R. 12.212 (Computer Software) and 12.211 (Technical Data) of the Federal Acquisition Regulations ("FAR") and its successors. If acquired by or on behalf of any agency within the Department of Defense ("DOD"), the U.S. Government acquires this commercial computer software and/or commercial computer software documentation subject to the terms of this Agreement as specified in 48 C.F.R. 227.7202-3 of the DOD FAR Supplement ("DFAR") and its successors. + +General. This Agreement will bind and inure to the benefit of each party's successors and assigns, provided that you may not assign or transfer this Agreement, in whole or in part, without Cypress' written consent. This Agreement shall be governed by and construed in accordance with the laws of the State of California, United States of America, as if performed wholly within the state and without giving effect to the principles of conflict of law. The parties consent to personal and exclusive jurisdiction of and venue in, the state and federal courts within Santa Clara County, California; provided however, that nothing in this Agreement will limit Cypress' right to bring legal action in any venue in order to protect or enforce its intellectual property rights. No failure of either party to exercise or enforce any of its rights under this Agreement will act as a waiver of such rights. If any portion hereof is found to be void or unenforceable, the remaining provisions of this Agreement shall remain in full force and effect. This Agreement is the complete and exclusive agreement between the parties with respect to the subject matter hereof, superseding and replacing any and all prior agreements, communications, and understandings (both written and oral) regarding such subject matter. Any notice to Cypress will be deemed effective when actually received and must be sent to Cypress Semiconductor Corporation, ATTN: General Counsel, 198 Champion Court, San Jose, CA 95134 USA. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6defe1b --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# PSoC 6 CapSense Middleware diff --git a/cy_capsense.h b/cy_capsense.h new file mode 100644 index 0000000..e45ad14 --- /dev/null +++ b/cy_capsense.h @@ -0,0 +1,484 @@ +/***************************************************************************//** +* \file cy_capsense.h +* \version 1.1 +* +* \brief +* This file includes all the header files of the CapSense middleware. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +/** +******************************************************************************** +* \mainpage Cypress CapSense Middleware Library +******************************************************************************** +* +* CapSense is a Cypress capacitive sensing solution. Capacitive sensing can be +* used in a variety of applications and products where conventional mechanical +* buttons can be replaced with sleek human interfaces to transform the way +* users interact with electronic systems. These include home appliances, and +* automotive, IoT, and industrial applications. CapSense supports multiple +* interfaces (widgets) using both CSX and CSD sensing methods with robust +* performance. +* +* CapSense has become a popular technology to replace conventional +* mechanical- and optical-based user interfaces. There are fewer parts +* involved, which saves cost and increases reliability with no wear-and-tear. +* The main advantages of CapSense compared with other solutions are: +* robust performance in harsh environmental conditions and rejection of a +* wide range of external noise sources. +* +* Use CapSense for: +* * Touch and gesture detection for various interfaces +* * Proximity detection for innovative user experiences and low-power +* optimization +* * Contactless liquid-level sensing in a variety of applications +* * Touch-free operations in hazardous materials +* +******************************************************************************** +* \section section_capsense_general General Description +******************************************************************************** +* +* The CSD HW block enables multiple sensing capabilities on PSoC devices +* including self-cap and mutual-cap capacitive touch sensing solution, +* a 10-bit ADC, IDAC, and Comparator. The CSD driver is a low-level +* peripheral driver, a wrapper to manage access to the CSD HW block. +* Each middleware access to the CSD HW block is through the CSD Driver. +* +* The CSD HW block can support only one function at a time. However, all +* supported functionality (like CapSense, ADC, etc.) can be +* time-multiplexed in a design. I.e. you can save the existing state +* of the CapSense middleware, restore the state of the ADC middleware, perform +* ADC measurements, and then switch back to the CapSense functionality. +* For more details and code examples refer to the description of the +* Cy_CapSense_Save() and Cy_CapSense_Restore() functions. +* +* \image html capsense_solution.png "CapSense Solution" width=800px +* \image latex capsense_solution.png +* +* This section describes only CapSense middleware. Refer to the corresponding +* sections for documentation of other middleware supported by the CSD HW block. +* +* A CapSense solution includes: +* * The CapSense Configurator tool, which is a configuration wizard to create +* and configure CapSense widgets. It could be launched in ModusToolbox +* from the CSD personality as well as in standalone mode. +* It contains a separate document about how to create and +* configure widgets, parameters and algorithm descriptions. +* * API to control the design from the application program. This documentation +* describes API with code snippets of how to use them. +* * The CapSense Tuner tool for real-time tuning, testing, and debugging, +* for easy and smooth designing of human interfaces on customer products. +* The Tuner tool communicates with a device through a HW bridge and +* communication drivers (EzI2C, UART, etc.) and allows to monitor +* widget statuses, sensor signals, detected touch positions, gestures, etc. +* The application program does not need to interact with the CSD driver +* and/or other drivers such as GPIO, SysClk directly. All of that is +* configured and managed by middleware. +* +* Include cy_capsense.h to get access to all functions and other declarations +* in this library. If you are using the ModusToolbox CapSense Configurator tool, +* you can include cycfg_capsense.h only. +* +* \subsection subsection_capsense_features Features +* +* * Offers best-in-class signal-to-noise ratio (SNR) +* * Supports Self-Capacitance (CSD) and Mutual-Capacitance (CSX) +* sensing methods +* * Features SmartSense auto-tuning technology for CSD sensing to avoid +* complex manual tuning process +* * Supports various Widgets, such as Buttons, Matrix Buttons, Sliders, +* Touchpads, and Proximity Sensors +* * Provides ultra-low power consumption and liquid-tolerant capacitive +* sensing technology +* * Contains the integrated graphical CapSense Tuner tool for real-time tuning, +* testing, and debugging +* * Provides superior immunity against external noise and low-radiated +* emission +* * Offers best-in-class liquid tolerance +* * Supports one-finger and two-finger gestures +* +******************************************************************************** +* \section section_capsense_configuration Summary of Application Programming Interface (API) +******************************************************************************** +* +* The CapSense operates on the top of the CapSense Sigma Delta (CSD) driver. +* Refer to the PDL API Reference Manual. +* +* This document provides descriptions of the functions in the CapSense +* middleware library, and descriptions of the data structures (register map) +* used by the middleware library. +* +* The Application Programming Interface (API) routines allow controlling and +* executing specific tasks using the CapSense middleware. The CapSense API +* is described in the following sections: +* * \ref group_capsense_high_level +* * \ref group_capsense_low_level +* * \ref group_capsense_data_structure +* * \ref group_capsense_enums +* * \ref group_capsense_macros +* * \ref group_capsense_callbacks +* +******************************************************************************** +* \section section_capsense_misra MISRA-C Compliance +******************************************************************************** +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
MISRA RuleRule Class (Required/Advisory)Rule DescriptionDescription of Deviation(s)
11.4AA conversion should not be performed between a pointer to object +* and an integer type.Such conversion is performed with CapSense context in two cases: +* interrupt handler and DeepSleepCallback function. +* Both cases are verified on correct operation.
12.13AThe increment (++) and decrement (--) operators should not be mixed +* with other operators in an expression.These violations are reported for the GCC ARM optimized form of +* the "for" loop that have the following syntax: +* for(index = COUNT; index --> 0u;) +* It is used to improve performance.
1.2 R Constant: Dereference of NULL pointer. These violations are reported as a result of using of offset macros +* of CSD Driver with corresponding documented violation 20.6. Refer +* to CSD Driver API Ref Guide.
20.3
+* +******************************************************************************** +* \section section_capsense_more_information More Information +******************************************************************************** +* +* Important information about the CapSense-technology overview, appropriate +* Cypress device for the design, CapSense system and sensor design guidelines, +* different interfaces and tuning guidelines necessary for a successful design +* of a CapSense system is available in the Getting Started with CapSense +* document and the product-specific CapSense design guide. Cypress highly +* recommends starting with these documents. They can be found on the +* Cypress web site at www.cypress.com. For details about application notes, +* code examples, and kits, see the References section in this datasheet. +* +* For more information, refer to the following documents: +* +* * Technical Reference Manual +* (TRM) +* +* * PSoC 63 with BLE Datasheet +* Programmable System-on-Chip datasheet +* +* * AN85951 PSoC 4 and PSoC 6 +* MCU CapSense Design Guide for more details +* +* * AN210781 Getting Started +* with PSoC 6 MCU with Bluetooth Low Energy (BLE) Connectivity +* +******************************************************************************** +* \section section_capsense_changelog Changelog +******************************************************************************** +* +* +* +* +* +* +* +* +* +* +* +* +* +*
VersionChangesReason for Change
1.1 +* * Marked several functions as obsolete: +* * Cy_CapSense_CSDSetupWidget() +* * Cy_CapSense_CSDSetupWidgetExt() +* * Cy_CapSense_CSDScan() +* * Cy_CapSense_CSDScanExt() +* * Cy_CapSense_CSDCalibrateWidget() +* * Cy_CapSense_CSXSetupWidget() +* * Cy_CapSense_CSXSetupWidgetExt() +* * Cy_CapSense_CSXScan() +* * Cy_CapSense_CSXScanExt() +* * Cy_CapSense_CSXCalibrateWidget() +* * Added two new functions: +* * Cy_CapSense_SetupWidgetExt() +* * Cy_CapSense_ScanExt() +* * Fixed the shield operation when Csh is disabled. +* * Fixed implementation of position filtering for Radial Slider widget. +* * Fixed Cy_CapSense_DeInit() implementation by restoring hardware to +* its default state. +* * Added the possibility to enable the shield with no dedicated electrodes. +* * Added support of protocol-agnostic tuning (UART, SPI, etc.). +* +* * Improved user's experience with an API. +* * Improved documentation. +* * Defect fixing. +* * Enhanced functionality. +*
1.0 +* * The initial version. +*
+* +* \defgroup group_capsense_high_level High-level Functions +* +* \defgroup group_capsense_low_level Low-level Functions +* +* \defgroup group_capsense_data_structure CapSense Data Structure +* +* \defgroup group_capsense_structures CapSense Structures +* \ingroup group_capsense_data_structure +* \brief The CapSense structures. +* +* \defgroup group_capsense_gesture_structures Gesture Structures +* \ingroup group_capsense_data_structure +* \brief The Gesture-related structures. +* +* \defgroup group_capsense_enums Enumerated Types +* +* \defgroup group_capsense_macros Macros +* +* \defgroup group_capsense_macros_general General Macros +* \ingroup group_capsense_macros +* \brief General macros +* \defgroup group_capsense_macros_settings Settings Macros +* \ingroup group_capsense_macros +* \brief Settings macros +* \defgroup group_capsense_macros_pin Pin-related Macros +* \ingroup group_capsense_macros +* \brief Pin-related macros +* \defgroup group_capsense_macros_process Processing Macros +* \ingroup group_capsense_macros +* \brief Processing macros +* \defgroup group_capsense_macros_touch Touch-related Macros +* \ingroup group_capsense_macros +* \brief Touch-related macros +* \defgroup group_capsense_macros_gesture Gesture Macros +* \ingroup group_capsense_macros +* \brief Gesture macros +* \defgroup group_capsense_macros_miscellaneous Miscellaneous Macros +* \ingroup group_capsense_macros +* \brief Miscellaneous macros +* +* \defgroup group_capsense_callbacks Callbacks +* +* \cond SECTION_CAPSENSE_INTERNAL +* \defgroup group_capsense_internal Internal Functions +* \endcond +* +**/ + +/******************************************************************************/ +/** \addtogroup group_capsense_high_level +* \{ +* +* High-level functions represent the highest abstraction layer of the +* CapSense middleware. +* +* These functions perform tasks such as scanning, data processing, data +* reporting and tuning interfaces. When performing a task, different +* initialization is required based on a sensing method or type of +* widgets is automatically handled by these functions. Therefore, these +* functions are sensing methods, features, and widget type agnostics. +* +* All the tasks required to implement a sensing system can be fulfilled +* by the high-level functions. But, there is a set of +* \ref group_capsense_low_level that provides access to lower level +* and specific tasks. If a design requires access to low-level tasks, +* these functions can be used. The functions related to a given sensing +* methods are not available if the corresponding method is disabled. +* +* \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level +* \{ +* +* The low-level functions represent the lower layer of abstraction in +* support of \ref group_capsense_high_level. +* +* These functions also enable implementation of special case designs +* requiring performance optimization and non-typical functionalities. +* +* The functions that contain CSD or CSX in the name are specified for +* that sensing method appropriately and should be used only with +* dedicated widgets having that mode. +* All other functions are general to all sensing methods. Some of the +* functions detect the sensing method used by the widget and execute +* tasks as appropriate. +* +* \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros +* \{ +* +* Specifies constants used in CapSense middleware. +* +* \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_enums +* \{ +* +* Documents CapSense related enumerated types. +* +* \} */ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal +* \{ +* +* The section documents CapSense related internal function. +* +* These function should not be used in the application program. +* +* \} \endcond */ + +/******************************************************************************/ +/** \addtogroup group_capsense_data_structure +* \{ +* +* The CapSense Data Structure organizes configuration parameters, input, and +* output data shared among different FW modules within the CapSense. +* +* The key responsibilities of the Data Structure are as follows: +* * The Data Structure is the only data container in the CapSense middleware. +* * It serves as storage for the configuration and the output data. +* * All CapSense modules use the data structure for the communication +* and data exchange. +* +* The CapSense Data Structure is a composite of several smaller structures +* (for global / common data, widget data, sensor data, and pin data). +* Furthermore, the data is split between RAM and Flash to achieve a +* reasonable balance between resources consumption and configuration / tuning +* flexibility at runtime and compile time. A graphical representation of +* the CapSense Data Structure is shown below. +* +* Note that figure below shows a sample representation and documents the +* high-level design of the data structure, it does not include all the +* parameters and elements in each object. +* +* \image html capsense_ds.png "CapSense Data Structure" width=800px +* \image latex capsense_ds.png +* +* CapSense Data Structure does not perform error checking on the data +* written to CapSense Data Structure. It is the responsibility of application +* program to ensure register map rule are not violated while +* modifying the value of data field in CapSense Data Structure. +* +* \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_callbacks +* \{ +* +* Callbacks allow the user to execute Custom code called from the CapSense +* middleware when an event occurs. CapSense supports two callbacks. +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
#Callback NameAssociated RegisterCallback Function PrototypeDescription
1Start SampleptrSSCallback\ref cy_capsense_callback_tThis is called before each sensor scan triggering. Such a callback +* can be used to implement user-specific use cases like changing scan +* parameters depending on whether a sensor is going to be scanned.
2End Of ScanptrEOSCallback\ref cy_capsense_callback_tThis is called after sensor scan completion and there is no other +* sensor in the queue to be scanned.
3Tuner Send CallbackptrTunerSendCallback\ref cy_capsense_tuner_send_callback_tThis is called by the Cy_CapSense_RunTuner() function to establish +* synchronus communication with the Tuner tool.
4Tuner Receive CallbackptrTunerReceiveCallback\ref cy_capsense_tuner_receive_callback_tThis is called by the Cy_CapSense_RunTuner() function to establish +* synchronus communication with the Tuner tool.
+* +* \note +* 1. Callbacks 1 and 2 are called by the Cy_CapSense_InterruptHandler() function and +* lengthen this function execution. Usually, Cy_CapSense_InterruptHandler() is called inside the +* CSD ISR. In such a case, the callbacks mentioned lengthen the execution of the CSD ISR as well. +* +* 2. Callbacks 2 and 3 can only be registered by direct CapSense Data Structure assignment. +* +* All callbacks can be registered by direct assignment of the function pointers to the corresponding +* CapSense Data Structure field as follows: +* context-\>ptrCommonContext-\>\ = \&CallbackFunction; +* +* Callbacks 2 and 3 can be registered / unregistered using the Cy_CapSense_RegisterCallback() and +* Cy_CapSense_UnRegisterCallback() function. +* +* \} */ + + +#if !defined(CY_CAPSENSE_H) +#define CY_CAPSENSE_H + +#include "cy_device_headers.h" +#include "cy_capsense_common.h" +#include "cy_capsense_centroid.h" +#include "cy_capsense_control.h" +#include "cy_capsense_csd.h" +#include "cy_capsense_csx.h" +#include "cy_capsense_filter.h" +#include "cy_capsense_lib.h" +#include "cy_capsense_gesture_lib.h" +#include "cy_capsense_processing.h" +#include "cy_capsense_sensing.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_tuner.h" + +#ifndef CY_IP_MXCSDV2 + #error "The CSD driver is not supported on this device" +#endif + +#endif /* CY_CAPSENSE_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_centroid.c b/cy_capsense_centroid.c new file mode 100644 index 0000000..b63a722 --- /dev/null +++ b/cy_capsense_centroid.c @@ -0,0 +1,2140 @@ +/***************************************************************************//** +* \file cy_capsense_centroid.c +* \version 1.1 +* +* \brief +* This file provides the source code for the centroid calculation methods +* of the CapSense middleware. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include +#include +#include +#include "cy_syslib.h" +#include "cy_capsense_centroid.h" +#include "cy_capsense_common.h" +#include "cy_capsense_lib.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_filter.h" + + +/******************************************************************************* +* Local definition +*******************************************************************************/ +#define CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_LENGTH (3u) +#define CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_PREVIOUS (0u) +#define CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_CENTER (1u) +#define CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_NEXT (2u) +/* Minimum valid age */ +#define CY_CAPSENSE_CSX_TOUCHPAD_AGE_START (0x0100u) +#define CY_CAPSENSE_CSX_TOUCHPAD_Z_SHIFT (0x04u) +#define CY_CAPSENSE_CSX_TOUCHPAD_BYTE_SHIFT (8u) +#define CY_CAPSENSE_CENTROID_ROUND_VALUE (0x7Fu) +#define CY_CAPSENSE_NO_LOCAL_MAX (0xFFFFu) + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ +static void Cy_CapSense_TransferTouch( + uint32_t newIndex, + uint32_t oldIndex, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +static void Cy_CapSense_NewTouch( + uint32_t newIndex, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +static uint32_t Cy_CapSense_CalcDistance( + uint32_t newIndex, + uint32_t oldIndex, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +static void Cy_CapSense_Hungarian( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +static void Cy_CapSense_CopyTouchRecord( + cy_stc_capsense_position_t * destination, + const cy_stc_capsense_position_t * source); +__STATIC_INLINE void Cy_CapSense_TouchDownDebounce( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +__STATIC_INLINE void Cy_CapSense_SortByAge( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +__STATIC_INLINE uint8_t Cy_CapSense_GetLowestId(uint8_t idMask); + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpCentroidDiplex +****************************************************************************//** +* +* Finds touch position of a Linear slider widget with enabled diplexing. +* +* In scope of position searching this function finds the local maximum with the +* highest raw count. If such maximums are more than one, then the maximum with the +* bigger sum of neighboring sensors is taken for further processing. Then the position +* is calculated using centroid algorithm with three sensors. +* +* At least two neighboring sensors should cross finger threshold. Then the algorithm +* is able to distinguish where real touch is located (direct part of slider or +* diplex part of slider) and corresponding position is reported. Otherwise no +* touch is reported. +* +* This function does not detect two or more touches. +* +* \param newTouch +* The pointer to the touch structure where found position is stored. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +*******************************************************************************/ +void Cy_CapSense_DpCentroidDiplex( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t sum; + uint32_t diffM; + uint32_t diffP; + uint32_t snsIndex; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + const uint8_t * ptrDpxTable; + uint32_t snsCount = ptrWdConfig->numSns; + + uint32_t maxSum = 0u; + uint32_t maxDiff = 0u; + uint32_t maxIndex = CY_CAPSENSE_NO_LOCAL_MAX; + uint32_t threshold = ptrWdConfig->ptrWdContext->fingerTh; + int32_t numerator = 0; + int32_t denominator = 0; + uint32_t multiplier; + uint32_t offset; + + threshold -= ptrWdConfig->ptrWdContext->hysteresis; + ptrDpxTable = ptrWdConfig->ptrDiplexTable; + + /* Find maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < snsCount; snsIndex++) + { + if (maxDiff < ptrSnsCxt->diff) + { + maxDiff = ptrSnsCxt->diff; + } + ptrSnsCxt++; + } + + /* Find sensor index with maximum sum ([i-1],[i],[i+1]) including diplex part */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < (snsCount << 1u); snsIndex++) + { + /* Potential maximum */ + if (maxDiff == ptrSnsCxt[ptrDpxTable[snsIndex]].diff) + { + /* Get sum of differences around maximum */ + diffM = (snsIndex > 0u) ? ptrSnsCxt[ptrDpxTable[snsIndex - 1u]].diff : 0u; + diffP = (snsIndex < ((snsCount << 1u) - 1u)) ? ptrSnsCxt[ptrDpxTable[snsIndex + 1u]].diff : 0u; + sum = ptrSnsCxt[ptrDpxTable[snsIndex]].diff + diffM + diffP; + if ((diffM < threshold) && (diffP < threshold)) + { + sum = 0u; + } + if (maxSum < sum) + { + /* New maximum */ + maxIndex = snsIndex; + maxSum = sum; + numerator = (int32_t)diffP - (int32_t)diffM; + } + } + } + + if (maxIndex != CY_CAPSENSE_NO_LOCAL_MAX) + { + multiplier = (uint32_t)ptrWdConfig->xResolution << 8u; + /* Calculate position */ + if (0u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CALC_METHOD_MASK)) + { + multiplier /= ((snsCount << 1u) - 1u); + offset = 0u; + } + else + { + multiplier /= (snsCount << 1u); + offset = multiplier >> 1u; + } + + denominator = (int32_t)maxSum; + denominator = ((numerator * (int32_t)multiplier) / denominator) + (((int32_t)maxIndex * (int32_t)multiplier) + (int32_t)offset); + + /* Round result and shift 8 bits left */ + newTouch->numPosition = CY_CAPSENSE_POSITION_ONE; + newTouch->ptrPosition[0u].x = CY_LO16(((uint32_t)denominator + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + } + else + { + newTouch->numPosition = CY_CAPSENSE_POSITION_NONE; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpCentroidLinear +****************************************************************************//** +* +* Finds touch position of a Linear slider widget. +* +* In scope of position searching this function finds the local maximum with the +* highest raw count. If such maximums are more than one, then the maximum with +* bigger sum of neighboring sensors is taken for further processing. Then the position +* is calculated using centroid algorithm with three sensors. +* +* This function does not detect two or more touches. +* +* \param newTouch +* The pointer to the touch structure where the found position is stored. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +*******************************************************************************/ +void Cy_CapSense_DpCentroidLinear( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t snsIndex = 0u; + uint32_t snsCount = ptrWdConfig->numSns; + + uint32_t diffM; + uint32_t diffP; + uint32_t sum = 0u; + uint32_t maxSum = 0u; + uint32_t maxDiff = 0u; + uint32_t maxIndex = 0u; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + int32_t numerator = 0; + int32_t denominator = 0; + uint32_t multiplier; + uint32_t offset; + + if (1u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_NUMBER_MASK)) + { + /* Find maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < snsCount; snsIndex++) + { + if (ptrSnsCxt->diff > maxDiff) + { + maxDiff = ptrSnsCxt->diff; + } + ptrSnsCxt++; + } + + /* Find index of sensor with maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < snsCount; snsIndex++) + { + /* Potential maximum */ + if (maxDiff == ptrSnsCxt->diff) + { + /* Get sum of differences around maximum */ + diffM = (snsIndex > 0u) ? (ptrSnsCxt - 1u)->diff : 0u; + diffP = (snsIndex < (snsCount - 1u)) ? (ptrSnsCxt + 1u)->diff : 0u; + sum = ptrSnsCxt->diff + diffM + diffP; + if (maxSum < sum) + { + /* New maximum */ + maxIndex = snsIndex; + maxSum = sum; + numerator = (int32_t)diffP - (int32_t)diffM; + } + } + ptrSnsCxt++; + } + + /* Calculate position */ + multiplier = (uint32_t)ptrWdConfig->xResolution << 8u; + if (0u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CALC_METHOD_MASK)) + { + multiplier /= (snsCount - 1u); + offset = 0u; + } + else + { + multiplier /= snsCount; + offset = multiplier >> 1u; + } + + denominator = (int32_t)maxSum; + denominator = ((numerator * (int32_t)multiplier) / denominator) + (((int32_t)maxIndex * (int32_t)multiplier) + (int32_t)offset); + + /* Round result and shift 8 bits left */ + newTouch->numPosition = 1u; + newTouch->ptrPosition[0u].x = CY_LO16(((uint32_t)denominator + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + } + else + { + /* This is a place holder for local maximum searching when number of centroids could be more than one */ + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpCentroidRadial +****************************************************************************//** +* +* Finds touch position of a Radial slider widget. +* +* In scope of position searching this function finds the local maximum with the +* highest raw count. If such maximums are more than one, then the maximum with +* bigger sum of neighboring sensors is taken for further processing. Then the position +* is calculated using centroid algorithm with three sensors. +* +* This function does not detect two or more touches. +* +* \param newTouch +* The pointer to the touch structure where found position is stored. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +*******************************************************************************/ +void Cy_CapSense_DpCentroidRadial( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t snsIndex = 0u; + uint32_t snsCount = ptrWdConfig->numSns; + + uint32_t diffM; + uint32_t diffP; + uint32_t sum = 0u; + uint32_t maxSum = 0u; + uint32_t maxDiff = 0u; + uint32_t maxIndex = 0u; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + int32_t numerator = 0; + int32_t denominator = 0; + uint32_t multiplier; + + if (1u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_NUMBER_MASK)) + { + /* Find maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < snsCount; snsIndex++) + { + if (ptrSnsCxt->diff > maxDiff) + { + maxDiff = ptrSnsCxt->diff; + } + ptrSnsCxt++; + } + + /* Find index of sensor with maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < snsCount; snsIndex++) + { + /* Potential maximum */ + if (maxDiff == ptrSnsCxt->diff) + { + /* Get sum of differences around maximum */ + diffM = (snsIndex > 0u) ? (ptrSnsCxt - 1u)->diff : ptrWdConfig->ptrSnsContext[snsCount - 1u].diff; + diffP = (snsIndex < (snsCount - 1u)) ? (ptrSnsCxt + 1u)->diff : ptrWdConfig->ptrSnsContext[0u].diff; + sum = ptrSnsCxt->diff + diffM + diffP; + if (maxSum < sum) + { + /* New maximum */ + maxIndex = snsIndex; + maxSum = sum; + numerator = (int32_t)diffP - (int32_t)diffM; + } + } + ptrSnsCxt++; + } + + /* Calculate position */ + multiplier = ((uint32_t)ptrWdConfig->xResolution << 8u) / snsCount; + + denominator = (int32_t)maxSum; + denominator = ((numerator * (int32_t)multiplier) / denominator) + ((int32_t)maxIndex * (int32_t)multiplier); + if (denominator < 0) + { + denominator += ((int32_t)snsCount * (int32_t)multiplier); + } + /* Round result and shift 8 bits left */ + newTouch->numPosition = 1u; + newTouch->ptrPosition[0u].x = CY_LO16(((uint32_t)denominator + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + } + else + { + /* This is a place holder for local maximum searching when number of centroids could be more than one */ + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpCentroidTouchpad +****************************************************************************//** +* +* Finds touch position of a CSD Touchpad widget. +* +* In scope of position searching this function finds the local maximum with the +* highest raw count. If such maximums are more than one, then the maximum with +* bigger sum of neighboring sensors is taken for further processing. Then the position +* is calculated using centroid algorithm with three sensors. +* +* This function does not detect two or more touches. +* +* \param newTouch +* The pointer to the touch structure where found position is stored. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +*******************************************************************************/ +void Cy_CapSense_DpCentroidTouchpad( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t snsIndex = 0u; + uint32_t snsCount = ptrWdConfig->numSns; + uint32_t colCount = ptrWdConfig->numCols; + uint32_t rowCount = ptrWdConfig->numRows; + + uint32_t diffM; + uint32_t diffP; + uint32_t sum = 0u; + uint32_t maxSum = 0u; + uint32_t maxDiff = 0u; + uint32_t maxIndex = 0u; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + int32_t numerator = 0; + int32_t denominator = 0; + uint32_t multiplier; + uint32_t offset; + + if (1u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_NUMBER_MASK)) + { + /*********************************************************************** + * X Axis (Cols) + ***********************************************************************/ + sum = 0u; + maxSum = 0u; + maxDiff = 0u; + /* Find maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < colCount; snsIndex++) + { + if (ptrSnsCxt->diff > maxDiff) + { + maxDiff = ptrSnsCxt->diff; + } + ptrSnsCxt++; + } + + /* Find index of sensor with maximum signal */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = 0u; snsIndex < colCount; snsIndex++) + { + /* Potential maximum */ + if (maxDiff == ptrSnsCxt->diff) + { + /* Get sum of differences around maximum */ + diffM = (snsIndex > 0u) ? (ptrSnsCxt - 1u)->diff : 0u; + diffP = (snsIndex < (colCount - 1u)) ? (ptrSnsCxt + 1u)->diff : 0u; + sum = ptrSnsCxt->diff + diffM + diffP; + /* Check whether this sum is maximum sum */ + if (maxSum < sum) + { + /* New maximum */ + maxIndex = snsIndex; + maxSum = sum; + numerator = (int32_t)diffP - (int32_t)diffM; + } + } + ptrSnsCxt++; + } + + /* Calculate position */ + multiplier = (uint32_t)ptrWdConfig->xResolution << 8u; + if (0u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CALC_METHOD_MASK)) + { + multiplier /= (colCount - 1u); + offset = 0u; + } + else + { + multiplier /= colCount; + offset = multiplier >> 1u; + } + + denominator = (int32_t)maxSum; + denominator = ((numerator * (int32_t)multiplier) / denominator) + (((int32_t)maxIndex * (int32_t)multiplier) + (int32_t)offset); + + /* Round result and shift 8 bits left */ + newTouch->ptrPosition[0u].x = CY_LO16(((uint32_t)denominator + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + + /*********************************************************************** + * Y Axis (Rows) + ***********************************************************************/ + sum = 0u; + maxSum = 0u; + maxDiff = 0u; + maxIndex = 0u; + /* Find maximum signal */ + ptrSnsCxt = &ptrWdConfig->ptrSnsContext[colCount]; + for (snsIndex = colCount; snsIndex < snsCount; snsIndex++) + { + if (ptrSnsCxt->diff > maxDiff) + { + maxDiff = ptrSnsCxt->diff; + } + ptrSnsCxt++; + } + + /* Find index of sensor with maximum signal */ + ptrSnsCxt = &ptrWdConfig->ptrSnsContext[colCount]; + for (snsIndex = 0u; snsIndex < rowCount; snsIndex++) + { + /* Potential maximum */ + if (maxDiff == ptrSnsCxt->diff) + { + /* Get sum of differences around maximum */ + diffM = (snsIndex > 0u) ? (ptrSnsCxt - 1u)->diff : 0u; + diffP = (snsIndex < (rowCount - 1u)) ? (ptrSnsCxt + 1u)->diff : 0u; + sum = ptrSnsCxt->diff + diffM + diffP; + /* Check if this sum is maximum sum */ + if (maxSum < sum) + { + /* New maximum */ + maxIndex = snsIndex; + maxSum = sum; + numerator = (int32_t)diffP - (int32_t)diffM; + } + } + ptrSnsCxt++; + } + + /* Calculate position */ + multiplier = (uint32_t)ptrWdConfig->yResolution << 8u; + if (0u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CALC_METHOD_MASK)) + { + multiplier /= (rowCount - 1u); + offset = 0u; + } + else + { + multiplier /= rowCount; + offset = multiplier >> 1u; + } + + denominator = (int32_t)maxSum; + denominator = ((numerator * (int32_t)multiplier) / denominator) + (((int32_t)maxIndex * (int32_t)multiplier) + (int32_t)offset); + + /* Round result and shift 8 bits left */ + newTouch->ptrPosition[0].y = CY_LO16(((uint32_t)denominator + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + + newTouch->numPosition = 1u; + } + else + { + /* This is a place holder for local maximum searching when number of centroids could be more than one */ + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpAdvancedCentroidTouchpad +****************************************************************************//** +* +* Finds touch position of a CSD touchpad widget using an advanced centroid +* algorithm. +* +* This function is able to detect two touch positions using a centroid algorithm +* with matrix 5*5 of sensors and virtual sensors on the edges. +* +* \param newTouch +* The pointer to the touch structure where the found position is stored. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +*******************************************************************************/ +void Cy_CapSense_DpAdvancedCentroidTouchpad( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t i; + cy_stc_capsense_sensor_context_t * ptrSnsIndex = ptrWdConfig->ptrSnsContext; + uint16_t * ptrDiffIndex = ptrWdConfig->ptrCsdTouchBuffer; + cy_stc_capsense_advanced_centroid_config_t advCfg; + + advCfg.fingerTh = ptrWdConfig->ptrWdContext->fingerTh; + advCfg.penultimateTh = ptrWdConfig->advConfig.penultimateTh; + advCfg.virtualSnsTh = ptrWdConfig->advConfig.virtualSnsTh; + advCfg.resolutionX = ptrWdConfig->xResolution; + advCfg.resolutionY = ptrWdConfig->yResolution; + advCfg.snsCountX = ptrWdConfig->numCols; + advCfg.snsCountY = ptrWdConfig->numRows; + advCfg.crossCouplingTh = ptrWdConfig->advConfig.crossCouplingTh; + advCfg.edgeCorrectionEn = 0u; + advCfg.twoFingersEn = 0u; + + if ((ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_NUMBER_MASK) > CY_CAPSENSE_POSITION_ONE) + { + advCfg.twoFingersEn = 1u; + } + if (0u != (ptrWdConfig->centroidConfig & CY_CAPSENSE_EDGE_CORRECTION_MASK)) + { + advCfg.edgeCorrectionEn = 1u; + } + for (i = 0u; i < ptrWdConfig->numSns; i++) + { + ptrDiffIndex[i] = ptrSnsIndex[i].diff; + } + + Cy_CapSense_AdvancedCentroidGetTouchCoordinates_Lib( + &advCfg, + ptrWdConfig->ptrCsdTouchBuffer, + newTouch); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpFindLocalMaxDd +****************************************************************************//** +* +* Finds up to five local maximums for CSX Touchpad. +* +* This function takes an array of differences of the specified widget and +* finds up to five local maximums. The found maximums are stored in the CSX buffer +* ptrCsxTouchBuffer \ref cy_stc_capsense_csx_touch_buffer_t. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +void Cy_CapSense_DpFindLocalMaxDd( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + uint32_t thresholdOff = (uint32_t)ptrWdCxt->fingerTh - ptrWdCxt->hysteresis; + uint32_t thresholdOn = (uint32_t)ptrWdCxt->fingerTh + ptrWdCxt->hysteresis; + uint16_t currDiff; + uint8_t rx; + uint8_t tx; + uint8_t snsShift; + uint8_t lastRx = ptrWdConfig->numCols - 1u; + uint8_t lastTx = ptrWdConfig->numRows - 1u; + uint32_t proceed = 0u; + uint32_t touchNum = 0u; + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + + for (rx = CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS; rx-- > 0u;) + { + ptrNewPeak[rx].id = CY_CAPSENSE_CSX_TOUCHPAD_ID_UNDEFINED; + } + + ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + /* Go through all Rx electrodes */ + for (rx = 0u; rx <= lastRx; rx++) + { + /* + * Go through all Tx and RX (changed above) electrodes intersections + * and check whether the local maximum requirement is met. + */ + for (tx = 0u; tx <= lastTx; tx++) + { + proceed = 0u; + currDiff = ptrSnsCxt->diff; + if (thresholdOff <= (uint32_t)currDiff) + { + /* + * Check local maximum requirement: Comparing raw count + * of a local maximum candidate with raw counts of sensors + * from the previous row. + */ + if (rx > 0u) + { + /* Sensor(i-1, j+1) */ + snsShift = lastTx; + if ((tx < lastTx) && (currDiff <= (ptrSnsCxt - snsShift)->diff)) + { + proceed = 1u; + } + if (0u == proceed) + { + /* Sensor(i-1, j) */ + snsShift++; + if (currDiff <= (ptrSnsCxt - snsShift)->diff) + { + proceed = 1u; + } + } + if (0u == proceed) + { + /* Sensor(i-1, j-1) */ + snsShift++; + if ((tx > 0u) && (currDiff <= (ptrSnsCxt - snsShift)->diff)) + { + proceed = 1u; + } + } + } + /* + * Check local maximum requirement: Comparing raw count + * of a local maximum candidate with raw counts of sensors + * from the next row. + */ + if ((0u == proceed) && (rx < lastRx)) + { + /* Sensor(i+1, j+1) */ + snsShift = lastTx + 2u; + if ((tx < lastTx) && (currDiff < (ptrSnsCxt + snsShift)->diff)) + { + proceed = 1u; + } + if (0u == proceed) + { + /* Sensor(i+1, j) */ + snsShift--; + if (currDiff < (ptrSnsCxt + snsShift)->diff) + { + proceed = 1u; + } + } + if (0u == proceed) + { + /* Sensor(i+1, j-1) */ + snsShift--; + if ((tx > 0u) && (currDiff < (ptrSnsCxt + snsShift)->diff)) + { + proceed = 1u; + } + } + } + /* + * Check local maximum requirement: Comparing raw count + * of a local maximum candidate with raw counts of sensors + * from the same row Sensor(i, j+1). */ + if ((0u == proceed) && (tx < lastTx)) + { + if (currDiff < (ptrSnsCxt + 1u)->diff) + { + proceed = 1u; + } + } + /* Sensor(i, j-1) */ + if ((0u == proceed) && (tx > 0u)) + { + if (currDiff <= (ptrSnsCxt - 1u)->diff) + { + proceed = 1u; + } + } + /* Add local maximum to the touch structure if there is room. */ + if (0u == proceed) + { + ptrNewPeak->x = rx; + ptrNewPeak->y = tx; + if (currDiff < thresholdOn) + { + ptrNewPeak->id |= CY_CAPSENSE_CSX_TOUCHPAD_ID_ON_FAIL; + } + touchNum++; + ptrNewPeak++; + } + } + ptrSnsCxt++; + if (touchNum >= CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS) + { + break; + } + } + if (touchNum >= CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS) + { + break; + } + } + ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber = (uint8_t)touchNum; +} + + +/* CY_ID633 */ +#if defined(__ICCARM__) + #pragma optimize=none +#endif /* (__ICCARM__) */ +/******************************************************************************* +* Function Name: Cy_CapSense_DpCalcTouchPadCentroid +****************************************************************************//** +* +* Calculates the position for each local maximum using the 3x3 algorithm. +* +* This function calculates position coordinates of found local maximums. +* The found positions are stored in the CSX buffer ptrCsxTouchBuffer +* \ref cy_stc_capsense_csx_touch_buffer_t. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +void Cy_CapSense_DpCalcTouchPadCentroid( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + uint8_t number; + uint8_t i; + uint8_t j; + uint32_t lastRx = (uint32_t)ptrWdConfig->numCols - 1u; + uint32_t lastTx = (uint32_t)ptrWdConfig->numRows - 1u; + uint16_t centroid[3u][3u]; + int32_t weightedSumX; + int32_t weightedSumY; + uint32_t totalSum; + uint32_t multiplierX; + uint32_t offsetX; + uint32_t multiplierY; + uint32_t offsetY; + uint32_t touchNum = ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber; + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0]; + + for(number = 0u; number < touchNum; number++) + { + /* Set the sensor pointer to the local maximum sensor */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + ptrSnsCxt += (ptrNewPeak->y + (ptrNewPeak->x * ptrWdConfig->numRows)); + + /* Prepare 3x3 centroid two dimensional array */ + /* Fill each row */ + for (i = 0u; i < CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_LENGTH; i++) + { + /* + * The first condition could be valid only when local max on the first row (0 row) of Touchpad + * The second condition could be valid only when local max on the last row of Touchpad + * Then corresponding row (zero or the last) of 3x3 array is initialized to 0u + */ + if (((((int32_t)ptrNewPeak->x - 1) + (int32_t)i) < 0) || + ((((int32_t)ptrNewPeak->x - 1) + (int32_t)i) > (int32_t)lastRx)) + { + centroid[CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_PREVIOUS][i] = 0u; + centroid[CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_CENTER][i] = 0u; + centroid[CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_NEXT][i] = 0u; + } + else + { + /* Fill each column */ + for (j = 0u; j < CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_LENGTH; j++) + { + /* + * The first condition could be valid only when local max + * on the first column (0 row) of Touchpad. The second + * condition could be valid only when local max on the last + * column of Touchpad. Then corresponding column (zero or + * the last) of 3x3 array is initialized to 0u. + */ + if (((((int32_t)ptrNewPeak->y - 1) + (int32_t)j) < 0) || + ((((int32_t)ptrNewPeak->y - 1) + (int32_t)j) > (int32_t)lastTx)) + { + centroid[j][i] = 0u; + } + else + { + centroid[j][i] = (uint16_t)(ptrSnsCxt + (((i - 1u) * ptrWdConfig->numRows) + (j - 1u)))->diff; //MISRA? + } + } + } + } + + weightedSumX = 0; + weightedSumY = 0; + totalSum = 0u; + + /* Calculate centroid */ + for (i = 0u; i < CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_LENGTH; i++) + { + for (j = 0u; j < CY_CAPSENSE_CSX_TOUCHPAD_CENTROID_LENGTH; j++) + { + totalSum += centroid[i][j]; + weightedSumX += (int32_t)centroid[i][j] * ((int32_t)j - 1); + weightedSumY += (int32_t)centroid[i][j] * ((int32_t)i - 1); + } + } + + /* The X position is calculated. + * The weightedSumX value depends on a finger position shifted regarding + * the X electrode (ptrNewTouches.x). + * The multiplier ptrWdConfig->xCentroidMultiplier is a short from: + * CY_CAPSENSE_TOUCHPAD0_X_RESOLUTION * 256u) / (CY_CAPSENSE_TOUCHPAD0_NUM_RX - CONFIG)) + * where CONFIG = 0 or 1 depends on TouchpadMultiplerMethod parameter. + */ + /* Calculate position */ + multiplierX = (uint32_t)ptrWdConfig->xResolution << 8u; + multiplierY = (uint32_t)ptrWdConfig->yResolution << 8u; + if (0u == (ptrWdConfig->centroidConfig & CY_CAPSENSE_CALC_METHOD_MASK)) + { + multiplierX /= lastRx; + offsetX = 0u; + multiplierY /= lastTx; + offsetY = 0u; + } + else + { + multiplierX /= (lastRx + 1u); + offsetX = multiplierX >> 1u; + multiplierY /= (lastTx + 1u); + offsetY = multiplierY >> 1u; + } + + weightedSumX = ((weightedSumX * (int32_t)multiplierX) / (int32_t)totalSum) + + ((((int32_t)ptrNewPeak->x) * (int32_t)multiplierX) + (int32_t)offsetX); + + /* The X position is rounded to the nearest integer value and normalized to the resolution range */ + ptrNewPeak->x = CY_LO16(((uint32_t)weightedSumX + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + /* The Y position is calculated. + * The weightedSumY value depends on a finger position shifted regarding the Y electrode (ptrWdConfig->ptrNewTouches.y) + * The multiplier ptrWdConfig->yCentroidMultiplier is a short from: + * CY_CAPSENSE_TOUCHPAD0_Y_RESOLUTION * 256u) / (CY_CAPSENSE_TOUCHPAD0_NUM_TX - CONFIG)) + * where CONFIG = 0 or 1 depends on TouchpadMultiplerMethod parameter + */ + weightedSumY = ((weightedSumY * (int32_t)multiplierY) / (int32_t)totalSum) + + ((((int32_t)ptrNewPeak->y) * (int32_t)multiplierY) + (int32_t)offsetY); + + /* The Y position is rounded to the nearest integer value and normalized to the resolution range */ + ptrNewPeak->y = CY_LO16(((uint32_t)weightedSumY + CY_CAPSENSE_CENTROID_ROUND_VALUE) >> 8u); + + /* The z value is a sum of raw counts of sensors that form 3x3 matrix with a local maximum in the center */ + ptrNewPeak->z = CY_LO8(totalSum >> CY_CAPSENSE_CSX_TOUCHPAD_Z_SHIFT); + ptrNewPeak++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpTouchTracking +****************************************************************************//** +* +* Tracks touches. +* +* This function tracks the found touches: +* - associates them with previous touches applying the Hungarian algorithm. +* - applies debounce filters. +* - suppresses excessive touches. +* +* The final touch data are stored in the CSX buffer ptrCsxTouchBuffer +* \ref cy_stc_capsense_csx_touch_buffer_t. This function should be called +* each scan cycle even when touch is not detected. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +void Cy_CapSense_DpTouchTracking( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t i; + + cy_stc_capsense_position_t * ptrNewPeak; + cy_stc_capsense_position_t * ptrOldPeak; + + uint32_t newTouchNum = ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber; + uint32_t oldTouchNum = ptrWdConfig->ptrCsxTouchHistory->oldPeakNumber; + + int8_t * fingerPosIndex = &ptrWdConfig->ptrCsxTouchBuffer->fingerPosIndexMap[0u]; + + if ((0u != newTouchNum) || (0u != oldTouchNum)) + { + /* Initialize variables */ + ptrWdConfig->ptrCsxTouchBuffer->newActiveIdsMask = 0u; + /* Getting active touch IDs from previous scan */ + ptrWdConfig->ptrCsxTouchHistory->oldActiveIdsMask = 0u; + + ptrOldPeak = &ptrWdConfig->ptrCsxTouchHistory->oldPeak[0u]; + for (i = 0u; i < oldTouchNum; i++) + { + ptrWdConfig->ptrCsxTouchHistory->oldActiveIdsMask |= (uint8_t)(1u << ptrOldPeak->id); + ptrOldPeak++; + } + + if (0u < newTouchNum) + { + if (0u == oldTouchNum) + { + /* If the previous touch tracking had not any touches */ + for (i = 0u; i < newTouchNum; i++) + { + /* Initializes a new touch, set ID to next value and Age to 0 */ + Cy_CapSense_NewTouch(i, ptrWdConfig); + } + } + else + { + /* Don't call Hungarian for 1 current and 1 previous touch */ + fingerPosIndex[0u] = 0; + if ((1u != newTouchNum) || (1u != oldTouchNum)) + { + Cy_CapSense_Hungarian(ptrWdConfig); + } + /* General case */ + if (newTouchNum >= oldTouchNum) + { + ptrOldPeak = &ptrWdConfig->ptrCsxTouchHistory->oldPeak[0u]; + for (i = 0u; i < oldTouchNum; i++) + { + if (ptrWdConfig->ptrCsxTouchHistory->velocity < Cy_CapSense_CalcDistance((uint32_t)fingerPosIndex[i], i, ptrWdConfig)) + { + /* Set new ID and reset Age */ + Cy_CapSense_NewTouch((uint32_t)fingerPosIndex[i], ptrWdConfig); + } + else + { + /* Set ID to previous value and increase Age */ + ptrWdConfig->ptrCsxTouchBuffer->newActiveIdsMask |= (uint8_t)(1u << (ptrOldPeak->id)); + Cy_CapSense_TransferTouch((uint32_t)fingerPosIndex[i], i, ptrWdConfig); + } + ptrOldPeak++; + } + } + else + { + ptrOldPeak = &ptrWdConfig->ptrCsxTouchHistory->oldPeak[0u]; + for (i = 0u; i < newTouchNum; i++) + { + if (ptrWdConfig->ptrCsxTouchHistory->velocity < Cy_CapSense_CalcDistance(i, (uint32_t)fingerPosIndex[i], ptrWdConfig)) + { + /* Set new ID and reset Age. */ + Cy_CapSense_NewTouch(i, ptrWdConfig); + } + else + { + /* Set ID to previous value and increase Age. */ + ptrWdConfig->ptrCsxTouchBuffer->newActiveIdsMask |= (uint8_t)(1u << (ptrOldPeak->id)); + Cy_CapSense_TransferTouch(i, (uint32_t)fingerPosIndex[i], ptrWdConfig); + } + ptrOldPeak++; + } + } + /* Added new fingers, they need to assign ID */ + if (newTouchNum > oldTouchNum) + { + /* Search new fingers */ + ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + for (i = 0u; i < newTouchNum; i++) + { + /* New finger found */ + if (0u != (ptrNewPeak->id & CY_CAPSENSE_CSX_TOUCHPAD_ID_UNDEFINED)) + { + Cy_CapSense_NewTouch(i, ptrWdConfig); + } + ptrNewPeak++; + } + } + } + + Cy_CapSense_TouchDownDebounce(ptrWdConfig); + } + + Cy_CapSense_SortByAge(ptrWdConfig); + newTouchNum = ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber; + + /* Store new touches as old touches */ + ptrWdConfig->ptrCsxTouchHistory->oldPeakNumber = (uint8_t)newTouchNum; + ptrWdConfig->ptrCsxTouchHistory->oldActiveIdsMask = ptrWdConfig->ptrCsxTouchBuffer->newActiveIdsMask; + ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + ptrOldPeak = &ptrWdConfig->ptrCsxTouchHistory->oldPeak[0u]; + for (i = newTouchNum; i-- > 0u;) + { + Cy_CapSense_CopyTouchRecord(ptrOldPeak, ptrNewPeak); + ptrNewPeak++; + ptrOldPeak++; + } + } + } + +/******************************************************************************* +* Function Name: Cy_CapSense_TransferTouch +****************************************************************************//** +* +* Transfers a touch from history array into active current array. +* +* This function transfers touch specified by oldIndex from history touch array +* by copying its ID, increments age and decrements debounce (if debounce > 0) +* parameters into currently active touch structure +* +* \param newIndex +* The touch index of touch array in the active touch structure. +* +* \param oldIndex +* The touch index of touch array in the history touch structure. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +static void Cy_CapSense_TransferTouch( + uint32_t newIndex, + uint32_t oldIndex, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t touchId; + uint32_t touchAge; + uint32_t touchDebounce; + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[newIndex]; + cy_stc_capsense_position_t * ptrOldPeak = &ptrWdConfig->ptrCsxTouchHistory->oldPeak[oldIndex]; + + touchId = (uint32_t)ptrOldPeak->id & CY_CAPSENSE_CSX_TOUCHPAD_ID_MASK; + touchAge = ((uint32_t)ptrOldPeak->z & CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK) >> CY_CAPSENSE_CSX_TOUCHPAD_BYTE_SHIFT; + touchDebounce = ((uint32_t)ptrOldPeak->id & CY_CAPSENSE_CSX_TOUCHPAD_DEBOUNCE_MASK) >> CY_CAPSENSE_CSX_TOUCHPAD_BYTE_SHIFT; + + /* Increase AGE by 1 if possible */ + if (touchAge < CY_CAPSENSE_CSX_TOUCHPAD_MAX_AGE) + { + touchAge++; + } + /* Decrement Debounce counter if possible */ + if (touchDebounce > 0u) + { + touchDebounce--; + } + + ptrNewPeak->id = (uint16_t)(touchId | (uint16_t)(touchDebounce << CY_CAPSENSE_CSX_TOUCHPAD_BYTE_SHIFT)); + ptrNewPeak->z &= (uint16_t)~CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK; + ptrNewPeak->z |= (uint16_t)(touchAge << CY_CAPSENSE_CSX_TOUCHPAD_BYTE_SHIFT); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_NewTouch +****************************************************************************//** +* +* Set ID, age, and on debounce parameters for a new touch. +* +* If raw count is lower than the finger-On-Threshold, +* then the corresponding touch is marked with CY_CAPSENSE_CSX_TOUCHPAD_ID_ON_FAIL +* in the ID and will be deleted from the new touch structure in Cy_CapSense_SortByAge() +* (new touch structure is reorganized in this case). +* +* \param newIndex +* The touch index of touch array in the active touch structure. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +static void Cy_CapSense_NewTouch( + uint32_t newIndex, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t idx; + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[newIndex]; + + /* Touch is not accepted */ + if (0u == (ptrNewPeak->id & CY_CAPSENSE_CSX_TOUCHPAD_ID_ON_FAIL)) + { + /* Create a bit map of ID's currently used and previously used and search for the new lowest ID */ + idx = Cy_CapSense_GetLowestId(ptrWdConfig->ptrCsxTouchHistory->oldActiveIdsMask | + ptrWdConfig->ptrCsxTouchBuffer->newActiveIdsMask); + + /* Indicate that ID is now taken */ + ptrWdConfig->ptrCsxTouchBuffer->newActiveIdsMask |= (uint8_t)(1u << idx); + + /* Set AGE */ + ptrNewPeak->z &= (uint16_t)~CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK; + ptrNewPeak->z |= CY_CAPSENSE_CSX_TOUCHPAD_AGE_START; + + /* Set ID and Debounce */ + ptrNewPeak->id = (uint16_t)idx | (uint16_t)(((uint16_t)ptrWdConfig->ptrWdContext->onDebounce - 1u) << CY_CAPSENSE_CSX_TOUCHPAD_BYTE_SHIFT); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_GetLowestId +****************************************************************************//** +* +* Returns the lowest available free touch ID. +* +* \param idMask +* The mask of IDs used in active and history touch structures. +* +* \return +* Returns the lowest available touch ID. If no ID is available, +* CY_CAPSENSE_CSX_TOUCHPAD_ID_ABSENT is returned. +* +*******************************************************************************/ +__STATIC_INLINE uint8_t Cy_CapSense_GetLowestId(uint8_t idMask) +{ + uint32_t idx; + uint32_t touchId = CY_CAPSENSE_CSX_TOUCHPAD_ID_ABSENT; + + /* Search for the lowest available ID */ + for (idx = CY_CAPSENSE_CSX_TOUCHPAD_ID_MIN; idx <= CY_CAPSENSE_CSX_TOUCHPAD_ID_MAX; idx++) + { + /* Determine whether the new ID is available */ + if (0u == (idMask & 1u)) + { + touchId = idx; + break; + } + + idMask >>= 1u; + } + + /* Return an indicator of failure */ + return (uint8_t)(touchId); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_TouchDownDebounce +****************************************************************************//** +* +* Handles touchdown debouncing. +* +* Even if a new touch is detected, it is not considered as active until the +* debounce counter has not reached zero. If the debounce counter has reached zero, +* the touchdown mask is cleared. Otherwise the age of the new finger is cleared +* (it is considered as not active). +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CapSense_TouchDownDebounce( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t i; + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + + for (i = 0u; i < ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber; i++) + { + /* If it is a touchdown debouncing finger its age is set to zero */ + if (0u != (ptrNewPeak->id & CY_CAPSENSE_CSX_TOUCHPAD_DEBOUNCE_MASK)) + { + /* Set the age to zero - finger is not active */ + ptrNewPeak->z &= (uint16_t)~CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK; + } + ptrNewPeak++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalcDistance +****************************************************************************//** +* +* Calculates squared distance between history and active touch structures +* pointed by the input parameters. +* +* \param newIndex +* The index of touch in the active touch structure. +* +* \param oldIndex +* The index of touch in the history touch structure. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +* \return +* Returns the squared distance. +* +*******************************************************************************/ +static uint32_t Cy_CapSense_CalcDistance( + uint32_t newIndex, + uint32_t oldIndex, + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[newIndex]; + cy_stc_capsense_position_t * ptrOldPeak = &ptrWdConfig->ptrCsxTouchHistory->oldPeak[oldIndex]; + + int32_t xDistance = (int32_t)(ptrOldPeak->x) - (int32_t)(ptrNewPeak->x); + int32_t yDistance = (int32_t)(ptrOldPeak->y) - (int32_t)(ptrNewPeak->y); + + xDistance *= xDistance; + yDistance *= yDistance; + + return ((uint32_t)xDistance + (uint32_t)yDistance); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Hungarian +****************************************************************************//** +* +* Executes the Hungarian method on a distance map to track motion of two +* touch sets (old touches vs new touches). +* +* This function uses the Hungarian method described in specification 001-63362. +* There is no bound checking on the parameters. It is the calling function's +* responsibility to ensure parameter validity. +* The function output is a fingerPosIndexMap array stored in the CSX buffer +* where associations between the previous and current touches are returned. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +static void Cy_CapSense_Hungarian( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + cy_stc_capsense_csx_touch_buffer_t * ptrBuffer = ptrWdConfig->ptrCsxTouchBuffer; + /* + * Number of elements in column of distanceMap matrix. This value must + * be greater than or equal to 1. + */ + int32_t * col = &ptrBuffer->colMap[0u]; + /* + * Number of elements in row of distanceMap matrix. This value must be + * greater than or equal to colCount. + */ + int32_t * row = &ptrBuffer->rowMap[0u]; + int32_t * mins = &ptrBuffer->minsMap[0u]; + int8_t * links = &ptrBuffer->linksMap[0u]; + int8_t * visited = &ptrBuffer->visitedMap[0u]; + int8_t * markIndices = &ptrBuffer->markIndicesMap[0u]; + /* + * The 2-dimensional map of distances between the nodes in each + * coordinate set. The 1st index of distanceMap corresponds to nodes + * in the 1st coordinate data set, and the 2nd index of distanceMap + * corresponds to the 2nd coordinate data set. Each element in + * distanceMap is the square of the distance between the + * corresponding coordinates in the 1st and 2nd data set. + */ + int32_t * distance = &ptrBuffer->distanceMap[0u]; + + int32_t delta = 0; + int32_t colValue = 0; + int32_t markedI = 0; + int32_t markedJ = 0; + int32_t i = 0; + int32_t iIndex = 0; + int32_t j = 0; + int32_t jIndex = 0; + + uint32_t rowCount = ptrBuffer->newPeakNumber; + uint32_t colCount = ptrWdConfig->ptrCsxTouchHistory->oldPeakNumber; + + /* Fill distance map */ + if (rowCount >= colCount) + { + for (i = (int32_t)rowCount; i-- > 0; ) + { + for (j = (int32_t)colCount; j-- > 0; ) + { + distance[((uint32_t)i * CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS) + (uint32_t)j] = (int32_t)Cy_CapSense_CalcDistance((uint32_t)i, (uint32_t)j, ptrWdConfig); + } + } + } + else + { + for (i = (int32_t)colCount; i-- > 0;) + { + for (j = (int32_t)rowCount; j-- > 0;) + { + distance[((uint32_t)i * CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS) + (uint32_t)j] = (int32_t)Cy_CapSense_CalcDistance((uint32_t)j, (uint32_t)i, ptrWdConfig); + } + } + colValue = (int32_t)colCount; + colCount = rowCount; + rowCount = (uint32_t)colValue; + } + + (void)memset(col, 0, (uint32_t)colCount * 4u); + + /* Initialize row and markIndices arrays */ + for (i = (int32_t)rowCount; i-- > 0;) + { + row[i] = 0; + markIndices[i] = -1; + } + + /* Go through all columns */ + for (i = (int32_t)colCount; i-- > 0;) + { + /* Initialize visited, links, mins arrays. They are used for every column */ + for (iIndex = (int32_t)rowCount; iIndex-- > 0;) + { + visited[iIndex] = 0; + links[iIndex] = -1; + mins[iIndex] = INT32_MAX; + } + + /* Next two variables are used to mark column and row */ + markedI = i; + markedJ = -1; + + while (markedI != -1) + { + j = -1; + colValue = col[markedI]; + + /* Go through all rows */ + for (jIndex = (int32_t)rowCount; jIndex-- > 0;) + { + if (visited[jIndex] == 0) + { + delta = distance[((uint32_t)jIndex * CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS) + (uint32_t)markedI] - row[jIndex] - colValue; + + /* Find the minimum element index in column i */ + if (mins[jIndex] > delta) + { + mins[jIndex] = delta; + links[jIndex] = (int8_t)markedJ; + } + + if ((j == -1) || (mins[jIndex] < mins[j])) + { + j = jIndex; + } + } + } + + delta = mins[j]; + + /* Go through all rows */ + for (jIndex = (int32_t)rowCount; jIndex-- > 0;) + { + if (visited[jIndex] != 0) + { + col[markIndices[jIndex]] += delta; + row[jIndex] -= delta; + } + else + { + mins[jIndex] -= delta; + } + } + + col[i] += delta; + + visited[j] = 1; + markedJ = j; + markedI = markIndices[j]; + } + + while (links[j] != -1) + { + markIndices[j] = markIndices[links[j]]; + j = links[j]; + } + + markIndices[j] = (int8_t)i; + } + + /* Provide an association between two sets of touches */ + for (j = (int32_t)rowCount; j-- > 0;) + { + if (markIndices[j] != -1) + { + ptrBuffer->fingerPosIndexMap[markIndices[j]] = (int8_t)j; + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SortByAge +****************************************************************************//** +* +* Sorts the new touch array by: +* 1. age (in decrementing order) +* and +* 2. id (in incrementing order) fields. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CapSense_SortByAge( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t i; + uint32_t j; + cy_stc_capsense_position_t tempPeak; + cy_stc_capsense_position_t * ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + cy_stc_capsense_position_t * ptrNewPeakJ; + uint32_t newTouchNum = ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber; + + /* + * Delete failed touch by coping (rewriting) the last touch content to the failed touch. + * If the last touch record is invalid, try the penultimate touch record and so on. + */ + for (i = 0u; i < newTouchNum; i++) + { + if ((ptrNewPeak->id & CY_CAPSENSE_CSX_TOUCHPAD_ID_MASK) > CY_CAPSENSE_CSX_TOUCHPAD_ID_MAX) + { + for (j = (newTouchNum - 1u); j > i; j--) + { + /* + * Check the touch records from the last to the current. + * If the touch record is valid, then replace the current touch record. + */ + ptrNewPeakJ = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[j]; + if ((ptrNewPeakJ->id & CY_CAPSENSE_CSX_TOUCHPAD_ID_MASK) <= CY_CAPSENSE_CSX_TOUCHPAD_ID_MAX) + { + Cy_CapSense_CopyTouchRecord(ptrNewPeak, ptrNewPeakJ); + + /* Finish the loop. The valid touch record is found and copied. */ + break; + } + else + { + /* Decrement the number of touch records. + * The last touch record is invalid - try the penultimate touch record. + */ + newTouchNum--; + } + } + + /* Decrement the number of touch records. + * The last touch record is valid and copied to the current position (i) + */ + newTouchNum--; + } + ptrNewPeak++; + } + + /* Set new number of touches */ + ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber = (uint8_t)newTouchNum; + + ptrNewPeak = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[0u]; + /* Sort new touches structure */ + for (i = 0u; i < newTouchNum; i++) + { + for (j = (i + 1u); j < newTouchNum; j++) + { + ptrNewPeakJ = &ptrWdConfig->ptrCsxTouchBuffer->newPeak[j]; + /* If next touches have higher age or lower id with the same age then swap touches */ + if (((ptrNewPeak->z & CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK) < (ptrNewPeakJ->z & CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK)) || + (((ptrNewPeak->z & CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK) == (ptrNewPeakJ->z & CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK)) && (ptrNewPeak->id > ptrNewPeakJ->id))) + { + /* Swap touches */ + Cy_CapSense_CopyTouchRecord(&tempPeak, ptrNewPeak); + Cy_CapSense_CopyTouchRecord(ptrNewPeak, ptrNewPeakJ); + Cy_CapSense_CopyTouchRecord(ptrNewPeakJ, &tempPeak); + } + } + ptrNewPeak++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CopyTouchRecord +****************************************************************************//** +* +* Copies content from the source touch structure to the destination touch structure. +* +* \param destination +* The pointer to the destination touch structure \ref cy_stc_capsense_position_t. +* +* \param source +* The pointer to the source touch structure \ref cy_stc_capsense_position_t. +* +*******************************************************************************/ +static void Cy_CapSense_CopyTouchRecord( + cy_stc_capsense_position_t * destination, + const cy_stc_capsense_position_t * source) +{ + *destination = *source; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpFilterTouchRecord +****************************************************************************//** +* +* Filters position data of every valid touch if enabled and copies data into +* public touch array. +* +* This function checks every touch in the new touch structure. If the touch is +* valid (valid id and age > 0), then touch is filtered if the filter is enabled. +* At the end, the corresponding fields are updated in the public touch structure. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure +* \ref cy_stc_capsense_widget_config_t. +* +*******************************************************************************/ +void Cy_CapSense_DpFilterTouchRecord( + const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t i; + uint32_t j; + uint32_t reportedTouchNum = 0u; + uint32_t peakNum = ptrWdConfig->ptrCsxTouchBuffer->newPeakNumber; + uint32_t filterSize; + uint32_t maxTouch; + uint32_t newTouchFlag = 0u; + cy_stc_capsense_position_t * ptrWdTouch = ptrWdConfig->ptrWdContext->wdTouch.ptrPosition; + cy_stc_capsense_position_t * ptrNewPeak = ptrWdConfig->ptrCsxTouchBuffer->newPeak; + cy_stc_capsense_position_t * ptrHistory; + uint32_t historyFlag[CY_CAPSENSE_MAX_CENTROIDS] = {0u}; + + /* Define number of touches that should be reported */ + for (i = 0u; i < CY_CAPSENSE_MAX_CENTROIDS; i++) + { + /* + * Age must be higher than 0 otherwise the touch does not pass + * debounce procedure. It exists in the array for correct + * touch tracking and debouncing. + */ + if ((i < peakNum) && ((ptrNewPeak->z & CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK) > 0u)) + { + reportedTouchNum++; + } + ptrNewPeak++; + } + + maxTouch = (uint32_t)ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_NUMBER_MASK; + if (reportedTouchNum > maxTouch) + { + reportedTouchNum = maxTouch; + } + + if (0u != (ptrWdConfig->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_MASK)) + { + filterSize = (ptrWdConfig->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_SIZE_MASK) >> + CY_CAPSENSE_POSITION_FILTERS_SIZE_OFFSET; + + /* Go through all new touches */ + ptrNewPeak = ptrWdConfig->ptrCsxTouchBuffer->newPeak; + for (i = 0u; i < reportedTouchNum; i++) + { + newTouchFlag = 0u; + /* Find index in the history array that corresponds to the new touch */ + ptrHistory = ptrWdConfig->ptrPosFilterHistory->ptrPosition; + for (j = 0u; j < maxTouch; j++) + { + /* ID must match */ + if (ptrHistory->id == ptrNewPeak->id) + { + /* Filter X and Y position of touch that exists from previous scan */ + Cy_CapSense_RunPositionFilters(ptrWdConfig, ptrNewPeak, ptrHistory); + /* Mark history touch as assigned */ + historyFlag[j] = 1u; + newTouchFlag = 1u; + /* Because the touch is found and processed, go to the next new touch */ + break; + } + ptrHistory += filterSize; + } + /* The touch is not found in history */ + if (0u == newTouchFlag) + { + /* Find a place to keep history and initialize it */ + ptrHistory = ptrWdConfig->ptrPosFilterHistory->ptrPosition; + for (j = 0u; j < maxTouch; j++) + { + if (0u == historyFlag[j]) + { + Cy_CapSense_InitPositionFilters(ptrWdConfig->posFilterConfig, ptrNewPeak, ptrHistory); + historyFlag[j] = 1u; + /* Assignment is done; go to the next new touch */ + break; + } + ptrHistory += filterSize; + } + } + ptrNewPeak++; + } + /* Reset all non-assigned history IDs */ + ptrHistory = ptrWdConfig->ptrPosFilterHistory->ptrPosition; + for (j = 0u; j < maxTouch; j++) + { + if (0u == historyFlag[j]) + { + ptrHistory->id = CY_CAPSENSE_CSX_TOUCHPAD_ID_UNDEFINED; + } + ptrHistory += filterSize; + } + } + + /* Go through all touch fields in the data structure */ + ptrNewPeak = ptrWdConfig->ptrCsxTouchBuffer->newPeak; + for (i = 0u; i < maxTouch; i++) + { + ptrWdTouch->id = CY_CAPSENSE_CSX_TOUCHPAD_ID_UNDEFINED; + + if (i < reportedTouchNum) + { + /* Report touch to the data structure */ + ptrWdTouch->x = ptrNewPeak->x; + ptrWdTouch->y = ptrNewPeak->y; + ptrWdTouch->z = ptrNewPeak->z; + ptrWdTouch->id = ptrNewPeak->id; + } + ptrNewPeak++; + ptrWdTouch++; + } + + ptrWdConfig->ptrWdContext->wdTouch.numPosition = (uint8_t)reportedTouchNum; + if (0u == reportedTouchNum) + { + ptrWdConfig->ptrWdContext->status &= (uint8_t)~CY_CAPSENSE_WD_ACTIVE_MASK; + } + else + { + ptrWdConfig->ptrWdContext->status = CY_CAPSENSE_WD_ACTIVE_MASK; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitPositionFilters +****************************************************************************//** +* +* Initializes history of touch structures by provided current touch states. +* +* \param filterConfig +* The configuration of filters of the widget. +* +* \param ptrInput +* The pointer to the position structure that holds currently detected +* position values. +* +* \param ptrHistory +* The pointer to the position structure that holds previous historical +* position values. +* +*******************************************************************************/ +void Cy_CapSense_InitPositionFilters( + uint32_t filterConfig, + const cy_stc_capsense_position_t * ptrInput, + cy_stc_capsense_position_t * ptrHistory) +{ + cy_stc_capsense_position_t * ptrHistoryIndex = ptrHistory; + + if (0u != (filterConfig & CY_CAPSENSE_POSITION_MED_MASK)) + { + *ptrHistoryIndex = *ptrInput; + ptrHistoryIndex++; + *ptrHistoryIndex = *ptrInput; + ptrHistoryIndex++; + } + if (0u != (filterConfig & CY_CAPSENSE_POSITION_IIR_MASK)) + { + *ptrHistoryIndex = *ptrInput; + ptrHistoryIndex++; + } + if (0u != (filterConfig & CY_CAPSENSE_POSITION_AIIR_MASK)) + { + ptrHistoryIndex->x = ptrInput->x; + ptrHistoryIndex->y = ptrInput->y; + ptrHistoryIndex++; + } + if (0u != (filterConfig & CY_CAPSENSE_POSITION_AVG_MASK)) + { + *ptrHistoryIndex = *ptrInput; + ptrHistoryIndex++; + } + if (0u != (filterConfig & CY_CAPSENSE_POSITION_JIT_MASK)) + { + *ptrHistoryIndex = *ptrInput; + ptrHistoryIndex++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunPositionFilters +****************************************************************************//** +* +* Applies enabled filters to position specified by ptrInput argument and stores +* history into ptrHistory. +* +* \param filterConfig +* The configuration of filters of the widget. +* +* \param ptrInput +* The pointer to the position structure that holds currently detected +* position values. +* +* \param ptrHistory +* The pointer to the position structure that holds previous historical +* position values. +* +*******************************************************************************/ +void Cy_CapSense_RunPositionFilters( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_position_t * ptrInput, + cy_stc_capsense_position_t * ptrHistory) +{ + uint32_t temp; + uint32_t xPos = ptrInput->x; + uint32_t yPos = ptrInput->y; + cy_stc_capsense_position_t * ptrHistoryIndex = ptrHistory; + uint32_t filterCfg = ptrWdConfig->posFilterConfig; + uint32_t coeffIIR = (uint32_t)(filterCfg & CY_CAPSENSE_POSITION_IIR_COEFF_MASK) >> CY_CAPSENSE_POSITION_IIR_COEFF_OFFSET; + + if (0u != (filterCfg & CY_CAPSENSE_POSITION_MED_MASK)) + { + temp = Cy_CapSense_FtMedian((uint32_t)ptrHistoryIndex[1u].x, (uint32_t)ptrHistoryIndex[0u].x, xPos); + ptrHistoryIndex[1u].x = ptrHistoryIndex[0u].x; + ptrHistoryIndex[0u].x = (uint16_t)xPos; + xPos = temp; + temp = Cy_CapSense_FtMedian((uint32_t)ptrHistoryIndex[1u].y, (uint32_t)ptrHistoryIndex[0u].y, yPos); + ptrHistoryIndex[1u].y = ptrHistoryIndex[0u].y; + ptrHistoryIndex[0u].y = (uint16_t)yPos; + yPos = temp; + ptrHistoryIndex++; + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_IIR_MASK)) + { + xPos = Cy_CapSense_FtIIR1stOrder(xPos, (uint32_t)ptrHistoryIndex->x, coeffIIR); + ptrHistoryIndex->x = (uint16_t)xPos; + yPos = Cy_CapSense_FtIIR1stOrder(yPos, (uint32_t)ptrHistoryIndex->y, coeffIIR); + ptrHistoryIndex->y = (uint16_t)yPos; + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_AIIR_MASK)) + { + Cy_CapSense_AdaptiveFilterRun_Lib(&ptrWdConfig->aiirConfig, ptrHistoryIndex, &xPos, &yPos); + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_AVG_MASK)) + { + temp = xPos; + xPos = (xPos + ptrHistoryIndex->x) >> 1u; + ptrHistoryIndex->x = (uint16_t)temp; + temp = yPos; + yPos = (yPos + ptrHistoryIndex->y) >> 1u; + ptrHistoryIndex->y = (uint16_t)temp; + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_JIT_MASK)) + { + xPos = Cy_CapSense_FtJitter(xPos, (uint32_t)ptrHistoryIndex->x); + ptrHistoryIndex->x = (uint16_t)xPos; + yPos = Cy_CapSense_FtJitter(yPos, (uint32_t)ptrHistoryIndex->y); + ptrHistoryIndex->y = (uint16_t)yPos; + } + ptrInput->x = (uint16_t)xPos; + ptrInput->y = (uint16_t)yPos; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunPositionFiltersRadial +****************************************************************************//** +* +* Applies enabled filters to position specified by the ptrInput argument and stores +* history into ptrHistory. Filtering considers specific widget type where +* the next value after maximum position is zero and vise versa. +* +* \param filterConfig +* The configuration of filters of the widget. +* +* \param ptrInput +* The pointer to the position structure that holds currently detected +* position values. +* +* \param ptrHistory +* The pointer to the position structure that holds previous historical +* position values. +* +*******************************************************************************/ +void Cy_CapSense_RunPositionFiltersRadial( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_position_t * ptrInput, + cy_stc_capsense_position_t * ptrHistory) +{ + /* + * If new position crosses the zero point in one or another direction, + * the position variable with the smaller value is increased by the + * slider resolution. This is done for the proper filtering. For + * example, xResolution = 100, currPosition = 95, newPosition = 5. + * If no actions are taken, then the average filter will give a value of + * 50 - which is wrong. But if the position values are adjusted as + * mentioned here, we will get newPosition equal 105 and the average + * will be 100. Later this filtered value will be adjusted further + * to not cross the xResolution and it will end up with 0u - which + * is correct average result for the provided example. + */ + + uint32_t z1; + uint32_t z2; + uint32_t temp; + /* The register contains max position value, so therefore it is increased by 1 */ + uint32_t centroidResolution = (uint32_t)ptrWdConfig->xResolution + 1u; + uint32_t halfResolution = centroidResolution >> 1u; + uint32_t xPos = ptrInput->x; + uint32_t yPos = 0u; + cy_stc_capsense_position_t * ptrHistoryIndex = ptrHistory; + uint32_t filterCfg = ptrWdConfig->posFilterConfig; + uint32_t coeffIIR = (uint32_t)(filterCfg & CY_CAPSENSE_POSITION_IIR_COEFF_MASK) >> CY_CAPSENSE_POSITION_IIR_COEFF_OFFSET; + + if (0u != (filterCfg & CY_CAPSENSE_POSITION_MED_MASK)) + { + /* Get the filter history for further zero-cross correction */ + z1 = ptrHistoryIndex[0u].x; + z2 = ptrHistoryIndex[1u].x; + /* Preserve the filter history without zero-cross correction */ + ptrHistoryIndex[1u].x = ptrHistoryIndex[0u].x; + ptrHistoryIndex[0u].x = (uint16_t)xPos; + + /* Perform zero-cross correction */ + if (z1 > (halfResolution + xPos)) + { + xPos += centroidResolution; + } + if (xPos > (halfResolution + z1)) + { + z1 += centroidResolution; + z2 += centroidResolution; + } + if (z2 > (halfResolution + z1)) + { + z1 += centroidResolution; + xPos += centroidResolution; + } + if (z1 > (halfResolution + z2)) + { + z2 += centroidResolution; + } + + /* Perform filtering */ + xPos = Cy_CapSense_FtMedian(z2, z1, xPos); + /* Perform zero-cross correction of filtered position */ + if (xPos >= centroidResolution) + { + xPos -= centroidResolution; + } + ptrHistoryIndex++; + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_IIR_MASK)) + { + /* Perform zero-cross correction */ + if (ptrHistoryIndex->x > (halfResolution + xPos)) + { + xPos += centroidResolution; + } + if (xPos > (halfResolution + ptrHistoryIndex->x)) + { + ptrHistoryIndex->x += (uint16_t)centroidResolution; + } + if (ptrHistoryIndex->x > xPos) + { + temp = ptrHistoryIndex->x - xPos; + } + else + { + temp = xPos - ptrHistoryIndex->x; + } + + /* + * IIR filter can accumulate a delay up to a full circle and even more. + * This situation is not supported by the middleware. If the difference + * between the new position and IIR filter history is bigger than + * half of resolution, then all enabled position filters are reset. + */ + if(temp >= halfResolution) + { + /* Perform Initialization */ + Cy_CapSense_InitPositionFilters(filterCfg, ptrInput, ptrHistory); + } + else + { + /* Perform filtering */ + xPos = Cy_CapSense_FtIIR1stOrder(xPos, (uint32_t)ptrHistoryIndex->x, coeffIIR); + /* Perform zero-cross correction of filtered position */ + if (xPos >= centroidResolution) + { + xPos -= centroidResolution; + } + ptrHistoryIndex->x = (uint16_t)xPos; + } + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_AIIR_MASK)) + { + /* Perform zero-cross correction */ + if (ptrHistoryIndex->x > (halfResolution + xPos)) + { + xPos += centroidResolution; + } + if (xPos > (halfResolution + ptrHistoryIndex->x)) + { + ptrHistoryIndex->x += (uint16_t)centroidResolution; + } + if (ptrHistoryIndex->x > xPos) + { + temp = ptrHistoryIndex->x - xPos; + } + else + { + temp = xPos - ptrHistoryIndex->x; + } + + /* + * IIR filter can accumulate delay up to full circle and even more. + * This situation is not supported by the middleware. If the difference + * between the new position and IIR filter history is bigger than + * half of resolution, then all enabled position filters are reset. + */ + if(temp >= halfResolution) + { + /* Perform Initialization */ + Cy_CapSense_InitPositionFilters(filterCfg, ptrInput, ptrHistory); + } + else + { + /* Perform filtering */ + Cy_CapSense_AdaptiveFilterRun_Lib( + &ptrWdConfig->aiirConfig, + ptrHistoryIndex, + &xPos, + &yPos); + /* Perform zero-cross correction of filtered position */ + if (xPos >= centroidResolution) + { + xPos -= centroidResolution; + } + ptrHistoryIndex->x = (uint16_t)xPos; + } + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_AVG_MASK)) + { + temp = xPos; + /* Perform zero-cross correction */ + if (ptrHistoryIndex->x > (halfResolution + xPos)) + { + xPos += centroidResolution; + } + if (xPos > (halfResolution + ptrHistoryIndex->x)) + { + ptrHistoryIndex->x += (uint16_t)centroidResolution; + } + /* Perform filtering */ + xPos = (xPos + ptrHistoryIndex->x) >> 1u; + /* Perform zero-cross correction of filtered position */ + if (xPos >= centroidResolution) + { + xPos -= centroidResolution; + } + ptrHistoryIndex->x = (uint16_t)temp; + ptrHistoryIndex++; + } + if (0u != (filterCfg & CY_CAPSENSE_POSITION_JIT_MASK)) + { + /* Perform zero-cross correction */ + if (ptrHistoryIndex->x > (halfResolution + xPos)) + { + xPos += centroidResolution; + } + if (xPos > (halfResolution + ptrHistoryIndex->x)) + { + ptrHistoryIndex->x += (uint16_t)centroidResolution; + } + /* Perform filtering */ + xPos = Cy_CapSense_FtJitter(xPos, (uint32_t)ptrHistoryIndex->x); + /* Perform zero-cross correction of filtered position */ + if (xPos >= centroidResolution) + { + xPos -= centroidResolution; + } + ptrHistoryIndex->x = (uint16_t)xPos; + } + ptrInput->x = (uint16_t)xPos; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ProcessPositionFilters +****************************************************************************//** +* +* Performs filtering of touch positions applying enabled filters. +* +* \param newTouch +* The pointer to the touch structure. +* +* \param ptrHistory +* The pointer to the position structure that holds previous historical +* position values. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_ProcessPositionFilters( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + uint32_t posIndex; + uint32_t filterCfg; + uint32_t numPosMin; + uint32_t filterSize; + cy_stc_capsense_position_t * ptrHistory; + cy_stc_capsense_position_t * ptrPos; + uint32_t numPos = newTouch->numPosition; + + /* Position filtering */ + if ((CY_CAPSENSE_POSITION_NONE != numPos) && (CY_CAPSENSE_POSITION_MULTIPLE != numPos)) + { + filterCfg = ptrWdConfig->posFilterConfig; + numPosMin = ptrWdConfig->ptrPosFilterHistory->numPosition; + ptrPos = newTouch->ptrPosition; + ptrHistory = ptrWdConfig->ptrPosFilterHistory->ptrPosition; + filterSize = (filterCfg & CY_CAPSENSE_POSITION_FILTERS_SIZE_MASK) >> CY_CAPSENSE_POSITION_FILTERS_SIZE_OFFSET; + + /* The same actions should be done for cases with no touches or multiple touches */ + if (CY_CAPSENSE_POSITION_MULTIPLE == numPosMin) + { + numPosMin = CY_CAPSENSE_POSITION_NONE; + } + + /* Find number of position that exists from previous processing */ + if (numPosMin > numPos) + { + numPosMin = numPos; + } + + /* Process touches that exists from previous processing */ + + if((uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E == ptrWdConfig->wdType) + { + for (posIndex = 0u; posIndex < numPosMin; posIndex++) + { + Cy_CapSense_RunPositionFiltersRadial(ptrWdConfig, ptrPos, ptrHistory); + ptrPos++; + ptrHistory += filterSize; + } + } + else + { + for (posIndex = 0u; posIndex < numPosMin; posIndex++) + { + Cy_CapSense_RunPositionFilters(ptrWdConfig, ptrPos, ptrHistory); + ptrPos++; + ptrHistory += filterSize; + } + } + + /* Initialize all rest newly detected touches */ + for (; posIndex < numPos; posIndex++) + { + Cy_CapSense_InitPositionFilters(filterCfg, ptrPos, ptrHistory); + ptrPos++; + ptrHistory += filterSize; + } + } + /* Finally, copy number of positions */ + ptrWdConfig->ptrPosFilterHistory->numPosition = (uint8_t)numPos; +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_centroid.h b/cy_capsense_centroid.h new file mode 100644 index 0000000..8ca7296 --- /dev/null +++ b/cy_capsense_centroid.h @@ -0,0 +1,91 @@ +/***************************************************************************//** +* \file cy_capsense_centroid.h +* \version 1.1 +* +* \brief +* This file provides the function prototypes for the centroid calculation +* methods. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_CENTROID_H) +#define CY_CAPSENSE_CENTROID_H + +#include "cy_capsense_lib.h" +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************* +* Function Prototypes - internal functions +*******************************************************************************/ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_DpCentroidLinear( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpCentroidRadial( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpCentroidDiplex( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpCentroidTouchpad( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpAdvancedCentroidTouchpad( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpFindLocalMaxDd( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpCalcTouchPadCentroid( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpTouchTracking( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_DpFilterTouchRecord( + const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_InitPositionFilters( + uint32_t filterConfig, + const cy_stc_capsense_position_t * ptrInput, + cy_stc_capsense_position_t * ptrHistory); +void Cy_CapSense_RunPositionFilters( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_position_t * ptrInput, + cy_stc_capsense_position_t * ptrHistory); +void Cy_CapSense_RunPositionFiltersRadial( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_position_t * ptrInput, + cy_stc_capsense_position_t * ptrHistory); +void Cy_CapSense_ProcessPositionFilters( + cy_stc_capsense_touch_t * newTouch, + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +/** \} \endcond */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_CENTROID_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_common.h b/cy_capsense_common.h new file mode 100644 index 0000000..b1232b2 --- /dev/null +++ b/cy_capsense_common.h @@ -0,0 +1,388 @@ +/***************************************************************************//** +* \file cy_capsense_common.h +* \version 1.1 +* +* \brief +* This file provides the common CapSense definitions. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + + +#if !defined(CY_CAPSENSE_COMMON_H) +#define CY_CAPSENSE_COMMON_H + +#include "cy_device_headers.h" +#include "cy_sysint.h" + +#ifndef CY_IP_MXCSDV2 + #error "The CapSense middleware is not supported on this device" +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************************************* +* Macros +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_general *//** \{ */ +/******************************************************************************/ +/** Middleware major version */ +#define CY_CAPSENSE_MDW_VERSION_MAJOR 1 +/** Middleware minor version */ +#define CY_CAPSENSE_MDW_VERSION_MINOR 1 +/** Middleware ID */ +#define CY_CAPSENSE_MDW_ID (CY_PDL_DRV_ID(0x07uL)) + + +/* Scanning status */ +/** The CapSense middleware is busy */ +#define CY_CAPSENSE_SW_STS_BUSY (0x80u) +/** The CapSense middleware is not busy */ +#define CY_CAPSENSE_NOT_BUSY (0x00u) + +/** Feature enabled */ +#define CY_CAPSENSE_ENABLE (1u) +/** Feature disabled */ +#define CY_CAPSENSE_DISABLE (0u) + +/** Sensor active status mask */ +#define CY_CAPSENSE_SNS_TOUCH_STATUS_MASK (0x01u) +/** Proximity active status mask */ +#define CY_CAPSENSE_SNS_PROX_STATUS_MASK (0x02u) +/** Widget active status mask */ +#define CY_CAPSENSE_WD_ACTIVE_MASK (0x01u) +/** Widget disable status mask */ +#define CY_CAPSENSE_WD_DISABLE_MASK (0x02u) +/** Widget working status mask */ +#define CY_CAPSENSE_WD_WORKING_MASK (0x04u) +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_settings *//** \{ */ +/******************************************************************************/ +/* Sensing methods */ +/** CSD Sensing method */ +#define CY_CAPSENSE_CSD_SENSING_METHOD (0u) +/** CSX Sensing method */ +#define CY_CAPSENSE_CSX_SENSING_METHOD (1u) + +/* SmartSense modes */ +/** Manual tunning mode */ +#define CY_CAPSENSE_CSD_SS_DIS (0x00uL) +/** Hardware auto-tune mask */ +#define CY_CAPSENSE_CSD_SS_HW_EN (0x01uL) +/** Threshold auto-tune mask */ +#define CY_CAPSENSE_CSD_SS_TH_EN (0x02uL) +/** Full auto-tune is enabled */ +#define CY_CAPSENSE_CSD_SS_HWTH_EN (CY_CAPSENSE_CSD_SS_HW_EN | CY_CAPSENSE_CSD_SS_TH_EN) + +/* MFS macros */ +/** Number of multi-frequency scan channels */ +#define CY_CAPSENSE_FREQ_CHANNELS_NUM (3u) +/** Multi-frequency channel 0 constant */ +#define CY_CAPSENSE_MFS_CH0_INDEX (0u) +/** Multi-frequency channel 1 constant */ +#define CY_CAPSENSE_MFS_CH1_INDEX (1u) +/** Multi-frequency channel 2 constant */ +#define CY_CAPSENSE_MFS_CH2_INDEX (2u) + +/* Inactive sensor connection options */ +/** Inactive sensor connection to ground */ +#define CY_CAPSENSE_SNS_CONNECTION_GROUND (1u) +/** Inactive sensor connection to high-z */ +#define CY_CAPSENSE_SNS_CONNECTION_HIGHZ (2u) +/** Inactive sensor connection to shield */ +#define CY_CAPSENSE_SNS_CONNECTION_SHIELD (3u) + +/* Shield electrode delay macros */ +/** No shield signal delay */ +#define CY_CAPSENSE_SH_DELAY_0NS (0u) +/** Shield signal delay > 5 ns */ +#define CY_CAPSENSE_SH_DELAY_5NS (1u) +/** Shield signal delay > 10 ns */ +#define CY_CAPSENSE_SH_DELAY_10NS (2u) +/** Shield signal delay > 20 ns */ +#define CY_CAPSENSE_SH_DELAY_20NS (3u) + +/* Idac sensing configuration */ +/** Idac sourcing */ +#define CY_CAPSENSE_IDAC_SOURCING (0u) +/** Idac sinking */ +#define CY_CAPSENSE_IDAC_SINKING (1u) + +/* Shield tank capacitor pre-charge source options */ +/** Shield tank capacitor pre-charge from Vref */ +#define CY_CAPSENSE_CSH_PRECHARGE_VREF (0u) +/** Shield tank capacitor pre-charge from IO buffer */ +#define CY_CAPSENSE_CSH_PRECHARGE_IO_BUF (1u) + +/* Sense clock selection options */ +/** Auto-mode of clock source selection mask */ +#define CY_CAPSENSE_CLK_SOURCE_AUTO_MASK (0x80u) +/** Clock source direct */ +#define CY_CAPSENSE_CLK_SOURCE_DIRECT (0x00u) +/** Clock source SSC6 */ +#define CY_CAPSENSE_CLK_SOURCE_SSC6 (0x01u) +/** Clock source SSC7 */ +#define CY_CAPSENSE_CLK_SOURCE_SSC7 (0x02u) +/** Clock source SSC9 */ +#define CY_CAPSENSE_CLK_SOURCE_SSC9 (0x03u) +/** Clock source SSC10 */ +#define CY_CAPSENSE_CLK_SOURCE_SSC10 (0x04u) +/** Clock source PRS8 */ +#define CY_CAPSENSE_CLK_SOURCE_PRS8 (0x05u) +/** Clock source PRS12 */ +#define CY_CAPSENSE_CLK_SOURCE_PRS12 (0x06u) + +/* Initialization switch resistance options */ +/** Low switch resistance at initialization */ +#define CY_CAPSENSE_INIT_SW_RES_LOW (0x00000000uL) +/** Medium switch resistance at initialization */ +#define CY_CAPSENSE_INIT_SW_RES_MEDIUM (0x00000001uL) +/** High switch resistance at initialization */ +#define CY_CAPSENSE_INIT_SW_RES_HIGH (0x00000002uL) + +/* Scanning switch resistance options */ +/** Low switch resistance at scanning */ +#define CY_CAPSENSE_SCAN_SW_RES_LOW (0x00000000uL) +/** Medium switch resistance at scanning */ +#define CY_CAPSENSE_SCAN_SW_RES_MEDIUM (0x00000001uL) +/** High switch resistance at scanning */ +#define CY_CAPSENSE_SCAN_SW_RES_HIGH (0x00000002uL) + +/* CSD shield switch resistance options */ +/** Low shield switch resistance */ +#define CY_CAPSENSE_SHIELD_SW_RES_LOW (0x00000000uL) +/** Medium shield switch resistance */ +#define CY_CAPSENSE_SHIELD_SW_RES_MEDIUM (0x00000001uL) +/** High shield switch resistance */ +#define CY_CAPSENSE_SHIELD_SW_RES_HIGH (0x00000002uL) +/** Low-EMI shield switch resistance */ +#define CY_CAPSENSE_SHIELD_SW_RES_LOW_EMI (0x00000003uL) + +/* Vref source options */ +/** Vref source is taken from SRSS */ +#define CY_CAPSENSE_VREF_SRSS (0x00000000uL) +/** Vref source is taken from PASS */ +#define CY_CAPSENSE_VREF_PASS (0x00000001uL) + +/* Iref source options */ +/** Iref source is taken from SRSS */ +#define CY_CAPSENSE_IREF_SRSS (0x00000000uL) +/** Iref source is taken from PASS */ +#define CY_CAPSENSE_IREF_PASS (0x00000001uL) + +/* Position Filter Configuration */ +/** Mask of all filters enabling */ +#define CY_CAPSENSE_POSITION_FILTERS_MASK (0x000000FFu) +/** Median position filter enable mask */ +#define CY_CAPSENSE_POSITION_MED_MASK (0x00000001u) +/** IIR position filter enable mask */ +#define CY_CAPSENSE_POSITION_IIR_MASK (0x00000002u) +/** Adaptive IIR position filter enable mask */ +#define CY_CAPSENSE_POSITION_AIIR_MASK (0x00000004u) +/** Average position filter enable mask */ +#define CY_CAPSENSE_POSITION_AVG_MASK (0x00000008u) +/** Jitter position filter enable mask */ +#define CY_CAPSENSE_POSITION_JIT_MASK (0x00000010u) +/** Mask of position filters history size */ +#define CY_CAPSENSE_POSITION_FILTERS_SIZE_MASK (0x0000FF00u) +/** Offset of position filters history size */ +#define CY_CAPSENSE_POSITION_FILTERS_SIZE_OFFSET (8u) +/** Mask of IIR coefficient of position filter */ +#define CY_CAPSENSE_POSITION_IIR_COEFF_MASK (0x00FF0000u) +/** Offset of IIR coefficient of position filter */ +#define CY_CAPSENSE_POSITION_IIR_COEFF_OFFSET (16u) + +/* Raw count filter macros */ +/** Offset of raw count filter history size */ +#define CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_OFFSET (0u) +/** Offset of raw count median filter enable mask */ +#define CY_CAPSENSE_RC_FILTER_MEDIAN_EN_OFFSET (4u) +/** Offset of raw count median filter mode mask */ +#define CY_CAPSENSE_RC_FILTER_MEDIAN_MODE_OFFSET (5u) +/** Offset of raw count IIR filter enable mask */ +#define CY_CAPSENSE_RC_FILTER_IIR_EN_OFFSET (7u) +/** Offset of raw count IIR filter mode mask */ +#define CY_CAPSENSE_RC_FILTER_IIR_MODE_OFFSET (8u) +/** Offset of raw count average filter enable mask */ +#define CY_CAPSENSE_RC_FILTER_AVERAGE_EN_OFFSET (10u) +/** Offset of raw count average filter mode mask */ +#define CY_CAPSENSE_RC_FILTER_AVERAGE_MODE_OFFSET (11u) + +/** Mask of raw count filter history size */ +#define CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK ((uint16_t)((uint16_t)0x000Fu << CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_OFFSET)) +/** Median raw count filter enable mask */ +#define CY_CAPSENSE_RC_FILTER_MEDIAN_EN_MASK ((uint16_t)((uint16_t)0x0001u << CY_CAPSENSE_RC_FILTER_MEDIAN_EN_OFFSET)) +/** Median raw count filter mode mask */ +#define CY_CAPSENSE_RC_FILTER_MEDIAN_MODE_MASK ((uint16_t)((uint16_t)0x0003u << CY_CAPSENSE_RC_FILTER_MEDIAN_MODE_OFFSET)) +/** IIR raw count filter enable mask */ +#define CY_CAPSENSE_RC_FILTER_IIR_EN_MASK ((uint16_t)((uint16_t)0x0001u << CY_CAPSENSE_RC_FILTER_IIR_EN_OFFSET)) +/** IIR raw count filter mode mask */ +#define CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK ((uint16_t)((uint16_t)0x0003u << CY_CAPSENSE_RC_FILTER_IIR_MODE_OFFSET)) +/** Average raw count filter enable mask */ +#define CY_CAPSENSE_RC_FILTER_AVERAGE_EN_MASK ((uint16_t)((uint16_t)0x0001u << CY_CAPSENSE_RC_FILTER_AVERAGE_EN_OFFSET)) +/** Average raw count filter mode mask */ +#define CY_CAPSENSE_RC_FILTER_AVERAGE_MODE_MASK ((uint16_t)((uint16_t)0x0003u << CY_CAPSENSE_RC_FILTER_AVERAGE_MODE_OFFSET)) +/** All raw count filters enable mask */ +#define CY_CAPSENSE_RC_FILTER_ALL_EN_MASK (CY_CAPSENSE_RC_FILTER_MEDIAN_EN_MASK |\ + CY_CAPSENSE_RC_FILTER_IIR_EN_MASK |\ + CY_CAPSENSE_RC_FILTER_AVERAGE_EN_OFFSET) +/** Raw count IIR filter mode standard */ +#define CY_CAPSENSE_IIR_FILTER_STANDARD ((uint16_t)((uint16_t)1u << CY_CAPSENSE_RC_FILTER_IIR_MODE_OFFSET)) +/** Raw count IIR filter mode performance */ +#define CY_CAPSENSE_IIR_FILTER_PERFORMANCE ((uint16_t)((uint16_t)2u << CY_CAPSENSE_RC_FILTER_IIR_MODE_OFFSET)) +/** Raw count average filter mode */ +#define CY_CAPSENSE_AVERAGE_FILTER_LEN_4 ((uint16_t)((uint16_t)2u << CY_CAPSENSE_RC_FILTER_AVERAGE_MODE_OFFSET)) +/** \} */ + +/* Centroid configuration */ +/** Supported touch count mask */ +#define CY_CAPSENSE_CENTROID_NUMBER_MASK (0x0003u) +/** Diplex enable mask */ +#define CY_CAPSENSE_DIPLEXING_MASK (0x0004u) +/** Ballistic multiplier enable mask */ +#define CY_CAPSENSE_CENTROID_BALLISTIC_MASK (0x0008u) +/** 3x3 centroid enable mask */ +#define CY_CAPSENSE_CENTROID_3X3_MASK (0x0020u) +/** 5x5 centroid enable mask */ +#define CY_CAPSENSE_CENTROID_5X5_MASK (0x0040u) +/** Edge correction enable mask */ +#define CY_CAPSENSE_EDGE_CORRECTION_MASK (0x0080u) +/** +* Centroid calculation method mask +* * Direct provides correct calculation but worse linearity on edges +* and requires edge correction [MaxPosition / (numSns)] +* * Approximate provides better linearity on edges that leads to +* worse accuracy in general [MaxPosition / (numSns - 1u)] +*/ +#define CY_CAPSENSE_CALC_METHOD_MASK (0x0100u) + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_touch *//** \{ */ +/******************************************************************************/ +/** No touch detected */ +#define CY_CAPSENSE_POSITION_NONE (0x00u) +/** One finger touch detected */ +#define CY_CAPSENSE_POSITION_ONE (0x01u) +/** Two finger touches detected */ +#define CY_CAPSENSE_POSITION_TWO (0x02u) +/** Three finger touches detected */ +#define CY_CAPSENSE_POSITION_THREE (0x03u) +/** Multiple touches detected that exceed number of supported touches */ +#define CY_CAPSENSE_POSITION_MULTIPLE (0xFFu) +/** Maximum possible centroid number */ +#define CY_CAPSENSE_MAX_CENTROIDS (3u) +/** Maximum number of peaks in CSX Touchpad */ +#define CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS (5u) +/** Maximum age of a touch */ +#define CY_CAPSENSE_CSX_TOUCHPAD_MAX_AGE (0xFFu) +/** Undefined ID */ +#define CY_CAPSENSE_CSX_TOUCHPAD_ID_UNDEFINED (0x80u) +/** Non-assigned ID */ +#define CY_CAPSENSE_CSX_TOUCHPAD_ID_ABSENT (0x40u) +/** Touch below threshold ID */ +#define CY_CAPSENSE_CSX_TOUCHPAD_ID_ON_FAIL (0x20u) +/** Minimum ID */ +#define CY_CAPSENSE_CSX_TOUCHPAD_ID_MIN (0u) +/** Maximum ID */ +#define CY_CAPSENSE_CSX_TOUCHPAD_ID_MAX (7u) +/** ID mask */ +#define CY_CAPSENSE_CSX_TOUCHPAD_ID_MASK (0x00FFu) +/** Touch power mask */ +#define CY_CAPSENSE_CSX_TOUCHPAD_Z_MASK (0x00FFu) +/** Age mask */ +#define CY_CAPSENSE_CSX_TOUCHPAD_AGE_MASK (0xFF00u) +/** Debounce mask */ +#define CY_CAPSENSE_CSX_TOUCHPAD_DEBOUNCE_MASK (0xFF00u) +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_process *//** \{ */ +/******************************************************************************/ +/** Applies all enabled filters in the default order to the raw counts */ +#define CY_CAPSENSE_PROCESS_FILTER (0x01u) +/** Updates baselines using current raw count values for the widget/sensor */ +#define CY_CAPSENSE_PROCESS_BASELINE (0x02u) +/** Calculates differences for the widget/sensor */ +#define CY_CAPSENSE_PROCESS_DIFFCOUNTS (0x04u) +/** Runs the noise envelope filter to measure noise magnitude for the widget/sensor */ +#define CY_CAPSENSE_PROCESS_CALC_NOISE (0x08u) +/** Updates widget thresholds based on raw counts noise magnitude */ +#define CY_CAPSENSE_PROCESS_THRESHOLDS (0x10u) +/** Runs the widget-specific processing algorithms and updates it status */ +#define CY_CAPSENSE_PROCESS_STATUS (0x20u) +/** Definition that combines all possible processing tasks */ +#define CY_CAPSENSE_PROCESS_ALL (CY_CAPSENSE_PROCESS_FILTER | \ + CY_CAPSENSE_PROCESS_BASELINE | \ + CY_CAPSENSE_PROCESS_DIFFCOUNTS | \ + CY_CAPSENSE_PROCESS_CALC_NOISE | \ + CY_CAPSENSE_PROCESS_THRESHOLDS | \ + CY_CAPSENSE_PROCESS_STATUS) +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_pin *//** \{ */ +/******************************************************************************/ +/** Connection of pin to ground */ +#define CY_CAPSENSE_GROUND (0u) +/** Connection of pin to high-z */ +#define CY_CAPSENSE_HIGHZ (1u) +/** Configuring of pin as a shield */ +#define CY_CAPSENSE_SHIELD (2u) +/** Configuring of pin as a CSD sensor */ +#define CY_CAPSENSE_SENSOR (3u) +/** Configuring of pin as a Tx */ +#define CY_CAPSENSE_TX_PIN (4u) +/** Configuring of pin as a Rx */ +#define CY_CAPSENSE_RX_PIN (5u) +/** Pin is not connected to scanning bus */ +#define CY_CAPSENSE_SNS_DISCONNECTED (0u) +/** Pin is connected to scanning bus */ +#define CY_CAPSENSE_SNS_CONNECTED (1u) +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_miscellaneous *//** \{ */ +/******************************************************************************/ +/** Defines the communication command complete bit mask */ +#define CY_CAPSENSE_TU_CMD_COMPLETE_BIT (0x8000u) +/** Defines the status if restart was not performed in Cy_CapSense_RunTuner() */ +#define CY_CAPSENSE_STATUS_RESTART_NONE (0x00u) +/** Defines the status if restart was done in Cy_CapSense_RunTuner() */ +#define CY_CAPSENSE_STATUS_RESTART_DONE (0x01u) +/** Number of supported idac gains */ +#define CY_CAPSENSE_IDAC_GAIN_NUMBER (6u) +/** 100% value */ +#define CY_CAPSENSE_PERCENTAGE_100 (100u) +/* Scope of scanning macros */ +/** Sensor scanning scope is undefined */ +#define CY_CAPSENSE_SCAN_SCOPE_UND (0u) +/** Sensor scanning scope is a single sensor */ +#define CY_CAPSENSE_SCAN_SCOPE_SGL_SNS (1u) +/** Sensor scanning scope is all sensors in a queue */ +#define CY_CAPSENSE_SCAN_SCOPE_ALL_SNS (2u) +/** Widget scanning scope is a single widget */ +#define CY_CAPSENSE_SCAN_SCOPE_SGL_WD (0u) +/** Widget scanning scope is all widgets */ +#define CY_CAPSENSE_SCAN_SCOPE_ALL_WD (1u) + +/** \} */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_COMMON_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_control.c b/cy_capsense_control.c new file mode 100644 index 0000000..f7ffa47 --- /dev/null +++ b/cy_capsense_control.c @@ -0,0 +1,1243 @@ +/***************************************************************************//** +* \file cy_capsense_control.c +* \version 1.1 +* +* \brief +* This file provides the source code to the Control module functions. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include +#include "cy_syslib.h" +#include "cy_syspm.h" +#include "cy_csd.h" +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_control.h" +#include "cy_capsense_processing.h" +#include "cy_capsense_filter.h" +#include "cy_capsense_sensing.h" +#include "cy_capsense_tuner.h" + + +/******************************************************************************* +* Function Name: Cy_CapSense_Init +****************************************************************************//** +* +* Captures the CSD HW block and configures it to the default state. This function is +* called by the application program prior to calling any other function of the +* middleware. +* +* The following tasks are executed: +* 1. Capturing the CSD HW block if it is not in use. If the CSD HW block is +* already in use, then the function returns fail status. In this case, +* the application program should perform corresponding actions like releasing +* the CSD HW block captured by other middleware. +* 2. If the CSD HW block was captured this function configures it to the +* default state. +* +* After the middleware is configured using Cy_CapSense_Init() function, +* application program should configure and enable the CSD block interrupt, +* and then call of the Cy_CapSense_Enable() function to complete the +* middleware initialization process. +* See the function usage example below for more details. +* +* When the middleware operation is stopped by the Cy_CapSense_DeInit() +* function, subsequent call of the Cy_CapSense_Init() function repeats +* initialization process and it is not needed to call the Cy_CapSense_Enable() +* function second time. However, to implement time-multiplexed mode +* (sharing the CSD HW Block between multiple middleware) +* the Cy_CapSense_Save() and Cy_CapSense_Restore() functions should be used +* instead of the Cy_CapSense_DeInit() and Cy_CapSense_Init() functions for +* further compatibility. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t +* generated by the CapSense Configurator tool. The structure contains both, CapSense +* configuration and internal data and it is used during whole CapSense operation. +* +* \return +* Returns the status of the initialization process. If CY_RET_SUCCESS is not +* received, some of the initialization fails, the middleware may not operate +* as expected, and repeating of initialization is required. +* +* \funcusage +* +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Initialization +* The 'cy_capsense_context' variable that is used as the parameter of the +* Cy_CapSense_Init() and Cy_CapSense_Enable() functions is declared in the +* cycfg_capsense.h file. +* +* The CapSense_ISR_cfg variable should be declared by the application +* program according to the examples below:
+* For CM0+ core: +* \snippet capsense\1.1\snippet\main.c snippet_m0p_capsense_interrupt_source_declaration +* +* For CM4 core: +* \snippet capsense\1.1\snippet\main.c snippet_m4_capsense_interrupt_source_declaration +* +* The CapSense interrupt handler should be declared by the application program +* according to the example below: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_IntHandler +* +* The CapSense_HW is the pointer to the base register address of +* the CSD HW block. A macro for the pointer can be found in cycfg_peripherals.h +* file defined as \_HW. If no name specified then +* the default name is used csd_\_csd_\_HW. +* +*******************************************************************************/ +cy_status Cy_CapSense_Init(cy_stc_capsense_context_t * context) +{ + cy_status result = CY_RET_BAD_PARAM; + + if (NULL != context) + { + result = Cy_CapSense_Restore(context); + + /* The 25us interval is required for settling analog part of the CSD HW block. */ + Cy_SysLib_DelayUs(CY_CAPSENSE_ANALOG_SETTLING_TIME_US); + } + + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Enable +****************************************************************************//** +* +* Initializes the CapSense firmware modules. +* +* This function requires the Cy_CapSense_Init() function is called and +* the CSD HW block interrupt to be configured prior to calling this function. +* See the function usage example below for details on usage. +* +* The following are executed as part of the function: +* 1. Check CapSense configuration integrity. +* 2. Pre-calculate of internal register values to speed up operation. +* 3. Configure the CSD HW block to perform capacitive sensing operation. +* 4. If SmartSense Auto-tuning is selected for the CSD Tuning mode in the +* Basic tab, the auto-tuning algorithm is executed to set the optimal +* values for the CSD HW block parameters of the widgets/sensors. +* 5. Calibrate the sensors and find the optimal values for IDACs of each +* widget/sensor, if the Enable IDAC auto-calibration is enabled in the +* CSD Setting or CSX Setting tabs. +* 5. Perform scanning for all the sensors and initialize the baseline history. +* 6. If the firmware filters are enabled in the Advanced General tab, the +* filter histories are also initialized. +* +* Any subsequent call of this function repeats initialization process. +* Therefore, it is possible to change the middleware configuration +* from the application program by writing registers to the data structure +* and calling this function again. +* +* The repeated call of this function is also done inside the +* Cy_CapSense_RunTuner() function when a restart command is received. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the initialization process. If CY_RET_SUCCESS is not +* received, some of the initialization fails. +* +* \funcusage +* +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Initialization +* The 'cy_capsense_context' variable that is used as the parameter of the +* Cy_CapSense_Init() and Cy_CapSense_Enable() functions is declared in the +* cycfg_capsense.h file. +* +* The CapSense_ISR_cfg variable should be declared by the application +* program according to the examples below:
+* For CM0+ core: +* \snippet capsense\1.1\snippet\main.c snippet_m0p_capsense_interrupt_source_declaration +* +* For CM4 core: +* \snippet capsense\1.1\snippet\main.c snippet_m4_capsense_interrupt_source_declaration +* +* The CapSense interrupt handler should be declared by the application program +* according to the example below: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_IntHandler +* +* The CapSense_HW is the pointer to the base register address of +* the CSD HW block. A macro for the pointer can be found in cycfg_peripherals.h +* file defined as \_HW. If no name is specified then +* the default name is used csd_\_csd_\_HW. +* +*******************************************************************************/ +cy_status Cy_CapSense_Enable(cy_stc_capsense_context_t * context) +{ + cy_status result; + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + + /* Approximate duration of Wait For Init loop */ + const uint32_t isBusyLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t isBusyWatchdogTimeUs = 1000000uL; + + /* Initialize CapSense modules */ + result = Cy_CapSense_Initialize(context); + + if(CY_RET_SUCCESS == result) + { + if (CY_CAPSENSE_CSD_SS_DIS != context->ptrCommonConfig->csdAutotuneEn) + { + result |= Cy_CapSense_SsAutoTune(context); + } + + if ((CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdEn) && + (CY_CAPSENSE_CSD_SS_DIS == context->ptrCommonConfig->csdAutotuneEn) && + (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacAutocalEn)) + { + result |= Cy_CapSense_CalibrateAllCsdWidgets(context); + } + + if((CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) && + (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxIdacAutocalEn)) + { + result |= Cy_CapSense_CalibrateAllCsxWidgets(context); + } + + + result |= Cy_CapSense_ScanAllWidgets(context); + /* Init Watchdog Counter to prevent a hang */ + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(isBusyWatchdogTimeUs, cpuFreqMHz, isBusyLoopDuration); + + while(CY_CAPSENSE_NOT_BUSY != Cy_CapSense_IsBusy(context)) + { + if(0uL == watchdogCounter) + { + break; + } + + watchdogCounter--; + } + } + + Cy_CapSense_InitializeAllFilters(context); + Cy_CapSense_InitializeAllBaselines(context); + + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Initialize +****************************************************************************//** +* +* Initializes all sub-modules of the CapSense middleware. +* +* The initialization includes: +* - Data Structure - set the default middleware parameters based +* on configuration. +* - Data Processing - resets the status all widgets. +* - Tuner - resets the tuner communication state. +* - Sensing - prepares the CSD HW block for operation. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Return CY_RET_SUCCESS if the initialization was successful. +* +*******************************************************************************/ +cy_status Cy_CapSense_Initialize(cy_stc_capsense_context_t * context) +{ + cy_status result = CY_RET_INVALID_STATE; + + result = Cy_CapSense_CheckConfigIntegrity(context); + if (CY_RET_SUCCESS == result) + { + /* The Tuner is initialized only once */ + if (CY_CAPSENSE_INIT_NEEDED == context->ptrCommonContext->initDone) + { + Cy_CapSense_TuInitialize(context); + context->ptrCommonContext->initDone = CY_CAPSENSE_INIT_DONE; + } + + Cy_CapSense_InitializeAllStatuses(context); + result = Cy_CapSense_SsInitialize(context); + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DeInit +****************************************************************************//** +* +* Stops the middleware operation and releases the CSD HW block. +* +* No sensor scanning can be executed when the middleware is stopped. +* This function should be called only when no scanning is in progress. +* I.e. Cy_CapSense_IsBusy() returns a non-busy status. +* +* After it is stopped, the CSD HW block may be reconfigured by the +* application program or other middleware for any other usage. +* +* When the middleware operation is stopped by the Cy_CapSense_DeInit() +* function, subsequent call of the Cy_CapSense_Init() function repeats +* initialization process and it is not needed to call the Cy_CapSense_Enable() +* function second time. However, to implement time-multiplexed mode +* (sharing the CSD HW Block between multiple middleware) +* the Cy_CapSense_Save() and Cy_CapSense_Restore() functions should be used +* instead of the Cy_CapSense_DeInit() and Cy_CapSense_Init() functions for +* further compatibility. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the stop process. If CY_RET_SUCCESS is not received, +* the stop process fails and retries may be required. +* +*******************************************************************************/ +cy_status Cy_CapSense_DeInit(cy_stc_capsense_context_t * context) +{ + cy_status result; + + result = Cy_CapSense_Save(context); + if (CY_RET_SUCCESS != result) + { + result = CY_RET_BAD_DATA; + } + else + { + context->ptrCommonContext->initDone = CY_CAPSENSE_INIT_NEEDED; + } + + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ProcessAllWidgets +****************************************************************************//** +* +* Performs full data processing of all enabled widgets. +* +* This function performs all data processes for all enabled widgets and +* sensors in the middleware to produce meaningful status output from widgets +* and sensors. The following tasks are executed as part of processing all the +* widgets: +* 1. Apply raw count filters to the raw counts, if they are enabled. +* 2. Update the thresholds if the SmartSense Full Auto-Tuning is enabled. +* 3. Update the baselines and difference counts for all the sensors. +* 4. Update the sensor and widget output status. Updates on/off status for +* buttons and proximity widgets, centroid/position for +* the sliders and the X/Y position for the touchpads. +* +* This function is called by the application program only after all the enabled +* widgets (and sensors) in the middleware are scanned. Calling this function +* multiple times without sensor scanning causes unexpected behavior. +* +* The disabled widgets are not processed by this function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the processing operation. If CY_RET_SUCCESS is not received, +* the processing fails and retries may be required. +* +*******************************************************************************/ +cy_status Cy_CapSense_ProcessAllWidgets(cy_stc_capsense_context_t * context) +{ + uint32_t wdIndex; + cy_status result = CY_RET_SUCCESS; + + for (wdIndex = context->ptrCommonConfig->numWd; wdIndex-- > 0u;) + { + result |= Cy_CapSense_ProcessWidget(wdIndex, context); + } + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ProcessWidget +****************************************************************************//** +* +* Performs full data processing of the specified widget if it is enabled. +* +* This function performs exactly the same tasks as +* Cy_CapSense_ProcessAllWidgets(), but only for a specified widget. This +* function can be used along with the Cy_CapSense_SetupWidget() and +* Cy_CapSense_Scan() functions to scan and process data for a specific +* widget. This function is called only after all the sensors in the +* widgets are scanned. A disabled widget is not processed by this function. +* +* A pipeline scan method (i.e. during scanning of a widget performing processing +* of the previously scanned widget) can be implemented using this function and +* it may reduce the total execution time, increase the refresh rate and +* decrease the average power consumption. +* +* A pipeline scan method (i.e. during scanning of a current widget (N), +* perform processing of the previously scanned widget (N-1)) can be +* implemented using this function and it may reduce the total execution time, +* increase the refresh rate, and decrease the average power consumption. +* See the function usage example below for details on usage. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the widget processing: +* - CY_RET_SUCCESS - The operation is successfully completed +* - CY_RET_BAD_PARAM - The input parameter is invalid +* - CY_RET_INVALID_STATE - The specified widget is disabled +* - CY_RET_BAD_DATA - The processing is failed +* +* \funcusage +* +* An example of pipeline implementation: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_ProcessWidget +* +*******************************************************************************/ +cy_status Cy_CapSense_ProcessWidget(uint32_t widgetId, cy_stc_capsense_context_t * context) +{ + cy_status result = CY_RET_BAD_PARAM; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + + /* Check parameter validity */ + if (widgetId < context->ptrCommonConfig->numWd) + { + ptrWdCfg = &context->ptrWdConfig[widgetId]; + + /* Check widget enable status */ + if (0u == (ptrWdCfg->ptrWdContext->status & CY_CAPSENSE_WD_DISABLE_MASK)) + { + switch(ptrWdCfg->senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + result = Cy_CapSense_DpProcessCsdWidgetRawCounts(ptrWdCfg, context); + Cy_CapSense_DpProcessCsdWidgetStatus(ptrWdCfg, context); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + result = Cy_CapSense_DpProcessCsxWidgetRawCounts(ptrWdCfg, context); + Cy_CapSense_DpProcessCsxWidgetStatus(ptrWdCfg, context); + break; + + default: + CY_ASSERT(0 != 0); + break; + } + } + else + { + result = CY_RET_INVALID_STATE; + } + } + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ProcessWidgetExt +****************************************************************************//** +* +* Performs customized data processing on the selected widget. +* +* This function performs customized data processing specified by the mode +* parameter on a widget. This function can be used with any of the +* available scan functions. This function should be called only after all +* the sensors in the specified widget are scanned. Calling this function +* multiple times with the same mode without new sensor scan causes +* unexpected behavior. This function ignores the value of the +* wdgtEnable register. +* +* The CY_CAPSENSE_PROCESS_CALC_NOISE and CY_CAPSENSE_PROCESS_THRESHOLDS masks +* for mode parameter are supported only when SmartSense is enabled for +* CSD widgets. +* +* The execution order of processing tasks starts from LSB to MSB of the +* mode parameter. To implement a different order of execution, call this +* function multiple times with the required mode parameter. +* +* For more details, refer to function usage example below. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param mode +* Specifies the type of widget processing to be executed for the +* specified widget: +* 1. Bits [31..6] - Reserved. +* 2. Bits [5..0] - CY_CAPSENSE_PROCESS_ALL - Execute all of the below tasks. +* 3. Bit [5] - CY_CAPSENSE_PROCESS_STATUS - Update the status +* (on/off, centroid position). +* 4. Bit [4] - CY_CAPSENSE_PROCESS_THRESHOLDS - Update the thresholds +* (only in CSD auto-tuning mode). +* 5. Bit [3] - CY_CAPSENSE_PROCESS_CALC_NOISE - Calculate the noise +* (only in CSD auto-tuning mode). +* 6. Bit [2] - CY_CAPSENSE_PROCESS_DIFFCOUNTS - Update the difference +* counts of each sensor. +* 7. Bit [1] - CY_CAPSENSE_PROCESS_BASELINE - Update the baselines +* for all sensor. +* 8. Bit [0] - CY_CAPSENSE_PROCESS_FILTER - Run the firmware filters +* on sensor rawcounts. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the widget processing operation: +* - CY_RET_SUCCESS - The processing is successfully performed. +* - CY_RET_BAD_PARAM - The input parameter is invalid. +* - CY_RET_BAD_DATA - The processing failed. +* +* \funcusage +* +* An example of customized data processing, changed processing order: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_ProcessWidgetExt +* +*******************************************************************************/ +cy_status Cy_CapSense_ProcessWidgetExt( + uint32_t widgetId, + uint32_t mode, + cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + cy_status result = CY_RET_BAD_PARAM; + uint32_t snsHistorySize; + uint32_t freqChIndex; + uint32_t freqChNumber; + uint16_t * ptrHistoryCh; + uint16_t * ptrHistorySns; + uint8_t * ptrHistoryLowCh = NULL; + uint8_t * ptrHistoryLowSns = NULL; + cy_stc_capsense_sensor_context_t * ptrSnsCxtCh; + cy_stc_capsense_sensor_context_t * ptrSnsCxtSns; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + + + /* Check parameter validity */ + if (widgetId < context->ptrCommonConfig->numWd) + { + ptrWdCfg = &context->ptrWdConfig[widgetId]; + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + + ptrSnsCxtCh = &ptrWdCfg->ptrSnsContext[0u]; + ptrHistoryCh = &ptrWdCfg->ptrRawFilterHistory[0u]; + if(CY_CAPSENSE_IIR_FILTER_PERFORMANCE == (ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + ptrHistoryLowCh = &ptrWdCfg->ptrRawFilterHistoryLow[0u]; + } + + + switch(ptrWdCfg->senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + + /* Run the desired processing for the all CSD widget sensors */ + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrSnsCxtSns = ptrSnsCxtCh; + ptrHistorySns = ptrHistoryCh; + ptrHistoryLowSns = ptrHistoryLowCh; + for (snsIndex = 0uL; snsIndex < ptrWdCfg->numSns; snsIndex++) + { + result = Cy_CapSense_DpProcessCsdSensorRawCountsExt(ptrWdCfg, ptrSnsCxtSns, ptrHistorySns, ptrHistoryLowSns, mode, context); + + ptrSnsCxtSns++; + ptrHistorySns += snsHistorySize; + if(NULL != ptrHistoryLowSns) + { + ptrHistoryLowSns++; + } + + } + + ptrSnsCxtCh += context->ptrCommonConfig->numSns; + ptrHistoryCh += context->ptrCommonConfig->numSns * snsHistorySize; + if(NULL != ptrHistoryLowCh) + { + ptrHistoryLowCh += context->ptrCommonConfig->numSns; + } + + } + + if(CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) + { + ptrSnsCxtSns = ptrWdCfg->ptrSnsContext; + for (snsIndex = ptrWdCfg->numSns; snsIndex-- > 0u;) + { + Cy_CapSense_RunMfsFiltering(ptrSnsCxtSns, context); + ptrSnsCxtSns++; + } + } + + if (0u != (mode & CY_CAPSENSE_PROCESS_STATUS)) + { + Cy_CapSense_DpProcessCsdWidgetStatus(ptrWdCfg, context); + } + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + + /* Run the desired processing for the all CSX widget sensors */ + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrSnsCxtSns = ptrSnsCxtCh; + ptrHistorySns = ptrHistoryCh; + ptrHistoryLowSns = ptrHistoryLowCh; + for (snsIndex = 0uL; snsIndex < ptrWdCfg->numSns; snsIndex++) + { + result = Cy_CapSense_DpProcessCsxSensorRawCountsExt(ptrWdCfg, ptrSnsCxtSns, ptrHistorySns, ptrHistoryLowSns, mode, context); + + ptrSnsCxtSns++; + ptrHistorySns += snsHistorySize; + if(NULL != ptrHistoryLowSns) + { + ptrHistoryLowSns++; + } + + } + + ptrSnsCxtCh += context->ptrCommonConfig->numSns; + ptrHistoryCh += context->ptrCommonConfig->numSns * snsHistorySize; + if(NULL != ptrHistoryLowCh) + { + ptrHistoryLowCh += context->ptrCommonConfig->numSns; + } + + } + + if(CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) + { + ptrSnsCxtSns = ptrWdCfg->ptrSnsContext; + for (snsIndex = ptrWdCfg->numSns; snsIndex-- > 0u;) + { + Cy_CapSense_RunMfsFiltering(ptrSnsCxtSns, context); + ptrSnsCxtSns++; + } + } + + if (0u != (mode & CY_CAPSENSE_PROCESS_STATUS)) + { + Cy_CapSense_DpProcessCsxWidgetStatus(ptrWdCfg, context); + } + break; + + default: + CY_ASSERT(0 != 0); + break; + } + } + return result; +} + +/******************************************************************************* +* Function Name: Cy_CapSense_ProcessSensorExt +****************************************************************************//** +* +* Performs customized data processing on the selected sensor. +* +* This function performs customized data processing specified by the mode +* parameter on a sensor. This function performs the exact same task +* of the Cy_CapSense_ProcessWidgetExt() function but only on the specified +* sensor instead of all sensors in the widget. +* +* The pipeline scan method (i.e. during scanning of a sensor, processing +* of a previously scanned sensor is performed) can be implemented using this +* function and it may reduce the total scan/process time, increase the refresh +* rate, and decrease the power consumption. For more details, refer to +* function usage example below. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param mode +* Specifies the type of the sensor processing that must be executed for the +* specified sensor: +* 1. Bits [31..5] - Reserved +* 2. Bits [4..0] - CY_CAPSENSE_PROCESS_ALL - Executes all the tasks +* 3. Bit [4] - CY_CAPSENSE_PROCESS_THRESHOLDS - Updates the thresholds +* (only in auto-tuning mode) +* 4. Bit [3] - CY_CAPSENSE_PROCESS_CALC_NOISE - Calculates the noise +* (only in auto-tuning mode) +* 5. Bit [2] - CY_CAPSENSE_PROCESS_DIFFCOUNTS - Updates the diff count +* 6. Bit [1] - CY_CAPSENSE_PROCESS_BASELINE - Updates the baseline +* 7. Bit [0] - CY_CAPSENSE_PROCESS_FILTER - Runs the firmware filters +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the sensor process operation: +* - CY_RET_SUCCESS - The processing is successfully performed. +* - CY_RET_BAD_PARAM - The input parameter is invalid. +* - CY_RET_BAD_DATA - The processing failed. +* +* \funcusage +* +* An example demonstrates pipeline implementation of sensor scanning and +* processing: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_ProcessSensorExt +* +*******************************************************************************/ +cy_status Cy_CapSense_ProcessSensorExt( + uint32_t widgetId, + uint32_t sensorId, + uint32_t mode, + const cy_stc_capsense_context_t * context) +{ + cy_status result = CY_RET_BAD_PARAM; + + uint32_t freqChIndex; + uint32_t freqChNumber; + uint32_t snsHistorySize; + uint32_t cxtOffset; + uint32_t historyOffset; + + uint16_t * ptrHistory; + uint8_t * ptrHistoryLow = NULL; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + + if (widgetId < context->ptrCommonConfig->numWd) + { + ptrWdCfg = &context->ptrWdConfig[widgetId]; + if (sensorId < ptrWdCfg->numSns) + { + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + ptrHistory = &ptrWdCfg->ptrRawFilterHistory[sensorId * snsHistorySize]; + if((uint32_t)CY_CAPSENSE_IIR_FILTER_PERFORMANCE == ((uint32_t)ptrWdCfg->rawFilterConfig & (uint32_t)CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + ptrHistoryLow = &ptrWdCfg->ptrRawFilterHistoryLow[sensorId]; + } + + ptrSnsCxt = &ptrWdCfg->ptrSnsContext[sensorId]; + cxtOffset = context->ptrCommonConfig->numSns; + historyOffset = snsHistorySize * context->ptrCommonConfig->numSns; + + switch(ptrWdCfg->senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + result = Cy_CapSense_DpProcessCsdSensorRawCountsExt( + ptrWdCfg, + ptrSnsCxt, + ptrHistory, + ptrHistoryLow, + mode, context); + ptrSnsCxt += cxtOffset; + ptrHistory += historyOffset; + ptrHistoryLow += cxtOffset; + } + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + result = Cy_CapSense_DpProcessCsxSensorRawCountsExt( + ptrWdCfg, + ptrSnsCxt, + ptrHistory, + ptrHistoryLow, + mode, context); + ptrSnsCxt += cxtOffset; + ptrHistory += historyOffset; + ptrHistoryLow += cxtOffset; + } + break; + + default: + CY_ASSERT(0 != 0); + break; + } + + if(CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) + { + ptrSnsCxt = ptrWdCfg->ptrSnsContext; + Cy_CapSense_RunMfsFiltering(ptrSnsCxt, context); + } + + result = CY_RET_SUCCESS; + } + } + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Wakeup +****************************************************************************//** +* +* Resumes the middleware after Deep Sleep. +* +* This function is used to resume the middleware operation after exiting +* Deep Sleep. In Deep Sleep power mode, the CSD HW block is powered off +* and an extra delay is required to establish correct operation of +* the CSD HW block. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_Wakeup(const cy_stc_capsense_context_t * context) +{ + Cy_SysLib_DelayUs((uint16_t)context->ptrCommonConfig->analogWakeupDelay); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DeepSleepCallback +****************************************************************************//** +* +* Handles Active to Deep Sleep power mode transition for the CapSense +* middleware. +* +* Calling this function directly from the application program is not recommended. +* Instead, Cy_SysPm_DeepSleep() should be used for the Active to Deep Sleep +* power mode transition of the device. +* +* For proper operation of the CapSense middleware during the Active to +* Deep Sleep mode transition, a callback to this function should be registered +* using the Cy_SysPm_RegisterCallback() function with CY_SYSPM_DEEPSLEEP +* type. After the callback is registered, this function is called by the +* Cy_SysPm_DeepSleep() function to prepare the middleware to the device +* power mode transition. +* +* When this function is called with CY_SYSPM_CHECK_READY as input, this +* function returns CY_SYSPM_SUCCESS if no scanning is in progress. Otherwise +* CY_SYSPM_FAIL is returned. If CY_SYSPM_FAIL status is returned, a device +* cannot change the power mode without completing the current scan as +* a transition to Deep Sleep during the scan can disrupt the middleware +* operation. +* +* For details of SysPm types and macros refer to +* SysPm API Reference. +* +* \param callbackParams +* Refer to the description of the cy_stc_syspm_callback_params_t type in the +* Peripheral Driver Library documentation. +* +* \param mode +* Specifies mode cy_en_syspm_callback_mode_t. +* +* \return +* Returns the status cy_en_syspm_status_t of the operation requested +* by the mode parameter: +* - CY_SYSPM_SUCCESS - Deep Sleep power mode can be entered. +* - CY_SYSPM_FAIL - Deep Sleep power mode cannot be entered. +* +*******************************************************************************/ +cy_en_syspm_status_t Cy_CapSense_DeepSleepCallback( + cy_stc_syspm_callback_params_t * callbackParams, + cy_en_syspm_callback_mode_t mode) +{ + cy_en_syspm_status_t retVal = CY_SYSPM_SUCCESS; + cy_en_csd_key_t mwKey; + cy_stc_capsense_context_t * capsenseCxt = (cy_stc_capsense_context_t *)callbackParams->context; + + if (CY_SYSPM_CHECK_READY == mode) + { + mwKey = Cy_CSD_GetLockStatus(capsenseCxt->ptrCommonConfig->ptrCsdBase, capsenseCxt->ptrCommonConfig->ptrCsdContext); + + if (CY_CSD_CAPSENSE_KEY == mwKey) + { + if (CY_CAPSENSE_NOT_BUSY != Cy_CapSense_IsBusy(capsenseCxt)) + { + retVal = CY_SYSPM_FAIL; + } + } + } + + return(retVal); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_IncrementGestureTimestamp +****************************************************************************//** +* +* Increments the timestamp register for the predefined timestamp interval. +* +* A timestamp is required for operation of the Gesture and Ballistic multiplier +* feature. Hence this function and timestamp is required only if the Gesture +* detection or Ballistic multiplier feature is enabled. +* +* This function increments the timestamp by the interval specified +* in the context->ptrCommonContext->timestampInterval register. The unit for +* the timestamp and timestamp interval is milliseconds and the default value of the +* interval is 1. +* +* The application program must periodically call this +* function or register a periodic callback to this function to keep the +* timestamp updated and operational for the operation of the Gesture and +* Ballistic multiplier feature. +* +* The timestamp can be updated in one of the three methods: +* 1. Register a periodic callback for the +* Cy_CapSense_IncrementGestureTimestamp() function. +* 2. Periodically call the Cy_CapSense_IncrementGestureTimestamp() function +* from the application program. +* 3. Directly modify the timestamp using the +* Cy_CapSense_SetGestureTimestamp() function. +* +* See the function usage example below for more details. +* +* The interval at which this function is called should match with interval +* defined in context->ptrCommonContext->timestampInterval register. Either the +* register value can be updated to match the callback interval or the callback +* can be made at interval set in the register. +* +* If a timestamp is available from another source, the application program +* may choose to periodically update the timestamp by using the +* Cy_CapSense_SetGestureTimestamp() function instead of +* registering a callback. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of timestamp updating: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Timestamp +* +*******************************************************************************/ +void Cy_CapSense_IncrementGestureTimestamp(cy_stc_capsense_context_t * context) +{ + context->ptrCommonContext->timestamp += + context->ptrCommonContext->timestampInterval; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetGestureTimestamp +****************************************************************************//** +* +* Rewrites the timestamp register by the specified value. +* +* This function writes the specified value into the middleware timestamp +* context->ptrCommonContext->timestamp register. +* +* If a timestamp is available from another source, the application program +* may choose to periodically update the timestamp by using this function +* instead of registering a callback. +* +* Do not modify the timestamp arbitrarily or simultaneously use with +* the Cy_CapSense_IncrementGestureTimestamp() function, which may result in +* unexpected result. +* +* \param value +* Specifies the timestamp value (in ms). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SetGestureTimestamp( + uint32_t value, + cy_stc_capsense_context_t * context) +{ + context->ptrCommonContext->timestamp = value; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Restore +****************************************************************************//** +* +* Resumes the middleware operation if the Cy_CapSense_Save() function was +* called previously. +* +* This function, along with the Cy_CapSense_Save() function is specifically +* designed for ease of use and supports time multiplexing of the CSD HW block +* among multiple middlewares. When the CSD HW block is shared by two or more +* middlewares, this function can be used to restore the previous state of +* the CSD HW block and CapSense middleware saved using the +* Cy_CapSense_Save() function. See the function usage example below for +* details on usage. +* +* This function performs the same tasks as Cy_CapSense_Init() function and is +* kept for API consistency among middlewares. It is recommended to use +* Cy_CapSense_Save() and Cy_CapSense_Restore() functions to implement +* time-multiplexed mode instead of Cy_CapSense_DeInit() and Cy_CapSense_Init() +* functions for further compatibility. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the resume process. If CY_RET_SUCCESS is not received, +* the resume process fails and retries may be required. +* +* \funcusage +* +* An example of sharing the CSD HW block by CapSense and CSDADC middleware: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_TimeMultiplex +* +*******************************************************************************/ +cy_status Cy_CapSense_Restore(cy_stc_capsense_context_t * context) +{ + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + + cy_en_csd_key_t mvKey; + cy_status result = CY_RET_INVALID_STATE; + cy_en_csd_status_t csdHwStatus = CY_CSD_SUCCESS; + cy_stc_csd_context_t * ptrCsdCxt = context->ptrCommonConfig->ptrCsdContext; + CSD_Type * ptrCsdBaseAdd = context->ptrCommonConfig->ptrCsdBase; + + /* Approximate duration of Wait For Init loop */ + const uint32_t intrInitLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t initWatchdogTimeUs = 1000000uL; + + /* Get the CSD HW block status */ + mvKey = Cy_CSD_GetLockStatus(ptrCsdBaseAdd, ptrCsdCxt); + if(CY_CSD_NONE_KEY == mvKey) + { + csdHwStatus = Cy_CSD_GetConversionStatus(ptrCsdBaseAdd, ptrCsdCxt); + if(CY_CSD_BUSY == csdHwStatus) + { + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_CSD_INTR_MASK_CLEAR_MSK); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_CSD_SEQ_START_ABORT_MSK); + + /* Init Watchdog Counter to prevent a hang */ + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(initWatchdogTimeUs, cpuFreqMHz, intrInitLoopDuration); + while((CY_CSD_BUSY == csdHwStatus) && (0uL != watchdogCounter)) + { + csdHwStatus = Cy_CSD_GetConversionStatus(ptrCsdBaseAdd, ptrCsdCxt); + watchdogCounter--; + } + } + + if(CY_CSD_SUCCESS == csdHwStatus) + { + csdHwStatus = Cy_CSD_Init( + ptrCsdBaseAdd, + &cy_capsense_csdCfg, + CY_CSD_CAPSENSE_KEY, + ptrCsdCxt); + result = CY_RET_SUCCESS; + } + + } + return (result); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Save +****************************************************************************//** +* +* Saves the state of CapSense so the functionality can be restored +* using the Cy_CapSense_Restore() function. +* +* This function, along with the Cy_CapSense_Restore() function, is specifically +* designed for ease of use and supports time multiplexing of the CSD HW block +* among multiple middlewares. When the CSD HW block is shared by two or more +* middlewares, this function can be used to save the current state of +* the CSD HW block and CapSense middleware prior to releasing the CSD HW block +* for use by other middleware. See the function usage example below for +* details on usage. +* +* This function performs the same tasks as the Cy_CapSense_DeInit() function and is +* kept for API consistency among middlewares. It is recommended to use +* Cy_CapSense_Save() and Cy_CapSense_Restore() functions to implement +* Time-multiplexed mode instead of Cy_CapSense_DeInit() and Cy_CapSense_Init() +* functions for further compatibility. +* +* This function performs the following operations: +* * Release the CSD HW block. +* * Configure sensor pins to the default state and disconnect them from +* analog buses. +* * Disconnect external capacitors from analog buses. +* * Set the middleware state to default. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the process. If CY_RET_SUCCESS is not received, +* the save process fails and retries may be required. +* +* \funcusage +* +* An example of sharing the CSD HW block by the CapSense and CSDADC middleware.
+* Declares the CapSense_ISR_cfg variable: +* \snippet capsense\1.1\snippet\main.c snippet_m4_capsense_interrupt_source_declaration +* +* Declares the CSDADC_ISR_cfg variable: +* \snippet capsense\1.1\snippet\main.c snippet_m4_adc_interrupt_source_declaration +* +* Defines the CapSense interrupt handler: +* \snippet capsense\1.1\snippet\main.c snippet_CapSense_Interrupt +* +* Defines the CSDADC interrupt handler: +* \snippet capsense\1.1\snippet\main.c snippet_CSDADC_Interrupt +* +* The part of the main.c FW flow: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_TimeMultiplex +* +*******************************************************************************/ +cy_status Cy_CapSense_Save(cy_stc_capsense_context_t * context) +{ + cy_status result = CY_RET_INVALID_STATE; + cy_en_csd_status_t initStatus = CY_CSD_LOCKED; + + if (CY_CAPSENSE_SW_STS_BUSY != Cy_CapSense_IsBusy(context)) + { + /* Disconnect external capacitors and sensor pins from analog bus */ + Cy_CapSense_SwitchSensingMode((uint8_t)CY_CAPSENSE_UNDEFINED_E, context); + + /* Release the CSD HW block */ + initStatus = Cy_CSD_DeInit( + context->ptrCommonConfig->ptrCsdBase, + CY_CSD_CAPSENSE_KEY, + context->ptrCommonConfig->ptrCsdContext); + + if (CY_CSD_SUCCESS == initStatus) + { + result = CY_RET_SUCCESS; + + } + } + + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RegisterCallback +****************************************************************************//** +* +* Registers a callback function. +* +* The registered function will be called by the CapSense middleware when +* the specified event \ref cy_en_capsense_callback_event_t has occurred in +* the CapSense middleware. +* +* \param callbackType +* The event on which the registered function is called by the CapSense +* middleware. Refer to \ref cy_en_capsense_callback_event_t for the list of +* supported events. +* +* \param callbackFunction +* The pointer to the callback function to be called by the middleware. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the callback registration: +* - CY_RET_SUCCESS - The action performed successfully. +* - CY_RET_BAD_PARAM - The input parameter is invalid. +* +*******************************************************************************/ +cy_status Cy_CapSense_RegisterCallback( + cy_en_capsense_callback_event_t callbackType, + cy_capsense_callback_t callbackFunction, + cy_stc_capsense_context_t * context) +{ + cy_status retVal = CY_RET_SUCCESS; + + if((NULL != callbackFunction) && (NULL != context)) + { + switch(callbackType) + { + case CY_CAPSENSE_START_SAMPLE_E: + context->ptrCommonContext->ptrSSCallback = callbackFunction; + break; + case CY_CAPSENSE_END_OF_SCAN_E: + context->ptrCommonContext->ptrEOSCallback = callbackFunction; + break; + default: + retVal = CY_RET_BAD_PARAM; + break; + } + } + else + { + retVal = CY_RET_BAD_PARAM; + } + + return(retVal); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_UnRegisterCallback +****************************************************************************//** +* +* This function unregisters a previously registered callback function in the +* CapSense middleware. +* +* \param callbackType +* The event on which the function should be unregistered. +* Refer to \ref cy_en_capsense_callback_event_t for the list of +* supported events. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the callback deregistration: +* - CY_RET_SUCCESS - The action performed successfully. +* - CY_RET_BAD_PARAM - The input parameter is invalid. +* +*******************************************************************************/ +cy_status Cy_CapSense_UnRegisterCallback( + cy_en_capsense_callback_event_t callbackType, + cy_stc_capsense_context_t * context) +{ + cy_status retVal = CY_RET_SUCCESS; + + if(NULL != context) + { + switch(callbackType) + { + case CY_CAPSENSE_START_SAMPLE_E: + context->ptrCommonContext->ptrSSCallback = NULL; + break; + case CY_CAPSENSE_END_OF_SCAN_E: + context->ptrCommonContext->ptrEOSCallback = NULL; + break; + default: + retVal = CY_RET_BAD_PARAM; + break; + } + } + else + { + retVal = CY_RET_BAD_PARAM; + } + + return(retVal); + +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_control.h b/cy_capsense_control.h new file mode 100644 index 0000000..5889be2 --- /dev/null +++ b/cy_capsense_control.h @@ -0,0 +1,111 @@ +/***************************************************************************//** +* \file cy_capsense_control.h +* \version 1.1 +* +* \brief +* This file provides the function prototypes of the Control module. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_CONTROL_H) +#define CY_CAPSENSE_CONTROL_H + +#include "cy_syspm.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_common.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Local definition +*******************************************************************************/ +#define CY_CAPSENSE_INIT_DONE (1u) +#define CY_CAPSENSE_INIT_NEEDED (0u) + +#define CY_CAPSENSE_ANALOG_SETTLING_TIME_US (25u) + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_high_level *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_Init(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_DeInit(cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_Enable(cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_Save(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_Restore(cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_ProcessAllWidgets(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_ProcessWidget( + uint32_t widgetId, + cy_stc_capsense_context_t * context); + +void Cy_CapSense_IncrementGestureTimestamp(cy_stc_capsense_context_t * context); +void Cy_CapSense_SetGestureTimestamp( + uint32_t value, + cy_stc_capsense_context_t * context); + +void Cy_CapSense_Wakeup(const cy_stc_capsense_context_t * context); + +cy_en_syspm_status_t Cy_CapSense_DeepSleepCallback( + cy_stc_syspm_callback_params_t * callbackParams, + cy_en_syspm_callback_mode_t mode); + +cy_status Cy_CapSense_RegisterCallback( + cy_en_capsense_callback_event_t callbackType, + cy_capsense_callback_t callbackFunction, + cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_UnRegisterCallback( + cy_en_capsense_callback_event_t callbackType, + cy_stc_capsense_context_t * context); + + +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_ProcessWidgetExt( + uint32_t widgetId, + uint32_t mode, + cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_ProcessSensorExt( + uint32_t widgetId, + uint32_t sensorId, + uint32_t mode, + const cy_stc_capsense_context_t * context); +/** \} */ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_Initialize(cy_stc_capsense_context_t * context); + +/** \} \endcond */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_CONTROL_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_csd.c b/cy_capsense_csd.c new file mode 100644 index 0000000..402dad9 --- /dev/null +++ b/cy_capsense_csd.c @@ -0,0 +1,1996 @@ +/***************************************************************************//** +* \file cy_capsense_csd.c +* \version 1.1 +* +* \brief +* This file defines the data structure global variables and provides +* implementation for the low-level functions of the CSD part of +* the Sensing module. The file contains the functions used for the CSD HW block +* initialization, calibration, and scanning. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include "cy_device_headers.h" +#include "cy_sysclk.h" +#include "cy_syslib.h" +#include "cy_gpio.h" +#include "cy_csd.h" + +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_sensing.h" +#include "cy_capsense_csd.h" + + +/******************************************************************************* +* Local definition +*******************************************************************************/ +/* CY_ID285392, CY_ID515 */ +#define CY_CAPSENSE_FILTER_DELAY_MAX (CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_4_CYCLES) +#define CY_CAPSENSE_EXTRA_COUNTS_MAX (CY_CAPSENSE_FILTER_DELAY_MAX + 5u + 20u) +#define CY_CAPSENSE_16_BIT_RESOLUTION (16uL) + +/******************************************************************************* +* Static Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +__STATIC_INLINE void Cy_CapSense_CSDChangeClkFreq(uint32_t channelIndex, cy_stc_capsense_context_t * context); + +static void Cy_CapSense_CSDInitNextSnsScan(cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSDInitNextChScan(cy_stc_capsense_context_t * context); + +static void Cy_CapSense_CSDEnableShieldElectrodes(const cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSDCmodPrecharge(cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSDTriggerScan(cy_stc_capsense_context_t * context); + +static void Cy_CapSense_CSDDischargeCmod(cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSDCalibrate(uint32_t widgetId, uint32_t target, + cy_stc_capsense_context_t * context); +static uint32_t Cy_CapSense_CSDSwitchIdacGain(cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSDNormalizeIdac( + cy_stc_capsense_widget_config_t const * ptrWdConfig, + uint32_t target, + const cy_stc_capsense_context_t * context); +/** \} \endcond */ + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDDisableMode +****************************************************************************//** +* +* This function disables CSD mode. +* +* To disable CSD mode the following tasks are performed: +* 1. Disconnect Cmod from AMUXBUS-A. +* 2. Disconnect previous CSX electrode if it has been connected. +* 3. Disconnect Csh from AMUXBUS-B. +* 4. Disable Shield Electrodes. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDDisableMode(cy_stc_capsense_context_t * context) +{ + /* Cmod pin to default state */ + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_GPIO); + + if (0u != context->ptrCommonConfig->csdShieldEn) + { + /* Disconnect shields */ + Cy_CapSense_CSDDisableShieldElectrodes(context); + + if (0u != context->ptrCommonConfig->csdCTankShieldEn) + { + /* Csh pin to default state */ + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, (uint32_t)context->ptrCommonConfig->pinCsh, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_GPIO); + } + } + + /* Disconnect IDACA, IDACB and RefGen input */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_REFGEN_SEL, 0u); + + /* Disconnect previous CSD sensor if it has been connected */ + Cy_CapSense_CSDSnsStateCheck(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDEnableShieldElectrodes +****************************************************************************//** +* +* This internal function initializes Shield Electrodes. +* +* The function sets the bit in the HSIOM register which enables the shield electrode +* functionality on the pin. The port and pin configurations are stored in +* the cy_capsense_shieldIoList structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDEnableShieldElectrodes(const cy_stc_capsense_context_t * context) +{ + uint32_t shieldIndex; + const cy_stc_capsense_pin_config_t * ptrShieldPin = context->ptrShieldPinConfig; + + for (shieldIndex = 0u; shieldIndex < context->ptrCommonConfig->csdShieldNumPin; shieldIndex++) + { + Cy_CapSense_SsConfigPinRegisters(ptrShieldPin->pcPtr, (uint32_t)ptrShieldPin->pinNumber, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_CSD_SHIELD); + ptrShieldPin++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDDisableShieldElectrodes +****************************************************************************//** +* +* This internal function disables Shield Electrodes. +* +* The function resets the bit in the HSIOM register which disables the shield +* electrode functionality on the pin. The port and pin configurations are +* stored in the cy_capsense_shieldIoList structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDDisableShieldElectrodes(const cy_stc_capsense_context_t * context) +{ + uint32_t shieldIndex; + uint32_t interruptState; + const cy_stc_capsense_pin_config_t * ptrShieldPin = context->ptrShieldPinConfig; + + for (shieldIndex = 0u; shieldIndex < context->ptrCommonConfig->csdShieldNumPin; shieldIndex++) + { + Cy_CapSense_SsConfigPinRegisters(ptrShieldPin->pcPtr, (uint32_t)ptrShieldPin->pinNumber, CY_GPIO_DM_STRONG, CY_CAPSENSE_HSIOM_SEL_GPIO); + + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_Clr(ptrShieldPin->pcPtr, (uint32_t)ptrShieldPin->pinNumber); + Cy_SysLib_ExitCriticalSection(interruptState); + + ptrShieldPin++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDInitialize +****************************************************************************//** +* +* This function initializes the CSD module. +* +* The function performs the following steps: +* 1) Sets GPIO output to "0" for all sensor pins; +* 2) Connects CMOD to AMUXBUS-A and to CSDBUS-A; +* 3) Connects CMOD to (sense path) to CSDCOMP; +* 4) Connects Csh_tank to AMUXBUS-B and to CSDBUS-B; +* 5) Connects VREF to REFGEN; +* 6) Configures REFGEN and sets the reference voltage; +* 7) Connects VREF to CSDCOMP and HSCOMP; +* 8) Configures IDAC and connect to CSDBUS-A (to drive CMOD); +* 9) Configures ModClk; +* 10) Configure SnsClk source; +* 11) Sets other CSD configurations (Csd Auto Zero time, +* Sample Init period, interrupts, +* CMOD and Csh_tank/shield initialization switch resistance). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDInitialize(cy_stc_capsense_context_t * context) +{ + uint32_t interruptState; + + /* Set all the sensors to inactive state */ + Cy_CapSense_CSDClearSensors(context); + Cy_CapSense_DischargeExtCapacitors(context); + + if (0u != context->ptrCommonConfig->csdShieldEn) + { + /* Connect shields to AMUX-B bus (config HSIOM regs) */ + Cy_CapSense_CSDEnableShieldElectrodes(context); + + if (0u != context->ptrCommonConfig->csdCTankShieldEn) + { + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, (uint32_t)context->ptrCommonConfig->pinCsh, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_AMUXB); + } + } + + /* Initialize the unused CSD IP registers to default state */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_DUTY, CY_CAPSENSE_CSD_SENSE_DUTY_SENSE_POL_PHI_HIGH); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_SET, CY_CAPSENSE_DEFAULT_CSD_INTR_SET); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_DSI_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_DSI_SEL); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_ADC_CTL, CY_CAPSENSE_DEFAULT_CSD_ADC_CTL); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, 0u); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_TANK_SEL, context->ptrInternalContext->csdRegSwFwTankSelScan); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_AMUXBUF_SEL, context->ptrInternalContext->csdRegSwAmuxbufSel); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_P_SEL, context->ptrInternalContext->csdRegSwHsPSelScan); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_N_SEL, CY_CAPSENSE_DEFAULT_SW_HS_N_SEL); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_HSCMP, context->ptrInternalContext->csdRegHscmpScan); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IO_SEL, context->ptrInternalContext->csdRegIoSel); + + /* Connection AMUXBUS-A to CSDBUS-A / AMUXBUS-B to CSDBUS-B */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_BYP_SEL, context->ptrInternalContext->csdRegSwBypSel); + + /* Connect CMOD to AMUXBUS-A */ + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetDrivemode((GPIO_PRT_Type*)context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, CY_GPIO_DM_ANALOG); + Cy_GPIO_SetHSIOM((GPIO_PRT_Type*)context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, CY_CAPSENSE_HSIOM_SEL_AMUXA); + Cy_SysLib_ExitCriticalSection(interruptState); + + /* Set Csd Auto Zero time (set AZ_TIME bitmask) */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_TIME, 0u); + /* Select CMOD and Csh_tank/shield initialization switch resistance */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_RES, context->ptrInternalContext->csdRegSwResScan); + /* Set the number of dummy fine initialization cycles */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_INIT_CNT, (uint32_t)context->ptrCommonConfig->csdFineInitTime); + + /* Connect CMOD to (sense path) to CSDCOMP */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_CMP_P_SEL, context->ptrInternalContext->csdRegSwCmpPSel); + + /* Configure VREF */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_REFGEN_SEL, + context->ptrInternalContext->regSwRefGenSel | CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_IAIB_MSK); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_AMBUF, context->ptrInternalContext->csdRegAmuxbufInit); + + /* Connect VREFHI to HSCOMP */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_N_SEL, CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCRH_STATIC_CLOSE); + + /* Connect VREFHI (from RefGen) to CSDCOMP when Vdda >= 2 V */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_CMP_N_SEL, CY_CAPSENSE_CSD_SW_CMP_N_SEL_SW_SCRH_STATIC_CLOSE); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_REFGEN, context->ptrInternalContext->csdRegRefgen); + + /* Configure IDACs mode */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACA, context->ptrInternalContext->csdIdacAConfig); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACB, context->ptrInternalContext->csdIdacBConfig); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CONFIG, context->ptrInternalContext->csdRegConfig); + + /* Configure ModClk */ + Cy_CapSense_SetClkDivider((uint32_t)context->ptrCommonContext->modCsdClk - 1u, context); + + /* Setup ISR handler to single-sensor scan function */ + context->ptrActiveScanSns->ptrISRCallback = &Cy_CapSense_CSDScanISR; + + context->ptrActiveScanSns->mfsChannelIndex = 0u; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDSnsStateCheck +****************************************************************************//** +* +* Checks if electrodes were previously connected using +* Cy_CapSense_CSDSetupWidgetExt() and if yes disconnects them. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDSnsStateCheck(cy_stc_capsense_context_t * context) +{ + if (CY_CAPSENSE_SNS_CONNECTED == context->ptrActiveScanSns->connectedSnsState) + { + Cy_CapSense_CSDDisconnectSnsExt(context); + } +} + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDSetUpIdacs +****************************************************************************//** +* +* This function writes both IDACs available in CSD method into corresponding +* the CSD HW block registers. +* +* Modulator IDAC is taken from widget context structure and Compensation +* IDAC is taken from sensor context structure. +* The cy_stc_active_scan_sns_t structure must be updated to the current +* widget/sensor by Cy_CapSense_InitActivePtr() before calling this function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDSetUpIdacs(cy_stc_capsense_context_t * context) +{ + uint32_t regValue; + + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + const uint32_t idacaBitsToWrite = CSD_IDACA_VAL_Msk | + CSD_IDACA_RANGE_Msk | + CSD_IDACA_LEG1_EN_Msk | + CSD_IDACA_LEG2_EN_Msk; + + const uint32_t idacbBitsToWrite = CSD_IDACB_VAL_Msk | + CSD_IDACB_RANGE_Msk | + CSD_IDACB_LEG1_EN_Msk | + CSD_IDACB_LEG2_EN_Msk | + CSD_IDACB_LEG3_EN_Msk; + + /* IDAC A Code */ + if (ptrActive->ptrWdConfig->numCols > ptrActive->sensorIndex) + { + regValue = ptrActive->ptrWdContext->idacMod[ptrActive->mfsChannelIndex]; + } + else + { + regValue = ptrActive->ptrWdContext->rowIdacMod[ptrActive->mfsChannelIndex]; + } + + regValue |= context->ptrCommonConfig->idacGainTable[ptrActive->ptrWdContext->idacGainIndex].gainReg; + + Cy_CSD_WriteBits(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACA, idacaBitsToWrite, regValue); + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + /* IDAC B Code */ + regValue = ptrActive->ptrSnsContext->idacComp; + regValue |= context->ptrCommonConfig->idacGainTable[ptrActive->ptrWdContext->idacGainIndex].gainReg; + + Cy_CSD_WriteBits(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACB, idacbBitsToWrite, regValue); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDGetNumberOfConversions +****************************************************************************//** +* +* This function calculate number of sub-conversions. +* +* \param snsClkDivider +* The divider value of the sense clock. +* +* \param resolution +* The widget resolution. +* +* \param snsClkSrc +* The widget Sense Clock Source. +* +* \return +* Returns the number of sub-conversions. +* +*******************************************************************************/ +uint32_t Cy_CapSense_CSDGetNumberOfConversions(uint32_t snsClkDivider, uint32_t resolution, uint32_t snsClkSrc) +{ + /* CY_ID304273 */ + uint32_t conversionsNum = 1uL << resolution; + uint32_t extraCounts = 0u; + + if (0u == snsClkDivider) + { + snsClkDivider = 1u; + } + + if ((CY_CAPSENSE_CLK_SOURCE_PRS8 == snsClkSrc) || (CY_CAPSENSE_CLK_SOURCE_PRS12 == snsClkSrc)) + { + snsClkDivider <<= 1u; + } + + if(CY_CAPSENSE_16_BIT_RESOLUTION <= resolution) + { + /* CY_ID285392 */ + extraCounts = CY_CAPSENSE_EXTRA_COUNTS_MAX; + } + + conversionsNum = (conversionsNum - extraCounts) / snsClkDivider; + + return((conversionsNum > 0u) ? (conversionsNum) : 1u); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDConfigClock +****************************************************************************//** +* +* This function configure sense clock for different modes. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDConfigClock(cy_stc_capsense_context_t * context) +{ + const cy_stc_capsense_widget_context_t * ptrWdCxt = context->ptrActiveScanSns->ptrWdContext; + uint32_t snsClkDivider; + uint32_t snsClkSrc = (uint32_t)ptrWdCxt->snsClkSource & ((uint32_t)~(uint32_t)CY_CAPSENSE_CLK_SOURCE_AUTO_MASK); + uint32_t regConfig = 0u; + + /* Getting row clock divider for matrix buttons or touchpad widgets */ + if (context->ptrActiveScanSns->ptrWdConfig->numCols <= context->ptrActiveScanSns->sensorIndex) + { + snsClkDivider = ptrWdCxt->rowSnsClk; + } + else + { + snsClkDivider = ptrWdCxt->snsClk; + } + + /* Configuring PRS SEL_BIT and decreasing divider in case of PRS */ + if ((CY_CAPSENSE_CLK_SOURCE_PRS8 == snsClkSrc) || (CY_CAPSENSE_CLK_SOURCE_PRS12 == snsClkSrc)) + { + regConfig = CY_CAPSENSE_CSD_SENSE_PERIOD_SEL_LFSR_MSB_MSK; + snsClkDivider >>= 1u; + } + + /* Check divider value */ + if (0u == snsClkDivider) + { + snsClkDivider = 1u; + } + + regConfig |= ((snsClkSrc << CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SIZE_POS) | (snsClkDivider - 1u)); + + /* Update reg value with divider and configuration */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_PERIOD, regConfig); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDCalculateScanDuration +****************************************************************************//** +* +* Calculates Scan Duration which is defined by scan resolution +* +* The function calculates the number of conversions and updates +* SEQ_NORM_CNT register. The number of conversions depends on resolution and +* snsClk divider. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDCalculateScanDuration(cy_stc_capsense_context_t * context) +{ + uint32_t subConv; + cy_stc_capsense_widget_context_t * ptrWdCxt = context->ptrActiveScanSns->ptrWdContext; + uint32_t divider = ptrWdCxt->snsClk; + + if (context->ptrActiveScanSns->ptrWdConfig->numCols <= context->ptrActiveScanSns->sensorIndex) + { + divider = ptrWdCxt->rowSnsClk; + } + + subConv = Cy_CapSense_CSDGetNumberOfConversions(divider, (uint32_t)ptrWdCxt->resolution, + ((uint32_t)ptrWdCxt->snsClkSource & ((uint32_t)~(uint32_t)CY_CAPSENSE_CLK_SOURCE_AUTO_MASK))); + + /* Write number of sub-conversions into the CSD HW block register */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_NORM_CNT, (subConv & CY_CAPSENSE_CSD_SEQ_NORM_CNT_CONV_CNT_MSK)); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDSetupWidget +****************************************************************************//** +* +* Performs the initialization required to scan the specified CSD widget. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_SetupWidget() function should be used instead. +* +* This function prepares the middleware to scan all the sensors in the +* specified CSD widget by executing the following tasks: +* 1. Configure the CSD HW block if it is not configured to perform the +* CSD sensing method used by the specified widget. +* 2. Initialize the CSD HW block with specific sensing configuration (e.g. +* sensor clock, scan resolution) used by the widget. +* 3. Disconnect all previously connected electrodes, if the electrodes +* connected by the Cy_CapSense_CSDSetupWidgetExt(), +* Cy_CapSense_CSXSetupWidgetExt() functions are not disconnected. +* +* This function does not start sensor scanning. The Cy_CapSense_CSDScan() +* function must be called to start the scan sensors in the widget. If this +* function is called more than once, it does not break the middleware +* operation, but only the last initialized widget is in effect. +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for example faster execution). +* +* The status of a sensor scan must be checked using the Cy_CapSense_IsBusy() +* function prior to starting a next scan or setting up another widget. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDSetupWidget(uint32_t widgetId, cy_stc_capsense_context_t * context) +{ + /* Setup new scanning mode */ + Cy_CapSense_SwitchSensingMode((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E, context); + + /* Disconnect previous sensors if they have been connected */ + Cy_CapSense_CSDSnsStateCheck(context); + + /* Save widget Id to have assess to it after scanning */ + Cy_CapSense_InitActivePtr(widgetId, 0u, context); + + /* Set up scanning resolution (Number of conversion) */ + Cy_CapSense_CSDCalculateScanDuration(context); + Cy_CapSense_CSDConfigClock(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDSetupWidgetExt +****************************************************************************//** +* +* Performs extended initialization required to scan a specified sensor in +* a widget using CSD sensing method. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_SetupWidgetExt() function should be used instead. +* +* This function performs the same tasks of Cy_CapSense_CSDSetupWidget() and +* also connects and configures specified sensor for scan. Hence this +* function, along with Cy_CapSense_CSDScanExt() function, can be used to +* scan a specific sensor in the widget. +* +* This function should be called for widget that is configured to use +* CSD sensing method, using this function on a non-CSD sensing widget +* would cause unexpected result. +* +* This function requires using the Cy_CapSense_CSDScanExt() function to +* initiate a scan. +* +* Calling this function directly from the application layer is not +* recommended. This function is used to implement only the user's +* specific use cases (for example faster execution). +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDSetupWidgetExt(uint32_t widgetId, uint32_t sensorId, cy_stc_capsense_context_t * context) +{ + /* Switch Mode if needed */ + Cy_CapSense_SwitchSensingMode((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E, context); + + /* Disconnect previous sensors if they have been connected */ + Cy_CapSense_CSDSnsStateCheck(context); + + /* Setup new widget/sensor */ + Cy_CapSense_InitActivePtr(widgetId, sensorId, context); + Cy_CapSense_CSDConnectSnsExt(context); + Cy_CapSense_CSDSetUpIdacs(context); + Cy_CapSense_CSDCalculateScanDuration(context); + Cy_CapSense_CSDConfigClock(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDStartSample +****************************************************************************//** +* +* Starts the CSD conversion. +* +* This function assumes that the CSD HW block is already set up using +* the Cy_CapSense_CSDSetupWidget() and the sensor port-pin is connected to the CSD +* block using Cy_CapSense_CSDConnectSns(). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDStartSample(cy_stc_capsense_context_t * context) +{ + if(NULL != context->ptrCommonContext->ptrSSCallback) + { + context->ptrCommonContext->ptrSSCallback(context->ptrActiveScanSns); + } + + /* Precharging Cmod and Csh */ + Cy_CapSense_CSDCmodPrecharge(context); + + /* Trigger Scan */ + Cy_CapSense_CSDTriggerScan(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDScanExt +****************************************************************************//** +* +* Starts the CSD conversion on the preconfigured sensor. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_ScanExt() function should be used instead. +* +* This function performs scanning of a specific sensor in the widget +* previously initialized using the Cy_CapSense_CSDSetupWidgetExt() function. +* +* This function is called when no scanning is in progress. +* I.e. Cy_CapSense_IsBusy() returns a non-busy status and the widget must +* be preconfigured using Cy_CapSense_CSDSetupWidgetExt() function prior +* to calling this function. Calling this function directly from +* the application program is not recommended. This function is used to +* implement only the user's specific use cases (for example faster execution). +* +* This function does not disconnect sensor GPIOs from CSD HW block at the +* end of a scan, therefore making subsequent scan of the same sensor is faster. +* If sensor needs to be disconnected after the scan, +* Cy_CapSense_CSDDisconnectSns() function can be used. +* +* Calling Cy_CapSense_SetupWidget(), Cy_CapSense_CSDSetupWidget(), +* Cy_CapSense_ScanAllWidgets(), or if Cy_CapSense_RunTuner() returns +* CY_CAPSENSE_STATUS_RESTART_DONE status invalidated initialization +* made by this function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDScanExt(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + /* Set MFS channel index to 0 */ + ptrActive->mfsChannelIndex = 0u; + + /* Initialize the Active Context pointer with the CH0 context */ + ptrActive->ptrSnsContext = &ptrActive->ptrWdConfig->ptrSnsContext[ptrActive->sensorIndex]; + + /* Set Start of sensor scan flag */ + Cy_CapSense_SetBusyFlags(context); + + /* Set scope flag */ + ptrActive->scanScopeSns = CY_CAPSENSE_SCAN_SCOPE_SGL_SNS; + + /* Initiate scan */ + Cy_CapSense_CSDStartSample(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDScan +****************************************************************************//** +* +* This function initiates a scan for the sensors of the widget initialized +* by the Cy_CapSense_CSDSetupWidget() function. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_Scan() function should be used instead. +* +* This function does the following tasks: +* 1. Connects the first sensor of the widget. +* 2. Configures the IDAC value. +* 3. Starts scanning for the first sensor in the widget. +* +* This function is called by the Cy_CapSense_Scan() if the given +* widget uses the CSD sensing method. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for example faster execution). +* +* This function is called when no scanning is in progress. I.e. +* Cy_CapSense_IsBusy() returns a non-busy status and the widget must be +* preconfigured using the Cy_CapSense_CSDSetupWidget() function prior +* to calling this function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDScan(cy_stc_capsense_context_t * context) +{ + Cy_CapSense_InitActivePtrSns(0u, context); + + /* Setup Idac Value */ + Cy_CapSense_CSDSetUpIdacs(context); + Cy_CapSense_CSDConnectSnsExt(context); + + /* Set Start of sensor scan flag */ + Cy_CapSense_SetBusyFlags(context); + /* Set scope flag */ + context->ptrActiveScanSns->scanScopeSns = CY_CAPSENSE_SCAN_SCOPE_ALL_SNS; + /* Initiate scan */ + Cy_CapSense_CSDStartSample(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDConnectSnsExt +****************************************************************************//** +* +* Connects a ganged sensor port-pin to the CSD HW block via the AMUX bus. +* +* The function gets the IO configuration registers addresses, their shifts and +* masks from the cy_stc_capsense_pin_config_t object. Based on this data, it +* updates the HSIOM and PC registers. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDConnectSnsExt(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + const cy_stc_capsense_electrode_config_t * ptrActiveSns = ptrActive->ptrEltdConfig; + const cy_stc_capsense_pin_config_t * ptrActivePin = ptrActiveSns->ptrPin; + uint32_t i; + + /* Connect all pins of current sensors */ + for(i = 0u; i < ptrActiveSns->numPins; i++) + { + Cy_CapSense_CSDConnectSns(ptrActivePin, context); + ptrActivePin++; + } + ptrActive->connectedSnsState = CY_CAPSENSE_SNS_CONNECTED; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDDisconnectSnsExt +****************************************************************************//** +* +* Disconnects a ganged sensor port-pin from the CSD HW block and AMUX bus. +* Sets the default state of the un-scanned sensor. +* +* The function gets the IO configuration registers addresses, their shifts and +* masks from the cy_stc_capsense_pin_config_t object. Based on this data and +* the Inactive sensor connection parameter, it updates the HSIOM, PC, and DR registers. +* The HSIOM register is updated only when the Inactive sensor connection parameter +* is set to Shield. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDDisconnectSnsExt(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + const cy_stc_capsense_electrode_config_t * ptrActiveSns = ptrActive->ptrEltdConfig; + const cy_stc_capsense_pin_config_t * ptrActivePin = ptrActiveSns->ptrPin; + + uint32_t i; + + /* Disconnect all pins of current sensors */ + for(i = 0u; i < ptrActiveSns->numPins; i++) + { + Cy_CapSense_CSDDisconnectSns(ptrActivePin, context); + ptrActivePin++; + } + ptrActive->connectedSnsState = CY_CAPSENSE_SNS_DISCONNECTED; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDConnectSns +****************************************************************************//** +* +* Connects port pin to the CSD HW block using AMUX bus. +* +* This function can be used to customize the default sensor connection +* by connecting one or more pins to an existing sensor prior to initiating +* scan of the sensor. +* +* The function ignores whether the sensor is a ganged sensor and +* connects only a specified port pin to the CSD HW block. This function can +* only use GPIOs that are already assigned to CapSense middleware. +* +* The functions that perform a setup and scan of a sensor/widget do not +* take into account changes in the design made by +* the Cy_CapSense_CSDConnectSns() function, hence all GPIOs connected +* using this function must be disconnected using +* the Cy_CapSense_CSDDisconnectSns() function prior to initializing +* new widgets. Use this function in StartSample +* callback (see the \ref group_capsense_callbacks section for details) +* or with low-level functions that perform a single-sensor scanning. +* +* Scanning should be completed before calling this function. +* +* \param snsAddrPtr +* Specifies the pointer to the cy_stc_capsense_pin_config_t object belonging to +* a sensor that is to be connected to the CSD HW block. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of using the function to perform port pin re-connection: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_CSDConnect +* +*******************************************************************************/ +void Cy_CapSense_CSDConnectSns( + const cy_stc_capsense_pin_config_t * snsAddrPtr, + cy_stc_capsense_context_t * context) +{ + Cy_CapSense_SsConfigPinRegisters(snsAddrPtr->pcPtr, (uint32_t)snsAddrPtr->pinNumber, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_CSD_SENSE); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDDisconnectSns +****************************************************************************//** +* +* Disconnects port pin from the CSD HW block by disconnecting it from AMUX bus. +* +* This function can be used to disconnect a sensor connected +* using the Cy_CapSense_CSDConnectSns() function. In addition, this +* function can be used to customize a default sensor connection by +* disconnecting one or more already connected sensors prior to +* initiating a scan of the sensor. +* +* This function works identically to the Cy_CapSense_CSDConnectSns() function +* except it disconnects the specified port pin used by the sensor. +* +* Scanning should be completed before calling this function. +* +* \param snsAddrPtr +* Specifies the pointer to the cy_stc_capsense_pin_config_t object belonging to +* a sensor that should be disconnected from the CSD HW block. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of using the function to perform port pin re-connection: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_CSDConnect +* +*******************************************************************************/ +void Cy_CapSense_CSDDisconnectSns( + const cy_stc_capsense_pin_config_t * snsAddrPtr, + const cy_stc_capsense_context_t * context) +{ + uint32_t interruptState; + + Cy_CapSense_SsConfigPinRegisters(snsAddrPtr->pcPtr, (uint32_t)snsAddrPtr->pinNumber, + context->ptrInternalContext->csdInactiveSnsDm, + context->ptrInternalContext->csdInactiveSnsHsiom); + + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_Clr(snsAddrPtr->pcPtr, (uint32_t)snsAddrPtr->pinNumber); + Cy_SysLib_ExitCriticalSection(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDClearSensors +****************************************************************************//** +* +* Resets all the CSD sensors to the non-sampling state by sequentially +* disconnecting all the sensors from the Analog MUX bus and putting them to +* an inactive state. +* +* The function goes through all the widgets and updates appropriate bits in +* the IO HSIOM, PC and DR registers depending on the Inactive sensor connection +* parameter. DR register bits are set to zero when the Inactive sensor +* connection is Ground or Hi-Z. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDClearSensors(const cy_stc_capsense_context_t * context) +{ + uint32_t wdgtIndex; + uint32_t snsIndex; + uint32_t pinIndex; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + const cy_stc_capsense_electrode_config_t * ptrSnsCfg; + + /* Go through all CSD widgets and configure each sensor/pin to the defined state */ + for (wdgtIndex = 0u; wdgtIndex < context->ptrCommonConfig->numWd; wdgtIndex++) + { + ptrWdCfg = &context->ptrWdConfig[wdgtIndex]; + if ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == ptrWdCfg->senseMethod) + { + /* Go through all sensors in widget */ + for (snsIndex = 0u; snsIndex < ptrWdCfg->numSns; snsIndex++) + { + ptrSnsCfg = ptrWdCfg->ptrEltdConfig; + /* Go through all pins in sensor */ + for(pinIndex = 0u; pinIndex < ptrSnsCfg->numPins; pinIndex++) + { + /* Set CSD pin default state */ + Cy_CapSense_CSDDisconnectSns(ptrSnsCfg->ptrPin, context); + } + } + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDSetWidgetSenseClkSrc +****************************************************************************//** +* +* Sets a source for the sense clock for a widget. +* +* \param ptrWdConfig +* The pointer to the widget context structure. +* +*******************************************************************************/ +void Cy_CapSense_CSDSetWidgetSenseClkSrc(const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t lfsrSize; + uint32_t conversionsNum; + uint32_t rowLfsrSize; + uint8_t widgetType = ptrWdConfig->wdType; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + + if (0u != (ptrWdCxt->snsClkSource & CY_CAPSENSE_CLK_SOURCE_AUTO_MASK)) + { + conversionsNum = Cy_CapSense_CSDGetNumberOfConversions((uint32_t)ptrWdCxt->snsClk, (uint32_t)ptrWdCxt->resolution, CY_CAPSENSE_CLK_SOURCE_DIRECT); + lfsrSize = Cy_CapSense_SsCalcLfsrSize((uint32_t)ptrWdCxt->snsClk, conversionsNum); + if (CY_CAPSENSE_CLK_SOURCE_DIRECT == lfsrSize) + { + lfsrSize = Cy_CapSense_CSDCalcPrsSize((uint32_t)ptrWdCxt->snsClk << 1uL, (uint32_t)ptrWdCxt->resolution); + } + + if (((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == widgetType) || ((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == widgetType)) + { + if (ptrWdCxt->rowSnsClk != ptrWdCxt->snsClk) + { + conversionsNum = Cy_CapSense_CSDGetNumberOfConversions((uint32_t)ptrWdCxt->rowSnsClk, (uint32_t)ptrWdCxt->resolution, CY_CAPSENSE_CLK_SOURCE_DIRECT); + rowLfsrSize = Cy_CapSense_SsCalcLfsrSize((uint32_t)ptrWdCxt->rowSnsClk, conversionsNum); + if (CY_CAPSENSE_CLK_SOURCE_DIRECT == rowLfsrSize) + { + rowLfsrSize = Cy_CapSense_CSDCalcPrsSize((uint32_t)ptrWdCxt->rowSnsClk << 1uL, (uint32_t)ptrWdCxt->resolution); + } + /* Select sense clock source based on both dimensions */ + if (rowLfsrSize != lfsrSize) + { + lfsrSize = CY_CAPSENSE_CLK_SOURCE_DIRECT; + } + } + } + ptrWdCxt->snsClkSource = (uint8_t)lfsrSize | CY_CAPSENSE_CLK_SOURCE_AUTO_MASK; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDCalcPrsSize +****************************************************************************//** +* +* The function finds PRS polynomial size when clock source is set to Auto mode. +* +* The PRS polynomial size in the Auto mode is found based on the following +* requirements: +* - at least one full spread spectrum polynomial should pass during scan time. +* +* \param snsClkDivider +* The divider value for the sense clock. +* +* \param resolution +* The widget resolution. +* +* \return +* Returns the size of PRS value for SENSE_PERIOD register. +* +*******************************************************************************/ +uint32_t Cy_CapSense_CSDCalcPrsSize(uint32_t snsClkDivider, uint32_t resolution) +{ + uint32_t prsSize; + + if ((snsClkDivider * CY_CAPSENSE_PRS_LENGTH_12_BITS) <= ((0x00000001uL << resolution) - 1u)) + { + /* Set PRS12 mode */ + prsSize = CY_CAPSENSE_CLK_SOURCE_PRS12; + } + else if ((snsClkDivider * CY_CAPSENSE_PRS_LENGTH_8_BITS) <= ((0x00000001uL << resolution) - 1u)) + { + /* Set PRS8 mode */ + prsSize = CY_CAPSENSE_CLK_SOURCE_PRS8; + } + else + { + prsSize = CY_CAPSENSE_CLK_SOURCE_DIRECT; + } + + return prsSize; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDDischargeCmod +****************************************************************************//** +* +* Discharges Cmod capacitor related to CSD sensing method and restores +* it state. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDDischargeCmod(cy_stc_capsense_context_t * context) +{ + en_hsiom_sel_t hsiomReg; + uint32_t pcReg; + uint32_t interruptState; + + /* Disconnect Ext Cap from AMUXBUS-A / AMUXBUSB using HSIOM registers */ + interruptState = Cy_SysLib_EnterCriticalSection(); + hsiomReg = Cy_GPIO_GetHSIOM(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod); + Cy_GPIO_SetHSIOM(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, + CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_SysLib_ExitCriticalSection(interruptState); + + /* Set port configuration register (drive mode) to STRONG mode */ + interruptState = Cy_SysLib_EnterCriticalSection(); + pcReg = Cy_GPIO_GetDrivemode(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod); + Cy_GPIO_Clr(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod); + Cy_GPIO_SetDrivemode(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, + CY_GPIO_DM_STRONG_IN_OFF); + Cy_SysLib_ExitCriticalSection(interruptState); + + /* Now external CSD-related capacitors discharging */ + Cy_SysLib_DelayUs(CY_CAPSENSE_EXT_CAP_DISCHARGE_TIME); + + /* Restore Ext Cap settings */ + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetDrivemode(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, pcReg); + Cy_GPIO_SetHSIOM(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, hsiomReg); + Cy_SysLib_ExitCriticalSection(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsCSDSwitchIdacGain +****************************************************************************//** +* +* Switches to the lower IDAC gain is possible. +* +* This internal function switches to the lower IDAC gain is possible. +* Conditions of switching to the lower IDAC gains: +* 1. The current IDAC gain is not the lowest one. +* 2. The maximum IDAC at gain switching will not be out of range. +* 3. The minimum IDAC is still below the acceptable range. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return Returns the status of the operation: +* - Zero - Gain switching is not needed. +* - Non-Zero - Gain was switched to the lower one. +* +*******************************************************************************/ +static uint32_t Cy_CapSense_CSDSwitchIdacGain(cy_stc_capsense_context_t * context) +{ + uint32_t ratio; + uint32_t maxIdac; + uint32_t minIdac; + uint32_t swStatus = 0u; + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + uint32_t gainIndex = ptrActive->ptrWdContext->idacGainIndex; + uint32_t snsIndex; + uint32_t idacVal; + uint8_t freqChIndex; + uint8_t freqChNumber; + + maxIdac = 0u; + minIdac = CY_CAPSENSE_CAL_IDAC_MAX_VALUE; + + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + /* Find maximum and minimum IDACs */ + idacVal = ptrActive->ptrWdContext->idacMod[freqChIndex]; + if (maxIdac < idacVal) + { + maxIdac = idacVal; + } + if (minIdac > idacVal) + { + minIdac = idacVal; + } + /* Check for sensorIndex >= numCols added and choose rowIdac if needed */ + if ((((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrActive->ptrWdConfig->wdType) || + ((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == ptrActive->ptrWdConfig->wdType)) && + (ptrActive->ptrWdConfig->numCols <= ptrActive->sensorIndex)) + { + idacVal = ptrActive->ptrWdContext->rowIdacMod[freqChIndex]; + if (maxIdac < idacVal) + { + maxIdac = idacVal; + } + if (minIdac > idacVal) + { + minIdac = idacVal; + } + } + + /* Set value for iDac comp */ + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + for(snsIndex = 0u; snsIndex < ptrActive->ptrWdConfig->numSns; snsIndex++) + { + ptrSnsCxt = &ptrActive->ptrWdConfig->ptrSnsContext[snsIndex]; + idacVal = ptrSnsCxt[freqChIndex * context->ptrCommonConfig->numSns].idacComp; + if (minIdac > idacVal) + { + minIdac = idacVal; + } + } + } + } + + /* Check gain switch conditions */ + if (gainIndex != 0u) + { + if (minIdac < context->ptrCommonConfig->csdIdacMin) + { + ratio = context->ptrCommonConfig->idacGainTable[gainIndex].gainValue / + context->ptrCommonConfig->idacGainTable[gainIndex - 1u].gainValue; + if ((maxIdac * ratio) < CY_CAPSENSE_CAL_IDAC_MAX_VALUE) + { + /* Switch to lower idac gain */ + ptrActive->ptrWdContext->idacGainIndex--; + swStatus = 1u; + } + } + } + return (swStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsCSDNormalizeIdac +****************************************************************************//** +* +* This function normalizes compensation IDAC. +* +* \param ptrWdConfig +* Specifies the pointer to a widget configuration structure. +* +* \param target +* Raw count target in percentage. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDNormalizeIdac( + cy_stc_capsense_widget_config_t const * ptrWdConfig, + uint32_t target, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t maxIdac; + uint32_t minIdac; + uint32_t minRaw; + uint32_t rawLevel; + uint32_t iMod; + + uint8_t freqChIndex; + uint8_t freqChNumber; + + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + uint32_t maxRawLevel = ptrWdCxt->maxRawCount; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + /* Find maximum and minimum IDACs */ + maxIdac = ptrWdConfig->ptrWdContext->idacMod[freqChIndex]; + minIdac = maxIdac; + ptrSnsCxt = &ptrWdConfig->ptrSnsContext[freqChIndex * context->ptrCommonConfig->numSns]; + minRaw = ptrSnsCxt->raw; + for(snsIndex = 0u; snsIndex < ptrWdConfig->numCols; snsIndex++) + { + if (minIdac > ptrSnsCxt->idacComp) + { + minIdac = ptrSnsCxt->idacComp; + minRaw = ptrSnsCxt->raw; + } + ptrSnsCxt++; + } + + /* Define new modulator IDAC */ + rawLevel = ((minRaw * CY_CAPSENSE_PERCENTAGE_100) / maxRawLevel) + CY_CAPSENSE_PERCENTAGE_100; + iMod = (rawLevel * minIdac) / target; + + if (iMod > maxIdac) + { + iMod = maxIdac; + } + ptrWdCxt->idacMod[freqChIndex] = (uint8_t)iMod; + + /* Re-calculate compensation IDAC */ + ptrSnsCxt = &ptrWdConfig->ptrSnsContext[freqChIndex * context->ptrCommonConfig->numSns]; + for(snsIndex = 0u; snsIndex < ptrWdConfig->numCols; snsIndex++) + { + rawLevel = ((((uint32_t)ptrSnsCxt->raw * CY_CAPSENSE_PERCENTAGE_100) / maxRawLevel) + + CY_CAPSENSE_PERCENTAGE_100) * ptrSnsCxt->idacComp; + if (rawLevel < (iMod * target)) + { + ptrSnsCxt->idacComp = 0u; + } + else + { + ptrSnsCxt->idacComp = (uint8_t)(((rawLevel - (iMod * target)) + + (CY_CAPSENSE_PERCENTAGE_100 >> 1u)) / CY_CAPSENSE_PERCENTAGE_100); + } + ptrSnsCxt++; + } + /* IDAC Normalization is performed separately for row and column */ + if (((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrWdConfig->wdType) || + ((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == ptrWdConfig->wdType)) + { + /* Find maximum and minimum IDACs */ + maxIdac = ptrWdCxt->rowIdacMod[freqChIndex]; + minIdac = ptrWdCxt->rowIdacMod[freqChIndex]; + ptrSnsCxt = &(ptrWdConfig->ptrSnsContext[(freqChIndex * context->ptrCommonConfig->numSns) + ptrWdConfig->numCols]); + minRaw = ptrSnsCxt->raw; + for(snsIndex = ptrWdConfig->numCols; snsIndex < ptrWdConfig->numSns; snsIndex++) + { + if (minIdac > ptrSnsCxt->idacComp) + { + minIdac = ptrSnsCxt ->idacComp; + minRaw = ptrSnsCxt->raw; + } + ptrSnsCxt++; + } + + /* Define new modulator IDAC */ + rawLevel = ((minRaw * CY_CAPSENSE_PERCENTAGE_100) / maxRawLevel) + CY_CAPSENSE_PERCENTAGE_100; + iMod = (rawLevel * minIdac) / target; + + if (iMod > maxIdac) + { + iMod = maxIdac; + } + ptrWdCxt->rowIdacMod[freqChIndex] = (uint8_t)iMod; + + /* Re-calculate compensation IDAC */ + ptrSnsCxt = &(ptrWdConfig->ptrSnsContext[(freqChIndex * context->ptrCommonConfig->numSns) + ptrWdConfig->numCols]); + for(snsIndex = 0u; snsIndex < ptrWdConfig->numCols; snsIndex++) + { + rawLevel = ((((uint32_t)ptrSnsCxt->raw * CY_CAPSENSE_PERCENTAGE_100) / maxRawLevel) + + CY_CAPSENSE_PERCENTAGE_100) * ptrSnsCxt->idacComp; + if (rawLevel < (iMod * target)) + { + ptrSnsCxt->idacComp = 0u; + } + else + { + ptrSnsCxt->idacComp = (uint8_t)(((rawLevel - (iMod * target)) + + (CY_CAPSENSE_PERCENTAGE_100 >> 1u)) / CY_CAPSENSE_PERCENTAGE_100); + } + ptrSnsCxt++; + } + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsCSDCalibrate +****************************************************************************//** +* +* Implements IDAC calibration for a desired widget using successive +* approximation algorithm. +* +* It supports any type of CSD widgets, and works +* with multi-frequency scan and compensation IDAC features enabled. +* +* As result of function operation, the modulator IDAC that corresponds to the +* sensor with the highest capacitance (the biggest modulator IDAC) is stored +* into widget data structure. If it is dual-axis widget type (touchpad or matrix +* buttons) or if multi-frequency scan feature is enabled then the maximum +* modulator IDAC found separately for each multi-frequency channel and for +* rows/columns. +* +* If compensation IDAC is enabled, then it preserves IDAC value of +* single-sensor calibration. In dual IDAC mode each sensor was calibrated with +* equal values of modulator and compensation IDAC. +* +* After IDACs were found each sensor scanned again to get real raw count stored +* in sensor structure. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param target +* Specifies the calibration target in percentages of the maximum raw count. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDCalibrate( + uint32_t widgetId, + uint32_t target, + cy_stc_capsense_context_t * context) +{ + uint32_t freqChIndex; + uint32_t freqChNumber; + uint32_t snsIndex; + uint32_t rawTarget; + uint32_t tmpVal; + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + + uint8_t calMask; + uint8_t * ptrIdacMod; + uint8_t * ptrIdacMax; + uint8_t maxColIdac[CY_CAPSENSE_FREQ_CHANNELS_NUM] = {0u, 0u, 0u}; + uint8_t maxRowIdac[CY_CAPSENSE_FREQ_CHANNELS_NUM] = {0u, 0u, 0u}; + + cy_stc_capsense_widget_config_t const * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdCfg->ptrWdContext; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + + /* Approximate duration of Wait For Init loop */ + const uint32_t isBusyLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t isBusyWatchdogTimeUs = 200000uL; + + rawTarget = ((uint32_t)ptrWdCxt->maxRawCount * target) / CY_CAPSENSE_PERCENTAGE_100; + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + + for(snsIndex = 0u; snsIndex < (uint32_t)ptrWdCfg->numSns; snsIndex++) + { + /* Set default IDAC code */ + calMask = (uint8_t)CY_CAPSENSE_CAL_MIDDLE_VALUE; + ptrSnsCxt = &ptrWdCfg->ptrSnsContext[snsIndex]; + + + if (ptrWdCfg->numCols > snsIndex) + { + ptrIdacMod = ptrWdCxt->idacMod; + ptrIdacMax = maxColIdac; + } + else + { + ptrIdacMod = ptrWdCxt->rowIdacMod; + ptrIdacMax = maxRowIdac; + } + + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrIdacMod[freqChIndex] = calMask; + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + ptrSnsCxt[freqChIndex * context->ptrCommonConfig->numSns].idacComp = calMask; + } + } + + do + { + /* Need to configure the CSD HW block with each IDAC change */ + Cy_CapSense_CSDSetupWidgetExt(widgetId, snsIndex, context); + /* Need to discharge Cmod capacitor */ + Cy_CapSense_CSDDischargeCmod(context); + /* Scan the sensor */ + Cy_CapSense_CSDScanExt(context); + + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(isBusyWatchdogTimeUs, cpuFreqMHz, isBusyLoopDuration); + + /* Wait for EOS */ + while (CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + if(0uL == watchdogCounter) + { + break; + } + watchdogCounter--; + } + + /* Switch to the lower IDAC mask */ + calMask >>= 1u; + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + /* Update IDAC based on scan result */ + if (ptrSnsCxt[freqChIndex * context->ptrCommonConfig->numSns].raw < rawTarget) + { + ptrIdacMod[freqChIndex] &= (uint8_t)(~(uint8_t)(calMask << 1u)); + } + + ptrIdacMod[freqChIndex] |= (uint8_t)calMask; + + if(0u == ptrIdacMod[freqChIndex]) + { + ptrIdacMod[freqChIndex] = 1u; + } + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + ptrSnsCxt[freqChIndex * context->ptrCommonConfig->numSns].idacComp = ptrIdacMod[freqChIndex]; + } + } + + } + while(calMask != 0u); + + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + /* Set the max Idac value */ + if (ptrIdacMax[freqChIndex] < ptrIdacMod[freqChIndex]) + { + ptrIdacMax[freqChIndex] = ptrIdacMod[freqChIndex]; + } + } + + /* Perform scan again to get real raw count if IDAC was changed last iteration */ + Cy_CapSense_CSDSetupWidgetExt(widgetId, snsIndex, context); + Cy_CapSense_CSDScanExt(context); + + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(isBusyWatchdogTimeUs, cpuFreqMHz, isBusyLoopDuration); + + /* Wait for EOS */ + while (CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + if(0uL == watchdogCounter) + { + break; + } + watchdogCounter--; + } + } + + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrWdCxt->idacMod[freqChIndex] = maxColIdac[freqChIndex]; + + if (((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == ptrWdCfg->wdType)) + { + ptrWdCxt->rowIdacMod[freqChIndex] = maxRowIdac[freqChIndex]; + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacRowColAlignEn) + { + if (((uint32_t)ptrWdCxt->idacMod[freqChIndex] * ptrWdCxt->snsClk) < + ((uint32_t)ptrWdCxt->rowIdacMod[freqChIndex] * ptrWdCxt->rowSnsClk)) + { + tmpVal = ((uint32_t)ptrWdCxt->rowIdacMod[freqChIndex] * ptrWdCxt->rowSnsClk) / ptrWdCxt->snsClk; + if (tmpVal > CY_CAPSENSE_CAL_IDAC_MAX_VALUE) + { + tmpVal = CY_CAPSENSE_CAL_IDAC_MAX_VALUE; + } + ptrWdCxt->idacMod[freqChIndex] = (uint8_t)tmpVal; + } + else + { + tmpVal = ((uint32_t)ptrWdCxt->idacMod[freqChIndex] * ptrWdCxt->snsClk) / ptrWdCxt->rowSnsClk; + if (tmpVal > CY_CAPSENSE_CAL_IDAC_MAX_VALUE) + { + tmpVal = CY_CAPSENSE_CAL_IDAC_MAX_VALUE; + } + ptrWdCxt->rowIdacMod[freqChIndex] = (uint8_t)tmpVal; + } + } + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDCalibrateWidget +****************************************************************************//** +* +* Executes the IDAC calibration for all the sensors in the widget specified in +* the input. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_CalibrateWidget() function should be used instead. +* +* Performs a successive approximation search algorithm to find appropriate +* modulator and compensation IDAC (if enabled) values for all sensors in +* the specified widget that provide the raw count to the level +* specified by the target parameter. +* +* Calibration returns CYRET_BAD_DATA if the achieved raw count is outside +* of the range specified by the target and acceptable calibration deviation +* parameters. +* +* This function could be used when the CSD Enable IDAC auto-calibration +* parameter is enabled. Do not use this function when +* the SmartSense auto-tuning mode is configured. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param target +* Specifies the calibration target in percentages of the maximum raw count. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified widget calibration: +* - CYRET_SUCCESS - The operation is successfully completed. +* - CYRET_BAD_PARAM - The input parameter is invalid. +* - CYRET_BAD_DATA - The calibration failed and CapSense may not operate +* as expected. +* - CYRET_INVALID_STATE - The previous scanning is not completed, and +* the CapSense middleware is busy. +* +*******************************************************************************/ +cy_status Cy_CapSense_CSDCalibrateWidget( + uint32_t widgetId, + uint32_t target, + cy_stc_capsense_context_t * context) +{ + cy_status calibrateStatus = CYRET_SUCCESS; + uint32_t gainSwitch; + + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + + /* Approximate duration of Wait For Init loop */ + const uint32_t isBusyLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t isBusyWatchdogTimeUs = 200000uL; + + if((context->ptrCommonConfig->numWd <= widgetId) || + (CY_CAPSENSE_DISABLE == context->ptrCommonConfig->csdIdacAutocalEn)) + { + calibrateStatus = CY_RET_BAD_PARAM; + } + + if((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E != context->ptrWdConfig[widgetId].senseMethod) + { + calibrateStatus = CY_RET_BAD_PARAM; + } + + if(CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + /* Previous widget is being scanned, return error */ + calibrateStatus = CYRET_INVALID_STATE; + } + + if(CY_RET_SUCCESS == calibrateStatus) + { + ptrWdCfg = &context->ptrWdConfig[widgetId]; + ptrWdCfg->ptrWdContext->idacGainIndex = context->ptrCommonConfig->csdIdacGainIndexDefault; + /* Perform calibration */ + if (CY_CAPSENSE_ENABLE != context->ptrCommonConfig->csdIdacAutoGainEn) + { + Cy_CapSense_CSDCalibrate(widgetId, target, context); + } + else + { + do + { + Cy_CapSense_CSDCalibrate(widgetId, target, context); + gainSwitch = Cy_CapSense_CSDSwitchIdacGain(context); + } while(0u != gainSwitch); + } + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + /* IDAC Normalization in Dual IDAC mode */ + Cy_CapSense_CSDNormalizeIdac(ptrWdCfg, target, context); + } + + /* Perform specified widget scan to check calibration result */ + Cy_CapSense_CSDSetupWidget(widgetId, context); + Cy_CapSense_CSDScan(context); + + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(isBusyWatchdogTimeUs, cpuFreqMHz, isBusyLoopDuration); + + while (CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + if(0uL == watchdogCounter) + { + break; + } + watchdogCounter--; + } + + /* Verification of calibration result */ + + calibrateStatus = Cy_CapSense_CalibrateCheck(widgetId, target, (uint32_t)CY_CAPSENSE_SENSE_METHOD_CSD_E, context); + } + + return calibrateStatus; +} + + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDCmodPrecharge +****************************************************************************//** +* +* Initializes the Cmod charging to Vref. +* +* This function performs coarse initialization for Cmod and Csh. +* The coarse initialization is performed by HSCOMP. +* The HSCOMP monitors the Cmod voltage via Cmod sense path +* and charges the Cmod using HCAV switch via CSDBUS-A, AMUXBUS-A +* and static connection of Cmod to AMUXBUS-A. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDCmodPrecharge(cy_stc_capsense_context_t * context) +{ + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + + /* Approximate duration of Wait For Init loop */ + const uint32_t intrInitLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t initWatchdogTimeUs = 200000uL; + + /* Disable INIT interrupt */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_CSD_INTR_MASK_CLEAR_MSK); + + /* Clear all interrupt pending requests */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + /* Enable power to sub-blocks */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_HSCMP, context->ptrInternalContext->csdRegHscmpInit); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CSDCMP, CY_CAPSENSE_CSD_CSDCMP_CSDCMP_EN_MSK); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_MOD_SEL, CY_CAPSENSE_CSD_SW_FW_MOD_SEL_INIT); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_TANK_SEL, context->ptrInternalContext->csdRegSwFwTankSelInit); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, context->ptrInternalContext->csdRegSwShieldSelInit); + + /* Connect CMOD to (sense path) to HSCOMP: HMPM or HMPS or HMPT switches depend on Cmod connects to certain pad */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_P_SEL, context->ptrInternalContext->csdRegSwHsPSelInit); + + if (0u != context->ptrCommonConfig->csdShieldEn) + { + if (0u != context->ptrCommonConfig->csdCTankShieldEn) + { + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, (uint32_t)context->ptrCommonConfig->pinCsh, + CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_AMUXA); + } + } + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_RES, context->ptrInternalContext->csdRegSwResInit); + + /* Start SEQUENCER for coarse initialization for Cmod */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_CSD_SEQ_START_SEQ_MODE_MSK | + CY_CAPSENSE_CSD_SEQ_START_START_MSK); + + /* Init Watchdog Counter to prevent a hang */ + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(initWatchdogTimeUs, cpuFreqMHz, intrInitLoopDuration); + + /* Approximate duration of Wait For Init loop */ + while((0u != (CY_CAPSENSE_CSD_SEQ_START_START_MSK & + Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START)))) + { + if(0uL == watchdogCounter) + { + break; + } + + watchdogCounter--; + } + + if (0u == watchdogCounter) + { + /* Set sequencer to idle state if coarse initialization fails */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_CSD_SEQ_START_ABORT_MSK); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDTriggerScan +****************************************************************************//** +* +* Triggers the scanning. +* +* This function trigger the fine initialization (scan some dummy cycles) and +* start sampling. +* For the fine initialization and sampling, Cmod is statically connected to +* AMUXBUS-A and in every conversion (one cycle of SnsClk), the sensor +* capacitance is charged from Cmod and discharged to ground using the +* switches in GPIO cell. The CSDCOMP monitors voltage on Cmod using the +* sense path and charges Cmod back to Vref using IDACs by connecting IDAC +* to CSDBUS-A and then the AMUXBUS-A. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDTriggerScan(cy_stc_capsense_context_t * context) +{ + /* Clear previous interrupts */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + /* Enable SAMPLE interrupt */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_CSD_INTR_MASK_SAMPLE_MSK); + + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_P_SEL, context->ptrInternalContext->csdRegSwHsPSelScan); + + /* Set scanning configuration for switches */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_MOD_SEL, CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SCAN); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_TANK_SEL, context->ptrInternalContext->csdRegSwFwTankSelScan); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, context->ptrInternalContext->csdRegSwShieldSelScan); + + if (0u != context->ptrCommonConfig->csdShieldEn) + { + if (0u != context->ptrCommonConfig->csdCTankShieldEn) + { + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, (uint32_t)context->ptrCommonConfig->pinCsh, + CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_AMUXB); + } + } + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_RES, context->ptrInternalContext->csdRegSwResScan); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CSDCMP, CY_CAPSENSE_CSD_CSDCMP_CSDCMP_EN_MSK); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_HSCMP, context->ptrInternalContext->csdRegHscmpScan); + + /* Force the LFSR to it's initial state (all ones) */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_PERIOD, + Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_PERIOD) | + CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_CLEAR_MSK | CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_BITS_MSK); + + /* Start SEQUENCER for fine initialization scan for Cmod and then for normal scan */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_CSD_SEQ_START_AZ0_SKIP_MSK | + CY_CAPSENSE_CSD_SEQ_START_AZ1_SKIP_MSK | + CY_CAPSENSE_CSD_SEQ_START_START_MSK); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDScanISR +****************************************************************************//** +* +* This is an internal ISR function to handle the CSD sensing method operation. +* +* This handler covers the following functionality: +* - Read the result of the measurement and store it into the corresponding +* register of the data structure. +* - If the Noise Metric functionality is enabled, then check the number of bad +* conversions and repeat the scan of the current sensor of the number of bad +* conversions is greater than the Noise Metric Threshold. +* - Initiate the scan of the next sensor for multiple sensor scanning mode. +* - Update the status register in the data structure. +* - Switch the CSD HW block to the default state if scanning of all the sensors is +* completed. +* +* This is an internal ISR function for the single-sensor scanning implementation. +* +* \param capsenseContext +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSDScanISR(void * capsenseContext) +{ + uint32_t rawData; + uint32_t maxCount; + cy_stc_capsense_context_t * cxt = (cy_stc_capsense_context_t *)capsenseContext; + cy_stc_active_scan_sns_t * ptrActive = cxt->ptrActiveScanSns; + + /* Clear pending interrupt */ + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + /* Open HCBV and HCBG switches */ + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, 0u); + + /* Save raw count */ + maxCount = (1uL << ptrActive->ptrWdContext->resolution) - 1uL; + rawData = Cy_CSD_ReadReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_RESULT_VAL1) & CY_CAPSENSE_CSD_RESULT_VAL1_VALUE_MSK; + + if(rawData > maxCount) + { + rawData = maxCount; + } + ptrActive->ptrSnsContext->raw = (uint16_t)rawData; + + /* Either complete scan or initiate new one */ + if((CY_CAPSENSE_ENABLE == cxt->ptrCommonConfig->mfsEn) && + (ptrActive->mfsChannelIndex < CY_CAPSENSE_MFS_CH2_INDEX)) + { + Cy_CapSense_CSDInitNextChScan(cxt); + } + else if ((CY_CAPSENSE_SCAN_SCOPE_SGL_WD == ptrActive->scanScopeAll) && + (CY_CAPSENSE_SCAN_SCOPE_SGL_SNS == ptrActive->scanScopeSns)) + { + Cy_CapSense_ClrBusyFlags(cxt); + } + else + { + /* Disable sensor */ + Cy_CapSense_CSDDisconnectSnsExt(cxt); + /* Scan the next sensor */ + Cy_CapSense_CSDInitNextSnsScan(cxt); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDInitNextSnsScan +****************************************************************************//** +* +* This function initializes the next sensor scan. +* +* The function increments the sensor index, updates sense clock for matrix +* or touchpad widgets only, sets up Compensation IDAC, enables the sensor and +* scans it. When all the sensors are scanned it continues to set up the next +* widget until all the widgets are scanned. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDInitNextSnsScan(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + uint32_t sensorId = ptrActive->sensorIndex + 1uL; + + /* Check if all the sensors are scanned in widget */ + if (ptrActive->ptrWdConfig->numSns > sensorId) + { + /* Switch to the next sensor */ + Cy_CapSense_InitActivePtrSns(sensorId, context); + + Cy_CapSense_CSDCalculateScanDuration(context); + Cy_CapSense_CSDConfigClock(context); + Cy_CapSense_CSDConnectSnsExt(context); + Cy_CapSense_CSDSetUpIdacs(context); + + Cy_CapSense_CSDStartSample(context); + } + else + { + if (CY_CAPSENSE_SCAN_SCOPE_ALL_WD == ptrActive->scanScopeAll) + { + /* Configure and begin scanning next widget */ + Cy_CapSense_SsPostAllWidgetsScan(context); + } + else + { + /* All the widgets are scanned */ + Cy_CapSense_ClrBusyFlags(context); + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDInitNextChScan +****************************************************************************//** +* +* This function initializes the next frequency of the sensor scan. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSDInitNextChScan(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + CY_ASSERT(ptrActive->mfsChannelIndex < CY_CAPSENSE_MFS_CH2_INDEX); + + ptrActive->mfsChannelIndex++; + ptrActive->ptrSnsContext += context->ptrCommonConfig->numSns; + + Cy_CapSense_CSDChangeClkFreq((uint32_t)ptrActive->mfsChannelIndex, context); + Cy_CapSense_CSDSetUpIdacs(context); + Cy_CapSense_CSDStartSample(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSDChangeClkFreq +****************************************************************************//** +* +* This function changes the sensor clock frequency by configuring +* the corresponding divider. +* +* \param channelIndex +* The frequency channel index. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CapSense_CSDChangeClkFreq(uint32_t channelIndex, cy_stc_capsense_context_t * context) +{ + const cy_stc_capsense_widget_context_t * ptrWdCxt = context->ptrActiveScanSns->ptrWdContext; + uint32_t snsClkDivider; + uint32_t snsClkSrc = (uint32_t)ptrWdCxt->snsClkSource & ((uint32_t)~(uint32_t)CY_CAPSENSE_CLK_SOURCE_AUTO_MASK); + uint32_t regConfig = 0u; + uint32_t freqOffset; + uint32_t conversionsNum; + + /* Getting row clock divider for matrix buttons or touchpad widgets */ + if (context->ptrActiveScanSns->ptrWdConfig->numCols <= context->ptrActiveScanSns->sensorIndex) + { + snsClkDivider = ptrWdCxt->rowSnsClk; + } + else + { + snsClkDivider = ptrWdCxt->snsClk; + } + + /* Change the divider based on the chId */ + switch (channelIndex) + { + case CY_CAPSENSE_MFS_CH1_INDEX: + { + freqOffset = context->ptrCommonConfig->csdMfsDividerOffsetF1; + break; + } + case CY_CAPSENSE_MFS_CH2_INDEX: + { + freqOffset = context->ptrCommonConfig->csdMfsDividerOffsetF2; + break; + } + default: + { + freqOffset = 0u; + break; + } + } + + if ((CY_CAPSENSE_CLK_SOURCE_PRS8 == snsClkSrc) || (CY_CAPSENSE_CLK_SOURCE_PRS12 == snsClkSrc)) + { + freqOffset <<= 1uL; + } + + snsClkDivider += freqOffset; + + /* Set Number Of Conversions based on scanning resolution */ + conversionsNum = Cy_CapSense_CSDGetNumberOfConversions(snsClkDivider, (uint32_t)ptrWdCxt->resolution, (uint32_t)snsClkSrc); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_NORM_CNT, (conversionsNum & CY_CAPSENSE_CSD_SEQ_NORM_CNT_CONV_CNT_MSK)); + + /* Configuring PRS SEL_BIT and decreasing divider in case of PRS */ + if ((CY_CAPSENSE_CLK_SOURCE_PRS8 == snsClkSrc) || (CY_CAPSENSE_CLK_SOURCE_PRS12 == snsClkSrc)) + { + regConfig = CY_CAPSENSE_CSD_SENSE_PERIOD_SEL_LFSR_MSB_MSK; + snsClkDivider >>= 1u; + } + + /* Check divider value */ + if (0u == snsClkDivider) + { + snsClkDivider = 1u; + } + + regConfig |= ((snsClkSrc << CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SIZE_POS) | (snsClkDivider - 1u)); + + /* Update reg value with divider and configuration */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_PERIOD, regConfig); +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_csd.h b/cy_capsense_csd.h new file mode 100644 index 0000000..b61b784 --- /dev/null +++ b/cy_capsense_csd.h @@ -0,0 +1,91 @@ +/***************************************************************************//** +* \file cy_capsense_csd.h +* \version 1.1 +* +* \brief +* This file provides the function prototypes specific to the CSD sensing +* method implementation. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_CSD_H) +#define CY_CAPSENSE_CSD_H + +#include "cy_syslib.h" +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/**************************************************************************** +* Register and mode mask definition +****************************************************************************/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_DSI_SEL (0x00000000uL) +#define CY_CAPSENSE_DEFAULT_CSD_INTR_SET (0x00000000uL) +#define CY_CAPSENSE_DEFAULT_SW_HS_N_SEL (0x00000000uL) +#define CY_CAPSENSE_DEFAULT_CSD_ADC_CTL (0x00000000uL) + +/* SW_FW_MOD_SEL switches states */ +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SCAN (0x00000000uL) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_INIT (0x00000000uL) + +#define CY_CAPSENSE_EXT_CAP_DISCHARGE_TIME (1u) + +/*************************************** +* Function Prototypes +**************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_CSDCalibrateWidget(uint32_t widgetId, uint32_t target, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDSetupWidget(uint32_t widgetId, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDSetupWidgetExt(uint32_t widgetId, uint32_t sensorId, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDScan(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDScanExt(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDConnectSns(const cy_stc_capsense_pin_config_t * snsAddrPtr, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDDisconnectSns(const cy_stc_capsense_pin_config_t * snsAddrPtr, const cy_stc_capsense_context_t * context); + +/** \} */ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_CSDDisableMode(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDInitialize(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDStartSample(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDDisableShieldElectrodes(const cy_stc_capsense_context_t * context); + +uint32_t Cy_CapSense_CSDGetNumberOfConversions(uint32_t snsClkDivider, uint32_t resolution, uint32_t snsClkSrc); +void Cy_CapSense_CSDSetUpIdacs(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDSnsStateCheck(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDCalculateScanDuration(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDConnectSnsExt(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDDisconnectSnsExt(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDConfigClock(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDClearSensors(const cy_stc_capsense_context_t * context); +void Cy_CapSense_CSDSetWidgetSenseClkSrc(const cy_stc_capsense_widget_config_t * ptrWdConfig); +uint32_t Cy_CapSense_CSDCalcPrsSize(uint32_t snsClkDivider, uint32_t resolution); +void Cy_CapSense_CSDScanISR(void * capsenseContext); + +/** \} \endcond */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_CSD_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_csx.c b/cy_capsense_csx.c new file mode 100644 index 0000000..ddf4167 --- /dev/null +++ b/cy_capsense_csx.c @@ -0,0 +1,1323 @@ +/***************************************************************************//** +* \file cy_capsense_csx.c +* \version 1.1 +* +* \brief +* This file defines the data structure global variables and provides +* implementation for the low-level functions of the CSX part of +* the Sensing module. The file contains the functions used for the CSD HW block +* initialization, calibration, and scanning. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include "cy_syslib.h" +#include "cy_sysclk.h" +#include "cy_gpio.h" +#include "cy_csd.h" + +#include "cy_device_headers.h" +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_csx.h" +#include "cy_capsense_sensing.h" + + +/******************************************************************************* +* Local function declarations +*******************************************************************************/ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +static void Cy_CapSense_CSXChangeClkFreq(uint32_t channelIndex, cy_stc_capsense_context_t * context); + +static void Cy_CapSense_CSXStartSample(cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSXInitNextChScan(cy_stc_capsense_context_t * context); +static void Cy_CapSense_CSXInitNextScan(cy_stc_capsense_context_t * context); + +__STATIC_INLINE void Cy_CapSense_CSXStartSampleExt(cy_stc_capsense_context_t * context); + +/** \} \endcond */ + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXInitialize +****************************************************************************//** +* +* Performs hardware and firmware initialization required for the CSX operation +* of the CapSense middleware. +* +* This function initializes hardware to perform the CSX sensing operation. +* If both CSX and CSD sensing methods are used in the +* middleware, this function is called by the Cy_CapSense_SetupWidget() to +* change hardware configured for CSD sensing method to re-initialize for the +* CSX sensing method. +* +* If the CSD and CSX widgets are used in the middleware, do not +* mix the CSD widgets between the CSX widgets. Instead, place all +* CSX widgets in the required scanning order and then place the CSD widgets +* in the CapSense Configurator tool. +* For the middleware, this action will eliminate the need for changing +* the CSD HW block configuration for every widget scan and will increase the +* execution speed in the Cy_CapSense_ScanAllWidgets() when the function is +* called. +* +* Similarly, set up and scan all the CSX widgets in such +* a sequence that the Cy_CapSense_SetupWidget() does not need to perform +* hardware sensing-configuration switches. +* +* Do not call this function directly from +* the application program. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXInitialize(cy_stc_capsense_context_t * context) +{ + uint32_t interruptState; + uint32_t tmpRegVal; + + Cy_CapSense_DischargeExtCapacitors(context); + + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetDrivemode(context->ptrCommonConfig->portCintA, (uint32_t)context->ptrCommonConfig->pinCintA, CY_GPIO_DM_ANALOG); + Cy_GPIO_SetDrivemode(context->ptrCommonConfig->portCintB, (uint32_t)context->ptrCommonConfig->pinCintB, CY_GPIO_DM_ANALOG); + Cy_SysLib_ExitCriticalSection(interruptState); + + /* Clear all pending interrupts of the CSD HW block */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + + /* Enable the End Of Scan interrupt */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_DEFAULT_CSD_INTR_MASK_CFG); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_HSCMP, CY_CAPSENSE_DEFAULT_CSD_HSCMP_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_AMBUF, CY_CAPSENSE_DEFAULT_CSD_AMBUF_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_REFGEN, context->ptrInternalContext->csxRegRefgen ); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CSDCMP, CY_CAPSENSE_DEFAULT_CSD_CSDCMP_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACA, CY_CAPSENSE_DEFAULT_CSD_IDACA_CFG); + + if (0u != context->ptrCommonConfig->csdIdacCompEn) + { + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACB, CY_CAPSENSE_DEFAULT_CSD_IDACB_CFG); + } + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_RES,context->ptrInternalContext->csxRegSwResInit); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_DUTY, CY_CAPSENSE_DEFAULT_CSD_SENSE_DUTY_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_P_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_HS_P_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_N_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_HS_N_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_SHIELD_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_AMUXBUF_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_AMUXBUF_SEL_CFG); + + tmpRegVal = Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_BYP_SEL); + tmpRegVal &= ~(CY_CAPSENSE_CSD_SW_BYP_SEL_SW_BYA_MSK); + tmpRegVal |= CY_CAPSENSE_DEFAULT_CSD_SW_BYP_SEL_CFG; + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_BYP_SEL, tmpRegVal); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_CMP_P_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_CMP_P_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_CMP_N_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_CMP_N_SEL_CFG); + + tmpRegVal = Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_REFGEN_SEL); + tmpRegVal &= ~CY_CAPSENSE_DEFAULT_CSD_SW_REFGEN_SEL_MSK; + tmpRegVal |= context->ptrInternalContext->regSwRefGenSel ; + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_REFGEN_SEL, tmpRegVal); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_MOD_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_FW_MOD_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_TANK_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_FW_TANK_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_DSI_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_DSI_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IO_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_IO_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_TIME, 0u); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_INIT_CNT, (uint32_t)context->ptrCommonConfig->csxFineInitTime); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_NORM_CNT, CY_CAPSENSE_DEFAULT_CSD_SEQ_NORM_CNT_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_ADC_CTL, CY_CAPSENSE_DEFAULT_CSD_ADC_CTL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_DEFAULT_CSD_SEQ_START_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CONFIG, context->ptrInternalContext->csxRegConfigInit); + + Cy_CapSense_SetClkDivider((uint32_t)context->ptrCommonContext->modCsxClk - 1u, context); + + /* Set all IO states to the default state */ + Cy_CapSense_SetIOsInDefaultState(context); + + /* Enable the CSD HW block interrupt and set interrupt vector to CSX sensing method */ + context->ptrActiveScanSns->ptrISRCallback = &Cy_CapSense_CSXScanISR; + + context->ptrActiveScanSns->mfsChannelIndex = 0u; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXElectrodeCheck +****************************************************************************//** +* +* Check whether electrodes were previously connected using +* the Cy_CapSense_CSXSetupWidgetExt() function and if yes, disconnect them. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXElectrodeCheck(cy_stc_capsense_context_t * context) +{ + if (CY_CAPSENSE_SNS_CONNECTED == context->ptrActiveScanSns->connectedSnsState) + { + /* Disconnect all Tx pins */ + Cy_CapSense_CSXDisconnectTxExt(context); + /* Disconnect all Rx pins */ + Cy_CapSense_CSXDisconnectRxExt(context); + /* Mark the current sensor as disconnected */ + context->ptrActiveScanSns->connectedSnsState = CY_CAPSENSE_SNS_DISCONNECTED; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXDisableMode +****************************************************************************//** +* +* This function disables CSX mode. +* +* To disable CSX mode, the following tasks are performed: +* 1. Disconnect previous CSX electrode if it has been connected. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXDisableMode(cy_stc_capsense_context_t * context) +{ + /* Disconnect previous CSX electrode if it has been connected */ + Cy_CapSense_CSXElectrodeCheck(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXSetupWidget +****************************************************************************//** +* +* Performs the initialization required to scan the specified CSX widget. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_SetupWidget() function should be used instead. +* +* This function prepares the middleware to scan all the sensors in the +* specified CSX widget by executing the following tasks: +* 1. Configure the CSD HW block if it is not configured to perform the +* CSX sensing method used by the specified widget. +* 2. Initialize the CSD HW block with specific sensing configuration (e.g. +* sensor clock, scan resolution) used by the widget. +* 3. Disconnect all previously connected electrodes, if the electrodes +* connected by the Cy_CapSense_CSDSetupWidgetExt(), +* Cy_CapSense_CSXSetupWidgetExt() functions are not disconnected. +* +* This function does not start sensor scanning. The Cy_CapSense_CSXScan() +* function must be called to start the scan sensors in the widget. If this +* function is called more than once, it does not break the middleware +* operation, but only the last initialized widget is in effect. +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for example faster execution). +* +* The status of a sensor scan must be checked using the Cy_CapSense_IsBusy() +* function prior to starting a next scan or setting up another widget. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXSetupWidget(uint32_t widgetId, cy_stc_capsense_context_t * context) +{ + /* variable to access widget details */ + uint32_t snsClkDivider; + uint32_t snsClkSrc; + uint32_t tmpRegVal; + + Cy_CapSense_SwitchSensingMode((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E, context); + /* + * Check whether CSX electrodes were previously connected using + * Cy_CapSense_CSXSetupWidgetExt and if yes, disconnect them + */ + Cy_CapSense_CSXElectrodeCheck(context); + /* Set up widget and its first sensor IDs and pointers to have assess to them after scanning */ + Cy_CapSense_InitActivePtr(widgetId, 0u, context); + /* Number of conversion and maxRawCount setup */ + tmpRegVal = (uint32_t)context->ptrActiveScanSns->ptrWdContext->resolution; + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_NORM_CNT, tmpRegVal); + context->ptrActiveScanSns->ptrWdContext->maxRawCount = (uint16_t)tmpRegVal * + (context->ptrActiveScanSns->ptrWdContext->snsClk - CY_CAPSENSE_CSX_DEADBAND_CYCLES_NUMBER); + + /* SnsClk setup */ + snsClkDivider = (uint32_t) context->ptrActiveScanSns->ptrWdContext->snsClk; + + /* Check divider value */ + if (0u == snsClkDivider) + { + snsClkDivider = 1u; + } + snsClkSrc = (uint32_t)context->ptrActiveScanSns->ptrWdContext->snsClkSource & (uint32_t)~((uint32_t)CY_CAPSENSE_CLK_SOURCE_AUTO_MASK); + tmpRegVal = ((snsClkSrc << CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SIZE_POS) | (snsClkDivider - 1u) | + CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_CLEAR_MSK | CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_BITS_MSK); + /* Update reg value with divider and configuration */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_PERIOD, tmpRegVal); +} + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXSetupWidgetExt +****************************************************************************//** +* +* Performs extended initialization required to scan a specified sensor in +* a widget using CSX sensing method. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_SetupWidgetExt() function should be used instead. +* +* This function performs the same tasks of Cy_CapSense_CSXSetupWidget() and +* also connects and configures specified sensor for scan. Hence this +* function, along with Cy_CapSense_CSXScanExt() function, can be used to +* scan a specific sensor in the widget. +* +* This function should be called for a widget that is configured to use +* CSX sensing method. Using this function on a non-CSX sensing widget +* would cause an unexpected result. +* +* This function requires using the Cy_CapSense_CSXScanExt() function to +* initiate a scan. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's +* specific use cases (for example faster execution). +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXSetupWidgetExt( + uint32_t widgetId, + uint32_t sensorId, + cy_stc_capsense_context_t * context) +{ + /* Initialize widget */ + Cy_CapSense_CSXSetupWidget(widgetId, context); + + /* Initialize sensor data structure pointer to appropriate address */ + Cy_CapSense_InitActivePtrSns(sensorId, context); + + /* Connect current sensor`s Tx and Rx IOs for scan + * and set flag to indicate that IOs should be disconnected */ + Cy_CapSense_CSXConnectTxExt(context); + Cy_CapSense_CSXConnectRxExt(context); +} + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXScan +****************************************************************************//** +* +* This function initiates a scan for the sensors of the widget initialized +* by the Cy_CapSense_CSXSetupWidget() function. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_Scan() function should be used instead. +* +* This function does the following tasks: +* 1. Connects the first sensor of the widget. +* 2. Configures the IDAC value. +* 3. Starts scanning for the first sensor in the widget. +* +* This function is called by the Cy_CapSense_Scan() if the given +* widget uses the CSX sensing method. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for example faster execution). +* +* This function is called when no scanning is in progress. I.e. +* Cy_CapSense_IsBusy() returns a non-busy status and the widget must be +* preconfigured using the Cy_CapSense_CSXSetupWidget() function prior +* to calling this function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXScan(cy_stc_capsense_context_t * context) +{ + Cy_CapSense_InitActivePtrSns(0u, context); + + /* Connect electrodes */ + Cy_CapSense_CSXConnectTxExt(context); + Cy_CapSense_CSXConnectRxExt(context); + + /* Set Start of scan flag */ + Cy_CapSense_SetBusyFlags(context); + /* Set scope flag */ + context->ptrActiveScanSns->scanScopeSns = CY_CAPSENSE_SCAN_SCOPE_ALL_SNS; + + Cy_CapSense_CSXStartSample(context); +} + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXScanExt() +****************************************************************************//** +* +* Starts the CSD conversion on the preconfigured sensor. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_ScanExt() function should be used instead. +* +* This function performs scanning of a specific sensor in the widget +* previously initialized using the Cy_CapSense_CSXSetupWidgetExt() function. +* +* This function is called when no scanning is in progress. +* I.e. Cy_CapSense_IsBusy() returns a non-busy status and the widget must +* be preconfigured using Cy_CapSense_CSXSetupWidgetExt() function prior +* to calling this function. Calling this function directly from +* the application program is not recommended. This function is used to +* implement only the user's specific use cases (for example faster execution). +* +* This function does not disconnect sensor GPIOs from CSD HW block at the +* end of a scan, therefore making subsequent scan of the same sensor is faster. +* If sensor must be disconnected after the scan, +* the Cy_CapSense_CSXDisconnectTx() or Cy_CapSense_CSXDisconnectRx() functions +* can be used. +* +* Calling Cy_CapSense_SetupWidget(), Cy_CapSense_CSXSetupWidget(), +* Cy_CapSense_ScanAllWidgets(), or if Cy_CapSense_RunTuner() returns +* CY_CAPSENSE_STATUS_RESTART_DONE status invalidated initialization +* made by this function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXScanExt(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + /* Set MFS channel index to 0 */ + ptrActive->mfsChannelIndex = 0u; + + /* Initialize the Active Context pointer with the CH0 context */ + ptrActive->ptrSnsContext = &ptrActive->ptrWdConfig->ptrSnsContext[ptrActive->sensorIndex]; + + /* Set busy flag and start conversion */ + Cy_CapSense_SetBusyFlags(context); + /* Set scope flag */ + context->ptrActiveScanSns->scanScopeSns = CY_CAPSENSE_SCAN_SCOPE_SGL_SNS; + + Cy_CapSense_CSXStartSample(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXCalibrateWidget +****************************************************************************//** +* +* Executes the IDAC calibration for all the sensors in the widget specified in +* the input. +* +* \note This function is obsolete and kept for backward compatibility only. +* The Cy_CapSense_CalibrateWidget() function should be used instead. +* +* Performs a successive approximation search algorithm to find appropriate +* IDAC values for all sensors in the specified widget that provide +* the raw count to the level specified by the target parameter. +* +* Calibration returns CYRET_BAD_DATA if the achieved raw count is outside +* of the range specified by the target and acceptable calibration deviation +* parameters. +* +* This function could be used when the CSX Enable IDAC auto-calibration +* parameter is enabled. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param target +* Specifies the calibration target in percentages of the maximum raw count. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified widget calibration: +* - CYRET_SUCCESS - The operation is successfully completed. +* - CYRET_BAD_PARAM - The input parameter is invalid. +* - CYRET_BAD_DATA - The calibration failed and CapSense may not operate +* as expected. +* - CYRET_INVALID_STATE - The previous scanning is not completed, and +* the CapSense middleware is busy. +* +*******************************************************************************/ +cy_status Cy_CapSense_CSXCalibrateWidget( + uint32_t widgetId, + uint32_t target, + cy_stc_capsense_context_t * context) +{ + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + + uint32_t freqChIndex; + uint32_t freqChNumber; + + cy_status calibrateStatus = CY_RET_SUCCESS; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + cy_stc_capsense_sensor_context_t * ptrActSnsContext; + + uint32_t rawTarget; + uint32_t totalSns; + uint32_t calibrationIndex; + /* Currently used IDAC-bit */ + uint8_t curIdacMask = CY_CAPSENSE_CAL_MIDDLE_VALUE; + /* Next used IDAC-bit */ + uint8_t nextIdacMask = (curIdacMask >> 1u); + + /* Approximate duration of Wait For Init loop */ + const uint32_t isBusyLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t isBusyWatchdogTimeUs = 200000uL; + + + if((context->ptrCommonConfig->numWd <= widgetId) || + (CY_CAPSENSE_DISABLE == context->ptrCommonConfig->csxIdacAutocalEn)) + { + calibrateStatus = CY_RET_BAD_PARAM; + } + + if((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E != context->ptrWdConfig[widgetId].senseMethod) + { + calibrateStatus = CY_RET_BAD_PARAM; + } + + if(CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + /* Previous widget is being scanned, return error */ + calibrateStatus = CYRET_INVALID_STATE; + } + + if(CY_RET_SUCCESS == calibrateStatus) + { + ptrWdCfg = &context->ptrWdConfig[widgetId]; + ptrActSnsContext = ptrWdCfg->ptrSnsContext; + totalSns = ptrWdCfg->numSns; + + /* Calculate target raw count */ + rawTarget = ((uint32_t)context->ptrWdContext[widgetId].maxRawCount * target) / CY_CAPSENSE_PERCENTAGE_100; + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + /* Clear raw count registers and IDAC registers of all the sensors/nodes */ + for (calibrationIndex = 0u; calibrationIndex < totalSns; calibrationIndex++) + { + ptrActSnsContext[calibrationIndex + (freqChIndex * context->ptrCommonConfig->numSns)].raw = 0u; + ptrActSnsContext[calibrationIndex + (freqChIndex * context->ptrCommonConfig->numSns)].idacComp = curIdacMask; + } + } + /* Perform binary search for accurate IDAC value for each sensor/node */ + do + { + /* Scan all the sensors/nodes in widget */ + (void)Cy_CapSense_SetupWidget(widgetId, context); + (void)Cy_CapSense_Scan(context); + + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(isBusyWatchdogTimeUs, cpuFreqMHz, isBusyLoopDuration); + + /* Wait for EOS */ + while (CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + if(0uL == watchdogCounter) + { + break; + } + + watchdogCounter--; + } + + /* Set pointer to the widget's first sensor data */ + ptrActSnsContext = ptrWdCfg->ptrSnsContext; + + for (freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + /* Check raw count and adjust IDAC, loop through all the sensors/nodes */ + for (calibrationIndex = 0u; calibrationIndex < totalSns; calibrationIndex++) + { + /* Check whether the current raw count is above target. + * If yes, clear the MS bit of bit. + * If no, keep the MS bit and set next bit. + */ + if (ptrActSnsContext[calibrationIndex + (freqChIndex * context->ptrCommonConfig->numSns)].raw > rawTarget) + { + ptrActSnsContext[calibrationIndex + (freqChIndex * context->ptrCommonConfig->numSns)].idacComp &= (uint8_t)(~curIdacMask); + } + ptrActSnsContext[calibrationIndex + (freqChIndex * context->ptrCommonConfig->numSns)].idacComp |= nextIdacMask; + } + } + /* Shift both current IDAC and pre IDAC values to the right by 1 */ + curIdacMask = nextIdacMask; + nextIdacMask = nextIdacMask >> 1u; + } + while (curIdacMask != 0u); + calibrateStatus = CY_RET_SUCCESS; + } + + if(CY_RET_SUCCESS == calibrateStatus) + { + /* Perform specified widget scan to check calibration result */ + /* Scan all the sensors/nodes in widget */ + (void)Cy_CapSense_SetupWidget(widgetId, context); + (void)Cy_CapSense_Scan(context); + + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(isBusyWatchdogTimeUs, cpuFreqMHz, isBusyLoopDuration); + + /* Wait for EOS */ + while (CY_CAPSENSE_SW_STS_BUSY == (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + if(0uL == watchdogCounter) + { + calibrateStatus = CY_RET_TIMEOUT; + break; + } + + watchdogCounter--; + } + + calibrateStatus = Cy_CapSense_CalibrateCheck(widgetId, target, (uint32_t)CY_CAPSENSE_SENSE_METHOD_CSX_E, context); + } + + return(calibrateStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXSetUpIdacs +****************************************************************************//** +* +* Configures IDAC for the CSX sensing method. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXSetUpIdacs(cy_stc_capsense_context_t * context) +{ + uint32_t tmpRegVal; + + tmpRegVal = (uint32_t)context->ptrActiveScanSns->ptrSnsContext->idacComp & CY_CAPSENSE_CSD_IDACA_VAL_MSK; + tmpRegVal = tmpRegVal | (((uint32_t)context->ptrCommonConfig->csxIdacGainInit << CSD_IDACA_RANGE_Pos) + & CY_CAPSENSE_CSD_IDACA_RANGE_MSK); + tmpRegVal = tmpRegVal | CY_CAPSENSE_DEFAULT_CSD_IDACA_CFG; + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACA, tmpRegVal); +} + +/******************************************************************************* +* Function Name: Cy_CapSense_SsCSXStartSample +****************************************************************************//** +* +* Starts scanning for the CSX widget. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSXStartSample(cy_stc_capsense_context_t * context) +{ + /* Set up IDAC Value */ + Cy_CapSense_CSXSetUpIdacs(context); + + /* Clear previous interrupts */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + /* Enable interrupt */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_CSD_INTR_MASK_SAMPLE_MSK); + + if(NULL != context->ptrCommonContext->ptrSSCallback) + { + context->ptrCommonContext->ptrSSCallback(context->ptrActiveScanSns); + } + + Cy_CapSense_CSXStartSampleExt(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXConnectRx +****************************************************************************//** +* +* Connects port pin (an Rx electrode) to the CSD HW block using AMUX bus. +* +* This function can be used to customize the default sensor connection +* by connecting one or more pins to an existing sensor as an Rx electrode +* prior to initiating scan of the sensor. +* +* The function ignores whether the sensor is a ganged sensor and +* connects only a specified port pin to the CSD HW block. This function can +* only use GPIOs that is already assigned to CapSense middleware. +* +* The functions that perform a setup and scan of a sensor/widget do not +* take into account changes in the design made by +* the Cy_CapSense_CSXConnectRx() function. Hence all GPIOs connected +* using this function must be disconnected using +* the Cy_CapSense_CSXDisconnectRx() function prior to initializing +* new widgets. Use this function in StartSample +* callback (see the \ref group_capsense_callbacks section for details) +* or with low-level functions that perform a single-sensor scanning. +* +* Scanning should be completed before calling this function. +* +* \param rxPtr +* Specifies the pointer to the cy_stc_capsense_pin_config_t object belonging to +* a sensor which to be connected to the CSD HW block as an Rx electrode. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of using the function to perform port pin re-connection: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_CSXConnect +* +*******************************************************************************/ +void Cy_CapSense_CSXConnectRx( + const cy_stc_capsense_pin_config_t * rxPtr, + cy_stc_capsense_context_t * context) +{ + Cy_CapSense_SsConfigPinRegisters(rxPtr->pcPtr, (uint32_t)rxPtr->pinNumber, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_AMUXA); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXConnectTx +****************************************************************************//** +* +* Connects port pin (a Tx electrode) to the CSD HW block. +* +* This function can be used to customize the default sensor connection +* by connecting one or more pins to an existing sensor as a Tx electrode +* prior to initiating scan of the sensor. +* +* The function ignores whether the sensor is a ganged sensor and +* connects only a specified port pin to the CSD HW block. This function can +* only use GPIOs that is already assigned to CapSense middleware. +* +* The functions that perform a setup and scan of a sensor/widget do not +* take into account changes in the design made by +* the Cy_CapSense_CSXConnectTx() function. Hence all GPIOs connected +* using this function must be disconnected using +* the Cy_CapSense_CSXDisconnectTx() function prior to initializing +* new widgets. Use this function in StartSample +* callback (see the \ref group_capsense_callbacks section for details) +* or with low-level functions that perform a single-sensor scanning. +* +* Scanning should be completed before calling this function. +* +* \param txPtr +* Specifies the pointer to the cy_stc_capsense_pin_config_t object belonging to +* a sensor which to be connected to the CSD HW block as a Tx electrode. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of using the function to perform port pin re-connection: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_CSXConnect +* +*******************************************************************************/ +void Cy_CapSense_CSXConnectTx( + const cy_stc_capsense_pin_config_t * txPtr, + cy_stc_capsense_context_t * context) +{ + Cy_CapSense_SsConfigPinRegisters(txPtr->pcPtr, (uint32_t)txPtr->pinNumber, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_CSD_SHIELD); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXDisconnectRx +****************************************************************************//** +* +* Disconnects port pin (an Rx electrode) from the CSD HW block by disconnecting +* it from the AMUX bus. +* +* This function can be used to disconnect a sensor connected +* using the Cy_CapSense_CSXConnectRx() function. In addition, this +* function can be used to customize default sensor connection by +* disconnecting one or more already connected sensors prior to +* initiating scan of the sensor. +* +* This function works identically to the Cy_CapSense_CSDConnectRx() function +* except it disconnects the specified port pin used by the sensor. +* +* Scanning should be completed before calling this function. +* +* \param rxPtr +* Specifies the pointer to the cy_stc_capsense_pin_config_t object belonging +* to an Rx pin sensor to be disconnected from the CSD HW block. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of using the function to perform port pin re-connection: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_CSXConnect +* +*******************************************************************************/ +void Cy_CapSense_CSXDisconnectRx( + const cy_stc_capsense_pin_config_t * rxPtr, + cy_stc_capsense_context_t * context) +{ + uint32_t interruptState; + + Cy_CapSense_SsConfigPinRegisters(rxPtr->pcPtr, (uint32_t)rxPtr->pinNumber, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_GPIO); + + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_Clr(rxPtr->pcPtr, (uint32_t)rxPtr->pinNumber); + Cy_SysLib_ExitCriticalSection(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXDisconnectTx +****************************************************************************//** +* +* Disconnects port pin (a Tx electrode) from the CSD HW block. +* +* This function can be used to disconnect a sensor connected +* using the Cy_CapSense_CSXConnectTx() function. In addition, this +* function can be used to customize default sensor connection by +* disconnecting one or more already connected sensors prior to +* initiating scan of the sensor. +* +* This function works identically to the Cy_CapSense_CSDConnectTx() function +* except it disconnects the specified port pin used by the sensor. +* +* Scanning should be completed before calling this function. +* +* \param txPtr +* Specifies the pointer to the cy_stc_capsense_pin_config_t object belonging +* to a Tx pin sensor to be disconnected from the CSD HW block. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \funcusage +* +* An example of using the function to perform port pin re-connection: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_CSXConnect +* +*******************************************************************************/ +void Cy_CapSense_CSXDisconnectTx( + const cy_stc_capsense_pin_config_t * txPtr, + cy_stc_capsense_context_t * context) +{ + Cy_CapSense_SsConfigPinRegisters(txPtr->pcPtr, (uint32_t)txPtr->pinNumber, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_GPIO_Clr(txPtr->pcPtr, (uint32_t)txPtr->pinNumber); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXConnectTxExt +****************************************************************************//** +* +* Connects a current Tx electrode to the CSX scanning hardware. +* +* This function connects all current Tx electrode's pins to the CSD_SENSE signal. +* It is assumed that drive mode of the port pin is already set to STRONG +* in the HSIOM_PORT_SELx register. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for faster execution time when there is only one port pin for an +* electrode for example). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXConnectTxExt(cy_stc_capsense_context_t * context) +{ + uint32_t pinIndex; + const cy_stc_capsense_pin_config_t * pinPointer = context->ptrActiveScanSns->ptrTxConfig->ptrPin; + + for (pinIndex = context->ptrActiveScanSns->ptrTxConfig->numPins; pinIndex-- > 0u;) + { + Cy_CapSense_CSXConnectTx(pinPointer, context); + pinPointer++; + } + context->ptrActiveScanSns->connectedSnsState = CY_CAPSENSE_SNS_CONNECTED; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXConnectRxExt +****************************************************************************//** +* +* Connects a current Rx electrode to the CSX scanning hardware. +* +* This function connects all current Rx electrode's pins to the CSD_SENSE signal. +* It is assumed that drive mode of the port pin is already set to STRONG +* in the HSIOM_PORT_SELx register. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for faster execution time when there is only one port pin for an +* electrode for example). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXConnectRxExt(cy_stc_capsense_context_t * context) +{ + uint32_t pinIndex; + const cy_stc_capsense_pin_config_t * pinPointer = context->ptrActiveScanSns->ptrRxConfig->ptrPin; + + for (pinIndex = context->ptrActiveScanSns->ptrRxConfig->numPins; pinIndex-- > 0u;) + { + Cy_CapSense_CSXConnectRx(pinPointer, context); + pinPointer++; + } + context->ptrActiveScanSns->connectedSnsState = CY_CAPSENSE_SNS_CONNECTED; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXDisconnectTxExt +****************************************************************************//** +* +* Disconnects a current Tx electrode from the CSX scanning hardware. +* +* This function connects all current Tx electrode's pins to the CSD_SENSE signal. +* It is assumed that drive mode of the port pin is already set to STRONG +* in the HSIOM_PORT_SELx register. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for faster execution time when there is only one port pin for an +* electrode for example). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXDisconnectTxExt(cy_stc_capsense_context_t * context) +{ + uint32_t pinIndex; + const cy_stc_capsense_pin_config_t * pinPointer = context->ptrActiveScanSns->ptrTxConfig->ptrPin; + + for (pinIndex = context->ptrActiveScanSns->ptrTxConfig->numPins; pinIndex-- > 0u;) + { + Cy_CapSense_CSXDisconnectTx(pinPointer, context); + pinPointer++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXDisconnectRxExt +****************************************************************************//** +* +* Connects a current Tx electrode to the CSX scanning hardware. +* +* This function connects all current Tx electrode's pins to the CSD_SENSE signal. +* It is assumed that drive mode of the port pin is already set to STRONG +* in the HSIOM_PORT_SELx register. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for faster execution time when there is only one port pin for an +* electrode for example). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXDisconnectRxExt(cy_stc_capsense_context_t * context) +{ + uint32_t pinIndex; + const cy_stc_capsense_pin_config_t * pinPointer = context->ptrActiveScanSns->ptrRxConfig->ptrPin; + + for (pinIndex = context->ptrActiveScanSns->ptrRxConfig->numPins; pinIndex-- > 0u;) + { + Cy_CapSense_CSXDisconnectRx(pinPointer, context); + pinPointer++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXSetWidgetTxClkSrc +****************************************************************************//** +* +* Sets a source for the Tx clock for a widget. +* +* \param ptrWdConfig +* The pointer to the cy_stc_capsense_widget_context_t structure. +* +*******************************************************************************/ +void Cy_CapSense_CSXSetWidgetTxClkSrc(const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + + if (0u != (ptrWdCxt->snsClkSource & CY_CAPSENSE_CLK_SOURCE_AUTO_MASK)) + { + ptrWdCxt->snsClkSource = (uint8_t)Cy_CapSense_SsCalcLfsrSize((uint32_t)ptrWdCxt->snsClk, (uint32_t)ptrWdCxt->resolution) | CY_CAPSENSE_CLK_SOURCE_AUTO_MASK; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXScanISR +****************************************************************************//** +* +* This is an internal ISR function to handle the CSX sensing method operation. +* +* This handler covers the following functionality: +* - Read the result of the measurement and store it into the corresponding register of +* the data structure. +* - If the Noise Metric functionality is enabled, then check the number of bad +* conversions and repeat the scan of the current sensor if the number of bad +* conversions is greater than the Noise Metric Threshold. +* - Initiate the scan of the next sensor for multiple sensor scanning mode. +* - Update the Status register in the data structure. +* - Switch the HW IP block to the default state if scanning of all the sensors is +* completed. +* +* \param capsenseContext +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_CSXScanISR(void * capsenseContext) +{ + uint32_t tmpRawCount; + cy_stc_capsense_context_t * cxt = (cy_stc_capsense_context_t *)capsenseContext; + cy_stc_active_scan_sns_t * ptrActive = cxt->ptrActiveScanSns; + uint32_t maxCount = (uint32_t) ptrActive->ptrWdContext->maxRawCount; + + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_CSD_INTR_MASK_CLEAR_MSK); + + /* Clear all pending interrupts of the CSD HW block */ + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + + tmpRawCount = (uint16_t)(Cy_CSD_ReadReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_RESULT_VAL1) & + CY_CAPSENSE_CSD_RESULT_VAL1_VALUE_MSK); + + tmpRawCount += (uint16_t)(Cy_CSD_ReadReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_RESULT_VAL2) & + CY_CAPSENSE_CSD_RESULT_VAL2_VALUE_MSK); + + /* This workaround needed to prevent overflow in the SW register map. Cypress ID #234358 */ + if(tmpRawCount > maxCount) + { + tmpRawCount = maxCount; + } + ptrActive->ptrSnsContext->raw = (uint16_t) (maxCount - tmpRawCount); + + /* Either complete scan or initiate new one */ + if((CY_CAPSENSE_ENABLE == cxt->ptrCommonConfig->mfsEn) && + (ptrActive->mfsChannelIndex < CY_CAPSENSE_MFS_CH2_INDEX)) + + { + Cy_CapSense_CSXInitNextChScan(cxt); + } + else if ((CY_CAPSENSE_SCAN_SCOPE_SGL_WD == ptrActive->scanScopeAll) && + (CY_CAPSENSE_SCAN_SCOPE_SGL_SNS == ptrActive->scanScopeSns)) + { + Cy_CapSense_ClrBusyFlags(cxt); + } + else + { + /* Disconnect Tx electrodes of previously scanned sensor as preparation for next sensor scan */ + Cy_CapSense_CSXDisconnectTxExt(cxt); + /* Scan the next sensor */ + Cy_CapSense_CSXInitNextScan(cxt); + } + + if(CY_CAPSENSE_NOT_BUSY == (cxt->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY)) + { + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CONFIG, cxt->ptrInternalContext->csxRegConfigInit); + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CSDCMP, CY_CAPSENSE_DEFAULT_CSD_CSDCMP_CFG); + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IDACA, CY_CAPSENSE_DEFAULT_CSD_IDACA_CFG); + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IO_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_IO_SEL_CFG); + } + + /* Clear previous interrupts */ + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + /* Enable interrupt */ + Cy_CSD_WriteReg(cxt->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR_MASK, CY_CAPSENSE_CSD_INTR_MASK_SAMPLE_MSK); + +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXInitNextScan +****************************************************************************//** +* +* This function initializes the next sensor scan. +* +* The function increments the sensor index, updates sense clock for matrix +* or touchpad widgets only, sets up Compensation IDAC, enables the sensor and +* scans it. When all the sensors are scanned it continues to set up the next +* widget until all the widgets are scanned. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSXInitNextScan(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + ptrActive->mfsChannelIndex = 0u; + ptrActive->ptrSnsContext = &ptrActive->ptrWdConfig->ptrSnsContext[ptrActive->sensorIndex]; + + /* Increment sensor index and sensor's context pointer to scope next sensor in widget */ + ptrActive->sensorIndex++; + ptrActive->ptrSnsContext++; + /* Initiate scan for next sensor in widget, if all the sensors in widget are not scanned */ + ptrActive->txIndex--; + + if (ptrActive->txIndex > 0u) + { + /* Increment pointer to the next Tx electrode and connect it for scan */ + ptrActive->ptrTxConfig++; + Cy_CapSense_CSXConnectTxExt(context); + /* Initiate a next scan */ + Cy_CapSense_CSXSetUpIdacs(context); + Cy_CapSense_CSXStartSample(context); + } + /* Check whether all Rx are looped through */ + else + { + ptrActive->rxIndex--; + if (ptrActive->rxIndex > 0u) + { + /* Disconnect the current Rx electrode and connect a next Rx electrode */ + Cy_CapSense_CSXDisconnectRxExt(context); + ptrActive->ptrRxConfig++; + Cy_CapSense_CSXConnectRxExt(context); + /* Re-initialize Tx index to be scanned per Rx and connect the first Tx electrode again */ + ptrActive->txIndex = ptrActive->ptrWdConfig->numRows; + ptrActive->ptrTxConfig = &ptrActive->ptrWdConfig->ptrEltdConfig[ptrActive->ptrWdConfig->numCols]; + Cy_CapSense_CSXConnectTxExt(context); + /* Initiate a next scan */ + Cy_CapSense_CSXSetUpIdacs(context); + Cy_CapSense_CSXStartSample(context); + } + else + { + /* If all the sensors are scanned, disconnect the last Rx electrode */ + Cy_CapSense_CSXDisconnectRxExt(context); + ptrActive->connectedSnsState = CY_CAPSENSE_SNS_DISCONNECTED; + /* Call scan of next widget if requested. If not, complete scan */ + if (CY_CAPSENSE_SCAN_SCOPE_ALL_WD == ptrActive->scanScopeAll) + { + Cy_CapSense_SsPostAllWidgetsScan(context); + } + else + { + /* All pending scans completed, clear busy state as scanning is completed */ + Cy_CapSense_ClrBusyFlags(context); + } + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsCSXStartSampleExt +****************************************************************************//** +* +* Starts the HW sequencer to perform the CSX conversion. +* +* This function covers the following functionality: +* 1. Configures the HW sequencer to perform the coarse initialization. +* 2. Waiting for completion of the coarse initialization. +* 3. Configures the HW sequencer to perform the normal conversion. +* 4. Starts the normal conversion +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +__STATIC_INLINE void Cy_CapSense_CSXStartSampleExt(cy_stc_capsense_context_t * context) +{ + uint32_t cpuFreqMHz; + uint32_t watchdogCounter; + + /* Approximate duration of Wait For Init loop */ + const uint32_t intrInitLoopDuration = 5uL; + + /* Wait For Init watchdog timeout in microseconds */ + const uint32_t initWatchdogTimeUs = 200000uL; + + + /* Configure the HW sequencer to perform the coarse initialization. */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CONFIG, context->ptrInternalContext->csxRegConfigInit); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_HSCMP, CY_CAPSENSE_PRECHARGE_CSD_HSCMP_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_P_SEL, CY_CAPSENSE_PRECHARGE_CSD_SW_HS_P_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_N_SEL, CY_CAPSENSE_PRECHARGE_CSD_SW_HS_N_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_DSI_SEL, CY_CAPSENSE_PRECHARGE_CSD_SW_DSI_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, CY_CAPSENSE_PRECHARGE_CSD_SW_SHIELD_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_MOD_SEL, CY_CAPSENSE_PRECHARGE_CSD_SW_FW_MOD_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_TANK_SEL, CY_CAPSENSE_PRECHARGE_CSD_SW_FW_TANK_SEL_CFG); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_RES, context->ptrInternalContext->csxRegSwResPrech); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_PRECHARGE_CSD_SEQ_START_CFG); + + /* Init Watchdog Counter to prevent a hang */ + cpuFreqMHz = context->ptrCommonConfig->cpuClkHz / 1000000uL; + watchdogCounter = Cy_CapSense_WatchdogCyclesNum(initWatchdogTimeUs, cpuFreqMHz, intrInitLoopDuration); + + /* Approximate duration of Wait For Init loop */ + while((0u != (CY_CAPSENSE_CSD_SEQ_START_START_MSK & + Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START)))) + { + if(0uL == watchdogCounter) + { + break; + } + + watchdogCounter--; + } + + + /* Reset the sequencer to the IDLE state if HSCMP not triggered till watchdog period is out. */ + if(0u != (CY_CAPSENSE_CSD_SEQ_START_START_MSK & Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START))) + { + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_DEFAULT_CSD_SEQ_START_CFG); + } + + /* Configure the HW sequencer to perform the normal conversion. */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CONFIG, context->ptrInternalContext->csxRegConfigScan); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_CSDCMP, CY_CAPSENSE_PRESCAN_CSD_CSDCMP_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_HSCMP, CY_CAPSENSE_DEFAULT_CSD_HSCMP_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_P_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_HS_P_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_HS_N_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_HS_N_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_DSI_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_DSI_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_SHIELD_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_SHIELD_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_MOD_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_FW_MOD_SEL_CFG); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_FW_TANK_SEL, CY_CAPSENSE_DEFAULT_CSD_SW_FW_TANK_SEL_CFG); + + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SW_RES, context->ptrInternalContext->csxRegSwResScan); + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_IO_SEL, CY_CAPSENSE_SCAN_CSD_SW_IO_SEL_CFG); + + /* Clear all pending interrupts of the CSD HW block */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR, CY_CAPSENSE_CSD_INTR_ALL_MSK); + (void)Cy_CSD_ReadReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_INTR); + + /* Start the normal conversion */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SEQ_START, CY_CAPSENSE_SCAN_CSD_SEQ_START_CFG); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXInitNextChScan +****************************************************************************//** +* +* This function initializes the next frequency of the sensor scan. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSXInitNextChScan(cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + ptrActive->mfsChannelIndex++; + ptrActive->ptrSnsContext += context->ptrCommonConfig->numSns; + + Cy_CapSense_CSXChangeClkFreq((uint32_t)ptrActive->mfsChannelIndex, context); + Cy_CapSense_CSXConnectTxExt(context); + Cy_CapSense_CSXSetUpIdacs(context); + Cy_CapSense_CSXStartSample(context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CSXChangeClkFreq +****************************************************************************//** +* +* Calculates sensor frequency depending on the specified frequency channel. +* +* \param channelIndex +* Specifies frequency index. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +static void Cy_CapSense_CSXChangeClkFreq(uint32_t channelIndex, cy_stc_capsense_context_t * context) +{ + uint32_t tmpRegVal; + uint32_t snsClkDivider; + + /* SnsClk setup */ + snsClkDivider = (uint32_t) context->ptrActiveScanSns->ptrWdContext->snsClk; + + /* Check divider value */ + if (0u == snsClkDivider) + { + snsClkDivider = 1u; + } + + /* Change the divider based on the chId */ + switch (channelIndex) + { + case CY_CAPSENSE_MFS_CH1_INDEX: + { + snsClkDivider += context->ptrCommonConfig->csxMfsDividerOffsetF1; + break; + } + case CY_CAPSENSE_MFS_CH2_INDEX: + { + snsClkDivider += context->ptrCommonConfig->csxMfsDividerOffsetF2; + break; + } + default: + { + break; + } + } + + tmpRegVal = (uint32_t)context->ptrActiveScanSns->ptrWdContext->snsClkSource & (uint32_t)~((uint32_t)CY_CAPSENSE_CLK_SOURCE_AUTO_MASK); + tmpRegVal = ((tmpRegVal << CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SIZE_POS) | (snsClkDivider - 1u) | + CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_CLEAR_MSK | CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_BITS_MSK); + /* Update reg value with divider and configuration */ + Cy_CSD_WriteReg(context->ptrCommonConfig->ptrCsdBase, CY_CSD_REG_OFFSET_SENSE_PERIOD, tmpRegVal); + +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_csx.h b/cy_capsense_csx.h new file mode 100644 index 0000000..a59fdae --- /dev/null +++ b/cy_capsense_csx.h @@ -0,0 +1,611 @@ +/***************************************************************************//** +* \file cy_capsense_csx.h +* \version 1.1 +* +* \brief +* This file provides the function prototypes specific to the CSX sensing +* implementation. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_CSX_H) +#define CY_CAPSENSE_CSX_H + +#include "cy_syslib.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_common.h" + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_CSXCalibrateWidget(uint32_t widgetId, uint32_t target, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXSetupWidget(uint32_t widgetId, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXSetupWidgetExt(uint32_t widgetId, uint32_t sensorId, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXScan(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXScanExt(cy_stc_capsense_context_t * context); + +void Cy_CapSense_CSXConnectRx(const cy_stc_capsense_pin_config_t * rxPtr, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXConnectTx(const cy_stc_capsense_pin_config_t * txPtr, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXDisconnectRx(const cy_stc_capsense_pin_config_t * rxPtr, cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXDisconnectTx(const cy_stc_capsense_pin_config_t * txPtr, cy_stc_capsense_context_t * context); + +/** \} */ + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_CSXConnectRxExt(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXConnectTxExt(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXDisconnectRxExt(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXDisconnectTxExt(cy_stc_capsense_context_t * context); + +void Cy_CapSense_CSXSetUpIdacs(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXDisableMode(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXInitialize(cy_stc_capsense_context_t * context); +void Cy_CapSense_CSXElectrodeCheck(cy_stc_capsense_context_t * context); + +void Cy_CapSense_CSXSetWidgetTxClkSrc(const cy_stc_capsense_widget_config_t * ptrWdConfig); +void Cy_CapSense_CSXScanISR(void * capsenseContext); + +/** \} \endcond */ + +/******************************************************************************* +* Local definition +*******************************************************************************/ +#define CY_CAPSENSE_CSX_DEADBAND_CYCLES_NUMBER (2u) + +/******************************************************************************* +* Register Configuration +*******************************************************************************/ + +/* + * +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | IREF_SEL | Select Iref according to IrefSel parameter | + * | 8:4 | FILTER_DELAY | 0x02(2-SampleClk cycles) | + * | 11:10 | SHIELD_DELAY | 0x00(Delay Line is OFF) | + * | 12 | SENSE_EN | 0x01(Enabled. Switches can be closed) | + * | 17 | FULL_WAVE | 0x00(Half Wave Mode) | + * | 18 | MUTUAL_CAP | 0x01(Mutual-cap mode) | + * | 19 | CSX_DUAL_CNT | 0x01(Use two counters) | + * | 24 | DSI_COUNT_SEL | 0x00(CSD-Result on DSI_COUNT bus) | + * | 25 | DSI_SAMPLE_EN | 0x00(DSI_SAMPLE_IN is disabled) | + * | 26 | SAMPLE_SYNC | 0x00(Double sync is disabled) | + * | 27 | DSI_SENSE_EN | 0x00(DSI_SENSE_IN is disabled) | + * | 30 | LP_MODE | 0x00(High power mode) | + * | 31 | ENABLE | 0x01(Analog part is ON) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_CONFIG_DEFAULT_EN_CFG (0x80001000uL) +#define CY_CAPSENSE_CONFIG_DEFAULT_FILTER_DELAY_CFG (0x00000020uL) +#define CY_CAPSENSE_CONFIG_DEFAULT_MUTUAL_CFG (0x00040000uL) +#define CY_CAPSENSE_CONFIG_DEFAULT_DUAL_CNT_CFG (0x00080000uL) + +#define CY_CAPSENSE_DEFAULT_CSD_CONFIG_CFG (CY_CAPSENSE_CONFIG_DEFAULT_FILTER_DELAY_CFG |\ + CY_CAPSENSE_CONFIG_DEFAULT_MUTUAL_CFG |\ + CY_CAPSENSE_CONFIG_DEFAULT_DUAL_CNT_CFG |\ + CY_CAPSENSE_CONFIG_DEFAULT_EN_CFG) + + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 1 | SAMPLE | 0x01(Clear CSD End Of Scan interrupt) | + * | 2 | INIT | 0x01(Clear CSD End Of Coarse Init interrupt) | + * | 8 | ADC_RES | 0x01(Clear ADC End Of Scan interrupt) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_INTR_CFG (CY_CAPSENSE_CSD_INTR_ALL_MSK) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 1 | SAMPLE | 0x00(CSD End Of Scan interrupt is cleared) | + * | 2 | INIT | 0x00(CSD End Of Coarse Init interrupt is cleared) | + * | 8 | ADC_RES | 0x00(ADC End Of Scan interrupt is cleared) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_INTR_SET_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 1 | SAMPLE | 0x01(CSD End Of Scan interrupt is masked) | + * | 2 | INIT | 0x00(CSD End Of Coarse Init interrupt is cleared) | + * | 8 | ADC_RES | 0x00(ADC End Of Scan interrupt is cleared) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_INTR_MASK_CFG (CY_CAPSENSE_CSD_INTR_MASK_SAMPLE_MSK) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | HSCMP_EN | 0x00(High Speed comparator is disabled) | + * | 4 | HSCMP_INVERT | 0x00(High Speed comparator output is not inverted) | + * | 31 | AZ_EN | 0x00(Auto-Zero is disabled) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_HSCMP_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 1:0 | PWR_MODE | 0x00(Amux buffer is disabled) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_AMBUF_CFG (0x00000000uL) + +/* +--------+---------------+------------------------------------------+---------------------------------------------+ + * | | | VDDA >= 2V | VDDA <2V | + * + BITS + FIELD +------------------------------------------+---------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|------------------------------------------|---------------------------------------------| + * | 0 | REFGEN_EN | 0x01(Reference generator is enabled) | 0x01(Reference generator is enabled) | + * | 4 | BYPASS | 0x00(BYPASS mode switch is open) | 0x00(BYPASS mode switch is open) | + * | 5 | VDDA_EN | 0x00(VDDA mode switch is open) | 0x00(VDDA mode switch is open) | + * | 6 | RES_EN | 0x01(Resistor string is enabled) | 0x01(Resistor string is enabled) | + * | 12:08 | GAIN | 0x1F(Gain = 31) | 0x15(Gain = 21) | + * | 20:16 | VREFLO_SEL | 0x00(Open all VREFLO switches) | 0x00(Open all VREFLO switches) | + * | 23 | VREFHI_SEL | 0x00(Open VREF_LO_INT switch) | 0x00(Open VREF_LO_INT switch) | + * +--------+---------------+------------------------------------------+---------------------------------------------+*/ + +#define CY_CAPSENSE_REFGEN_DEFAULT_EN_CFG (0x00000001uL) +#define CY_CAPSENSE_REFGEN_DEFAULT_RES_EN_CFG (0x00000040uL) + +#define CY_CAPSENSE_DEFAULT_CSD_REFGEN_CFG (CY_CAPSENSE_REFGEN_DEFAULT_EN_CFG |\ + CY_CAPSENSE_REFGEN_DEFAULT_RES_EN_CFG) + + +/* +--------+---------------+------------------------------------------+---------------------------------------------+ + * | | | AUTO_ZERO_EN=TRUE | AUTO_ZERO_EN=FALSE | + * + BITS + FIELD +------------------------------------------+---------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|------------------------------------------|---------------------------------------------| + * | 0 | CSDCMP_EN | 0x00(CSD comparator is disabled) | 0x00(CSD comparator is disabled) | + * | 5:04 | POLARITY_SEL | 0x00(IDAC_A polarity is used) | 0x00(IDAC_A polarity is used) | + * | 9:08 | CMP_PHASE | 0x03(Comparator activated on both phases)| 0x03(Comparator activated in both phases) | + * | 28 | CMP_MODE | 0x00(CSD mode) | 0x00(CSD mode) | + * | 29 | FEEDBACK_MODE | 0x00(Feedback from sampling flip-flop) | 0x00(Feedback from sampling flip-flop) | + * | 31 | AZ_EN | 0x01(Auto-Zero functionality is enabled) | 0x00(Auto-Zero functionality is disabled) | + * +--------+---------------+------------------------------------------+---------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_CSDCMP_CFG (0x00000300uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 6:0 | VAL | 0x00(Set IDAC value to "0") | + * | 7 | POL_DYN | 0x01(Set dynamic IDAC polarity) | + * | 9:8 | POLARITY | 0x02(IDAC polarity follows CSD_SENSE signal) | + * | 11:10 | BAL_MODE | 0x03(IDAC is enabled in both phases and disabled by CSDCOMP at the end of balancing) | + * | 17:16 | LEG1_MODE | 0x03(Configure LEG1 to CSD dynamic mode) | + * | 19:18 | LEG2_MODE | 0x00(LEG2 is disabled) | + * | 21 | DSI_CTRL_EN | 0x00(IDAC DSI control is disabled) | + * | 23:22 | RANGE | Set range according to Csx0IdacGainV2 parameter value | + * | 24 | LEG1_EN | 0x01(Output for LEG1 is enabled) | + * | 25 | LEG2_EN | 0x00(Output for LEG2 is disabled) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_IDACA_CFG (0x01030E80uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 6:0 | VAL | 0x00(Set IDAC value to "0") | + * | 7 | POL_DYN | 0x00(Set to "0" since IDACB is not used) | + * | 9:8 | POLARITY | 0x00(Set to "0" since IDACB is not used) | + * | 11:10 | BAL_MODE | 0x00(Set to "0" since IDACB is not used) | + * | 17:16 | LEG1_MODE | 0x00(Set to "0" since IDACB is not used) | + * | 19:18 | LEG2_MODE | 0x00(Set to "0" since IDACB is not used) | + * | 21 | DSI_CTRL_EN | 0x00(Set to "0" since IDACB is not used) | + * | 23:22 | RANGE | 0x00(Set to "0" since IDACB is not used) | + * | 24 | LEG1_EN | 0x00(Output for LEG2 is disabled) | + * | 25 | LEG2_EN | 0x00(Output for LEG2 is disabled) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_IDACB_CFG (0x00000000uL) + +/* +--------+---------------+--------------------------------------------+-------------------------------------------+ + * | | | TX_CLK_SOURCE=PRSAUTO | TX_CLK_SOURCE!=PRSAUTO | + * + BITS + FIELD +--------------------------------------------+-------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|--------------------------------------------|-------------------------------------------| + * | 11:00 | SENSE_DIV | Set to CSX_TX_CLK_DIVIDER value | Set to CSX_TX_CLK_DIVIDER value | + * | 18:16 | LFSR_SIZE | 0x00(Will be reconfigured in Run Time) | 0x00(Set to "0" since not used) | + * | 23:20 | LFSR_SCALE | 0x00(Will be reconfigured in Run Time) | Set to CSX_TX_CLK_SOURCE value | + * | 24 | LFSR_CLEAR | 0x00(Will be reconfigured in Run Time) | 0x00(Will be reconfigured in Run Time) | + * | 25 | SEL_LFSR_MSB | 0x00(Not used for CSX scanning method) | 0x00(Not used for CSX scanning method) | + * | 27:26 | LFSR_BITS | 0x0C(Use 5 bits. Range=[-16:15]) | 0x0C(Use 5 bits. Range=[-16:15]) | + * +--------+---------------+-----------------------------+----------------------------------------------------------+*/ + + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 11:0 | SENSE_WIDTH | 0x0000(Set to "0" SenseClk cycles) | + * | 16 | SENSE_POL | 0x00(Start with low phase) | + * | 18 | OVERLAP_PHI1 | 0x00(Non overlap for Phi1) | + * | 19 | OVERLAP_PHI2 | 0x00(Non overlap for Phi2) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SENSE_DUTY_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | SW_HMPM | 0x00(HMPM switch is statically open) | + * | 4 | SW_HMPT | 0x00(HMPT switch is statically open) | + * | 8 | SW_HMPS | 0x00(HMPS switch is statically open) | + * | 12 | SW_HMMA | 0x00(HMMA switch is statically open) | + * | 16 | SW_HMMB | 0x00(HMMB switch is statically open) | + * | 20 | SW_HMCA | 0x00(HMCA switch is statically open) | + * | 24 | SW_HMCB | 0x00(HMCB switch is statically open) | + * | 28 | SW_HMRH | 0x00(HMRH switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_HS_P_SEL_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 16 | SW_HCCC | 0x00(HCCC switch is statically open) | + * | 20 | SW_HCCD | 0x00(HCCD switch is statically open) | + * | 26:24 | SW_HCRH | 0x00(HCRH switch is statically open) | + * | 30:28 | SW_HCRL | 0x00(HCRL switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_HS_N_SEL_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 2:0 | SW_HCAV | 0x00(HCAV switch is statically open) | + * | 6:4 | SW_HCAG | 0x00(HCAG switch is statically open) | + * | 10:8 | SW_HCBV | 0x00(HCBV switch is statically open) | + * | 14:12 | SW_HCBG | 0x00(HCBG switch is statically open) | + * | 16 | SW_HCCV | 0x00(HCCV switch is statically open) | + * | 20 | SW_HCCG | 0x00(HCCG switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_SHIELD_SEL_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 4 | SW_IRBY | 0x00(IRBY switch is statically open) | + * | 8 | SW_IRLB | 0x00(IRLB switch is statically open) | + * | 12 | SW_ICA | 0x00(ICA switch is statically open) | + * | 18:16 | SW_ICB | 0x00(ICB switch is statically open) | + * | 20 | SW_IRLI | 0x00(IRLI switch is statically open) | + * | 24 | SW_IRH | 0x00(IRH switch is statically open) | + * | 28 | SW_IRL | 0x00(IRL switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_AMUXBUF_SEL_CFG (0x00000000uL) + + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 12 | SW_BYA | 0x01(BYA switch is statically open) | + * | 16 | SW_BYB | 0x00(BYB switch is statically open) | + * | 20 | SW_CBCC | 0x00(CBCC switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_BYP_SEL_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 2:0 | SW_SFPM | 0x03(SFPM switch is controlled by Phi2 of SenseClk signal) | + * | 6:4 | SW_SFPT | 0x02(SFPM switch is controlled by Phi1 of the SenseClk signal) | + * | 10:8 | SW_SFPS | 0x00(SFPS switch is statically open) | + * | 12 | SW_SFMA | 0x00(SFMA switch is statically open) | + * | 16 | SW_SFMB | 0x00(SFMB switch is statically open) | + * | 20 | SW_SFCA | 0x00(SFCA switch is statically open) | + * | 24 | SW_SFCB | 0x00(SFCB switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_CMP_P_SEL_CFG (0x00000023uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 26:24 | SW_SCRH | 0x01(SFPS switch is statically closed) | + * | 30:28 | SW_SCRL | 0x00(SFPS switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_CMP_N_SEL_CFG (0x01000000uL) + +/* +--------+---------------+--------------------------------------------+-------------------------------------------+ + * | | | VREF_SRC=SRSS | VREF_SRC=PASS | + * + BITS + FIELD +--------------------------------------------+-------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|--------------------------------------------|-------------------------------------------| + * | 0 | SW_IAIB | 0x00(IAIB switch is statically open) | 0x00(IAIB switch is statically open) | + * | 4 | SW_IBCB | 0x00(IBCB switch is statically open) | 0x00(IBCB switch is statically open) | + * | 16 | SW_SGMB | 0x00(SGMB switch is statically open) | 0x00(SGMB switch is statically open) | + * | 20 | SW_SGRP | 0x00(SGRP switch is statically open) | 0x01(SGRP switch is statically closed) | + * | 24 | SW_SGRE | 0x00(SGRE switch is statically open) | 0x00(SGRE switch is statically open) | + * | 28 | SW_SGR | 0x01(SGR switch is statically closed) | 0x00(SGR switch is statically open) | + * +--------+---------------+--------------------------------------------+-------------------------------------------+*/ + +#define CY_CAPSENSE_DEFAULT_CSD_SW_REFGEN_SEL_MSK (0x10100000uL) +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | SW_F1PM | 0x00(F1PM switch is statically closed) | + * | 10:8 | SW_F1MA | 0x00(F1MA switch is controlled by Phi2 of SenseClk signal) | + * | 18:16 | SW_F1CA | 0x00(F1CA switch is controlled by Phi2 of SenseClk signal) | + * | 20 | SW_C1CC | 0x00(C1CC switch is statically open) | + * | 24 | SW_C1CD | 0x00(C1CD switch is statically open) | + * | 28 | SW_C1F1 | 0x00(C1F1 switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_FW_MOD_SEL_CFG (0x00030301uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 4 | SW_F2PT | 0x00(F2PT switch is statically closed) | + * | 10:8 | SW_F2MA | 0x00(F2MA switch is controlled by Phi1 of the SenseClk signal) | + * | 14:12 | SW_F2CA | 0x00(F2CA switch is controlled by Phi1 of the SenseClk signal) | + * | 18:16 | SW_F2CB | 0x00(F2CB switch is statically open) | + * | 20 | SW_C2CC | 0x00(C2CC switch is statically open) | + * | 24 | SW_C2CD | 0x00(C2CD switch is statically open) | + * | 28 | SW_C2F2 | 0x00(C2F2 switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_FW_TANK_SEL_CFG (0x00002210uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 3:0 | TX_OUT | 0x00(The TX_OUT signal is controlled by SenseClk signal) | + * | 7:4 | TX_OUT_EN | 0x00(The TX_OUT_EN signal is set to the static "1") | + * | 15:12 | TX_AMUXB_EN | 0x00(The TX_AMUXB_EN signal is set to the static "0") | + * | 19:16 | TX_N_OUT | 0x00(The TX_N_OUT signal is set to the static "0") | + * | 23:20 | TX_N_OUT_EN | 0x00(The TX_N_OUT_EN signal is set to the static "0") | + * | 27:24 | TX_N_AMUXA_EN | 0x00(The TX_N_AMUXA_EN signal is set to the static "0") | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_IO_SEL_CFG (0x0000001FuL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 2:0 | DSI_CSH_TANK | 0x00(DSI_CSH_TANK switch is statically open) | + * | 6:4 | DSI_CMOD | 0x00(DSI_CMOD switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SW_DSI_SEL_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 15:0 | CONV_CNT | 0x0000(Sets the number of conversions per sample to "0") | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SEQ_NORM_CNT_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 7:0 | ADC_TIME | 0x00(Set to "0" since ADC is not used) | + * | 17:16 | ADC_MODE | 0b00(Set to "0" since ADC is not used) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_ADC_CTL_CFG (0x00000000uL) + +/* +--------+---------------+--------------------------------------------+-------------------------------------------+ + * | | | AUTO_ZERO_EN=TRUE | AUTO_ZERO_EN=FALSE | + * + BITS + FIELD +--------------------------------------------+-------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|--------------------------------------------|-------------------------------------------| + * | 0 | START | 0x00(CSD sequencer is stopped) | 0x00(CSD sequencer is stopped) | + * | 1 | SEQ_MODE | 0x00(Regular scan mode is used) | 0x00(Regular scan mode is used) | + * | 3 | ABORT | 0x01(Reset CSD sequencer to IDLE state) | 0x01(Reset CSD sequencer to IDLE state) | + * | 4 | DSI_START_EN | 0x00(Disable control by DSI) | 0x00(Disable control by DSI) | + * | 8 | AZ0_SKIP | 0x00(Do not skip AZ0 state) | 0x01(Skip AZ0 state) | + * | 9 | AZ1_SKIP | 0x00(Do not skip AZ1 state) | 0x01(Skip AZ1 state) | + * +--------+---------------+--------------------------------------------+-------------------------------------------+*/ +#define CY_CAPSENSE_DEFAULT_CSD_SEQ_START_CFG (0x00000308uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | IREF_SEL | 0x00(Select SRSS Iref) | + * | 8:4 | FILTER_DELAY | 0x00(Will be reconfigured in Run Time) | + * | 11:10 | SHIELD_DELAY | 0x00(Delay Line is OFF) | + * | 12 | SENSE_EN | 0x01(Enabled. Switches can be closed) | + * | 17 | FULL_WAVE | 0x00(Half Wave Mode) | + * | 18 | MUTUAL_CAP | 0x01(Mutual-cap mode) | + * | 19 | CSX_DUAL_CNT | 0x01(Use two counters) | + * | 24 | DSI_COUNT_SEL | 0x00(CSD-Result on DSI_COUNT bus) | + * | 25 | DSI_SAMPLE_EN | 0x00(DSI_SAMPLE_IN is disabled) | + * | 26 | SAMPLE_SYNC | 0x00(Double sync is disabled) | + * | 27 | DSI_SENSE_EN | 0x00(DSI_SENSE_IN is disabled) | + * | 30 | LP_MODE | 0x00(High power mode) | + * | 31 | ENABLE | 0x01(Analog part is ON) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ + +#define CY_CAPSENSE_CONFIG_PRESCAN_LP_MODE_CFG (0x00000000uL) +#define CY_CAPSENSE_CONFIG_PRESCAN_EN_CFG (0x80000000uL) +#define CY_CAPSENSE_CONFIG_PRESCAN_SENSE_EN_CFG (0x00001000uL) +#define CY_CAPSENSE_CONFIG_PRESCAN_FILTER_DELAY_CFG (0x00000000uL) +#define CY_CAPSENSE_CONFIG_PRESCAN_MUTUAL_CFG (0x00040000uL) +#define CY_CAPSENSE_CONFIG_PRESCAN_DUAL_CNT_CFG (0x00080000uL) + +#define CY_CAPSENSE_PRESCAN_CSD_CONFIG_CFG (CY_CAPSENSE_CONFIG_PRESCAN_FILTER_DELAY_CFG |\ + CY_CAPSENSE_CONFIG_PRESCAN_SENSE_EN_CFG |\ + CY_CAPSENSE_CONFIG_PRESCAN_MUTUAL_CFG |\ + CY_CAPSENSE_CONFIG_PRESCAN_DUAL_CNT_CFG |\ + CY_CAPSENSE_CONFIG_PRESCAN_LP_MODE_CFG |\ + CY_CAPSENSE_CONFIG_PRESCAN_EN_CFG) + +/* +--------+---------------+--------------------------------------------+-------------------------------------------+ + * | | | AUTO_ZERO_EN=TRUE | AUTO_ZERO_EN=FALSE | + * + BITS + FIELD +--------------------------------------------+-------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|--------------------------------------------|-------------------------------------------| + * | 0 | CSDCMP_EN | 0x01(CSD comparator is Enabled) | 0x01(CSD comparator is Enabled) | + * | 5:4 | POLARITY_SEL | 0x00(IDAC_A polarity is used) | 0x00(IDAC_A polarity is used) | + * | 9:8 | CMP_PHASE | 0x03(Comparator activated in both phases) | 0x03(Comparator activated in both phases) | + * | 28 | CMP_MODE | 0x00(CSD mode) | 0x00(CSD mode) | + * | 29 | FEEDBACK_MODE | 0x00(Feedback from sampling flip-flop) | 0x00(Feedback from sampling flip-flop) | + * | 31 | AZ_EN | 0x01(Auto-Zero functionality is enabled) | 0x00(Auto-Zero functionality is disabled) | + * +--------+---------------+--------------------------------------------+-------------------------------------------+*/ +#define CY_CAPSENSE_PRESCAN_CSD_CSDCMP_CFG (0x00000301uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | HSCMP_EN | 0x01(High Speed comparator is Enabled) | + * | 4 | HSCMP_INVERT | 0x00(High Speed comparator output is not inverted) | + * | 31 | AZ_EN | 0x00(Auto-Zero is Disabled) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_HSCMP_CFG (0x00000001uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | SW_HMPM | 0x01(HMPM switch is statically closed) | + * | 4 | SW_HMPT | 0x01(HMPT switch is statically closed) | + * | 8 | SW_HMPS | 0x00(HMPS switch is statically open) | + * | 12 | SW_HMMA | 0x00(HMMA switch is statically open) | + * | 16 | SW_HMMB | 0x00(HMMB switch is statically open) | + * | 20 | SW_HMCA | 0x00(HMCA switch is statically open) | + * | 24 | SW_HMCB | 0x00(HMCB switch is statically open) | + * | 28 | SW_HMRH | 0x00(HMRH switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SW_HS_P_SEL_CFG (0x00000011uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 16 | SW_HCCC | 0x00(HCCC switch is statically open) | + * | 20 | SW_HCCD | 0x00(HCCD switch is statically open) | + * | 26:24 | SW_HCRH | 0x01(HCRH switch is statically closed) | + * | 30:28 | SW_HCRL | 0x00(HCRL switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SW_HS_N_SEL_CFG (0x01000000uL) + + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 2:0 | DSI_CSH_TANK | 0x00(DSI_CSH_TANK switch is statically open) | + * | 6:4 | DSI_CMOD | 0x00(DSI_CMOD switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SW_DSI_SEL_CFG (0x00000000uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 2:0 | SW_HCAV | 0x06(HCAV switch is controlled by HSCMP output) | + * | 6:4 | SW_HCAG | 0x00(HCAG switch is statically open) | + * | 10:8 | SW_HCBV | 0x00(HCBV switch is statically open) | + * | 14:12 | SW_HCBG | 0x00(HCBG switch is statically open) | + * | 16 | SW_HCCV | 0x00(HCCV switch is statically open) | + * | 20 | SW_HCCG | 0x00(HCCG switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SW_SHIELD_SEL_CFG (0x00000006uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | SW_F1PM | 0x00(F1PM switch is statically closed) | + * | 10:8 | SW_F1MA | 0x00(F1MA switch is statically closed) | + * | 18:16 | SW_F1CA | 0x00(F1CA switch is statically closed) | + * | 20 | SW_C1CC | 0x00(C1CC switch is statically open) | + * | 24 | SW_C1CD | 0x00(C1CD switch is statically open) | + * | 28 | SW_C1F1 | 0x00(C1F1 switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SW_FW_MOD_SEL_CFG (0x00010101uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 4 | SW_F2PT | 0x00(F2PT switch is statically closed) | + * | 10:8 | SW_F2MA | 0x00(F2MA switch is statically closed) | + * | 14:12 | SW_F2CA | 0x00(F2CA switch is statically closed) | + * | 18:16 | SW_F2CB | 0x00(F2CB switch is statically open) | + * | 20 | SW_C2CC | 0x00(C2CC switch is statically open) | + * | 24 | SW_C2CD | 0x00(C2CD switch is statically open) | + * | 28 | SW_C2F2 | 0x00(C2F2 switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SW_FW_TANK_SEL_CFG (0x00001110uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | START | 0x01(STARTED) | + * | 1 | SEQ_MODE | 0x01(INIT_COARSE) | + * | 3 | ABORT | 0x00(RESET_TO_IDLE_STATE) | + * | 4 | DSI_START_EN | 0x00(DISABLE_CONTROL_BY_DSI) | + * | 8 | AZ0_SKIP | 0x01(SKIP_AZ0) | + * | 9 | AZ1_SKIP | 0x01(SKIP_AZ1) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_PRECHARGE_CSD_SEQ_START_CFG (0x00000303uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 0 | SW_F1PM | 0x01(F1PM switch is statically closed) | + * | 10:8 | SW_F1MA | 0x03(F1MA switch is controlled by Phi2 of the SenseClk signal) | + * | 18:16 | SW_F1CA | 0x03(F1CA switch is controlled by Phi2 of the SenseClk signal) | + * | 20 | SW_C1CC | 0x00(C1CC switch is statically open) | + * | 24 | SW_C1CD | 0x00(C1CD switch is statically open) | + * | 28 | SW_C1F1 | 0x00(C1F1 switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_SCAN_CSD_SW_FW_MOD_SEL_CFG (0x00030301uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 4 | SW_F2PT | 0x01(F2PT switch is statically closed) | + * | 10:8 | SW_F2MA | 0x02(F2MA switch is controlled by Phi1 of the SenseClk signal) | + * | 14:12 | SW_F2CA | 0x02(F2CA switch is controlled by Phi1 of the SenseClk signal) | + * | 18:16 | SW_F2CB | 0x00(F2CB switch is statically open) | + * | 20 | SW_C2CC | 0x00(C2CC switch is statically open) | + * | 24 | SW_C2CD | 0x00(C2CD switch is statically open) | + * | 28 | SW_C2F2 | 0x00(C2F2 switch is statically open) | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_SCAN_CSD_SW_FW_TANK_SEL_CFG (0x00002210uL) + +/* +--------+---------------+----------------------------------------------------------------------------------------+ + * | BITS | FIELD | MODE | + * |--------|---------------|----------------------------------------------------------------------------------------| + * | 3:0 | TX_OUT | 0x00(The TX_OUT signal is controlled by SenseClk signal) | + * | 7:4 | TX_OUT_EN | 0x00(The TX_OUT_EN signal is set to the static "1") | + * | 15:12 | TX_AMUXB_EN | 0x00(The TX_AMUXB_EN signal is set to the static "0") | + * | 19:16 | TX_N_OUT | 0x00(The TX_N_OUT signal is set to the static "0") | + * | 23:20 | TX_N_OUT_EN | 0x00(The TX_N_OUT_EN signal is set to the static "0") | + * | 27:24 | TX_N_AMUXA_EN | 0x00(The TX_N_AMUXA_EN signal is set to the static "0") | + * +--------+---------------+----------------------------------------------------------------------------------------+*/ +#define CY_CAPSENSE_SCAN_CSD_SW_IO_SEL_CFG (0x0000001FuL) + +/* +--------+---------------+--------------------------------------------+-------------------------------------------+ + * | | | AUTO_ZERO_EN=TRUE | AUTO_ZERO_EN=FALSE | + * + BITS + FIELD +--------------------------------------------+-------------------------------------------+ + * | | | MODE | MODE | + * |--------|---------------|--------------------------------------------|-------------------------------------------| + * | 0 | START | 0x01(CSD sequencer is stopped) | 0x01(CSD sequencer is stopped) | + * | 1 | SEQ_MODE | 0x00(Regular CSD scan mode is used) | 0x00(Regular CSD scan mode is used) | + * | 3 | ABORT | 0x00(Do not reset CSD sequencer) | 0x00(Do not reset CSD sequencer) | + * | 4 | DSI_START_EN | 0x00(Disable control by DSI) | 0x00(Disable control by DSI) | + * | 8 | AZ0_SKIP | 0x00(Do not skip AZ0 state) | 0x01(Skip AZ0 state) | + * | 9 | AZ1_SKIP | 0x00(Do not skip AZ1 state) | 0x01(Skip AZ1 state) | + * +--------+---------------+--------------------------------------------+-------------------------------------------+*/ +#define CY_CAPSENSE_SCAN_CSD_SEQ_START_CFG (0x00000301uL) + +#if defined(__cplusplus) +} +#endif + +#endif /* End of CY_CAPSENSE_CSX_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_filter.c b/cy_capsense_filter.c new file mode 100644 index 0000000..e92b07e --- /dev/null +++ b/cy_capsense_filter.c @@ -0,0 +1,1094 @@ +/***************************************************************************//** +* \file cy_capsense_filter.c +* \version 1.1 +* +* \brief +* This file contains the source code of all filters implementation. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include "stddef.h" +#include "cy_capsense_filter.h" +#include "cy_capsense_common.h" +#include "cy_capsense_lib.h" + + +/******************************************************************************* +* Local definition +*******************************************************************************/ +#define CY_CAPSENSE_IIR_BL_SHIFT (8u) + +#define CY_CAPSENSE_IIR_SHIFT_STANDARD (0u) +#define CY_CAPSENSE_IIR_SHIFT_PERFORMANCE (8u) + +#define CY_CAPSENSE_RC_MEDIAN_SIZE (2u) +#define CY_CAPSENSE_RC_IIR_SIZE (1u) +#define CY_CAPSENSE_RC_AVG_SIZE (3u) + +/* IIR filter constant */ +#define CY_CAPSENSE_IIR_COEFFICIENT_K (256u) + + +/******************************************************************************* +* Function Name: Cy_CapSense_UpdateAllBaselines +****************************************************************************//** +* +* Updates the baseline for all the sensors in all the widgets. +* +* Baselines must be updated after sensor scan to ignore low frequency +* changes in the sensor data caused by environment changes such as +* temperature from sensor status decision. +* +* This function ignores the widget enable bit in the widget status register. +* Calling this function multiple times without a new sensor scan leads to +* unexpected behavior and should be avoided. +* +* This function is called by Cy_CapSense_ProcessAllWidgets() and +* Cy_CapSense_ProcessWidget(), hence the application program need not use this +* function if any of the above functions is already used. This function can be +* used for custom application implementation. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the update baseline operation of all the widgets: +* - CY_RET_SUCCESS - The operation is successfully completed. +* - CY_RET_BAD_DATA - The baseline processing failed. +* +*******************************************************************************/ +cy_status Cy_CapSense_UpdateAllBaselines(const cy_stc_capsense_context_t * context) +{ + uint32_t wdIndex; + cy_status bslnStatus = CY_RET_SUCCESS; + + for(wdIndex = context->ptrCommonConfig->numWd; wdIndex-- > 0u;) + { + bslnStatus |= Cy_CapSense_UpdateWidgetBaseline(wdIndex, context); + } + + return(bslnStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_UpdateWidgetBaseline +****************************************************************************//** +* +* Updates the baselines for all the sensors in a widget specified by +* the input parameter. +* +* This function performs exactly the same tasks as +* Cy_CapSense_UpdateAllBaselines() but only for a specified widget. +* +* Calling this function multiple times without a new sensor scan leads to +* unexpected behavior and should be avoided. The application program need +* not use this function if the Cy_CapSense_UpdateAllBaselines(), +* Cy_CapSense_ProcessAllWidgets() or Cy_CapSense_ProcessWidget() functions +* are already used. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified widget update baseline operation: +* - CY_RET_SUCCESS - The operation is successfully completed. +* - CY_RET_BAD_DATA - The baseline processing failed. +* +*******************************************************************************/ +cy_status Cy_CapSense_UpdateWidgetBaseline( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + cy_status bslnStatus = CY_RET_SUCCESS; + + for(snsIndex = context->ptrWdConfig[widgetId].numSns; snsIndex-- > 0u;) + { + bslnStatus |= Cy_CapSense_UpdateSensorBaseline(widgetId, snsIndex, context); + } + + return(bslnStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_UpdateSensorBaseline +****************************************************************************//** +* +* Updates the baseline for a sensor in a widget specified by the +* input parameters. +* +* This function performs exactly the same tasks as +* Cy_CapSense_UpdateAllBaselines() and Cy_CapSense_UpdateWidgetBaseline() +* but only for a specified sensor. +* +* Calling this function multiple times without a new sensor scan leads to +* unexpected behavior and should be avoided. The application need not use +* this function if the Cy_CapSense_UpdateWidgetBaseline (), +* Cy_CapSense_UpdateAllBaselines (), Cy_CapSense_ProcessAllWidgets(), +* or Cy_CapSense_ProcessWidget() functions are already used. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified sensor update baseline operation: +* - CY_RET_SUCCESS - The operation is successfully completed. +* - CY_RET_BAD_DATA - The baseline processing failed. +* +*******************************************************************************/ +cy_status Cy_CapSense_UpdateSensorBaseline( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t result; + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + + result = Cy_CapSense_FtUpdateBaseline(ptrWdCfg->ptrWdContext, &ptrWdCfg->ptrSnsContext[sensorId], context); + + return (result); +} + +/******************************************************************************* +* Function Name: Cy_CapSense_FtUpdateBaseline +****************************************************************************//** +* +* Updates the baseline for a sensor specified by an input parameter. +* +* Check a matching of present baseline and its inverse duplication. If they +* match, then the function updates the baseline for a sensor specified by an input parameter. +* If they don't match, the function returns CY_CAPSENSE_TST_BSLN_DUPLICATION +* result and doesn't update the baseline. +* +* \param ptrWdContext +* The pointer to the widget context structure where all the widget parameters +* are stored. +* +* \param ptrSnsContext +* The pointer to the sensor context structure where the sensor data +* is stored. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns a status indicating whether the baseline has been updated: +* - Zero - if baseline updating was successful. +* - Non-zero - if present sensor's any channel baseline and its inversion +* doesn't match. +* +*******************************************************************************/ +uint32_t Cy_CapSense_FtUpdateBaseline( + const cy_stc_capsense_widget_context_t * ptrWdContext, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = CY_RET_SUCCESS; + uint32_t bslnHistory; + + /* Reset negative baseline counter */ + if(ptrSnsContext->raw >= ptrSnsContext->bsln) + { + ptrSnsContext->negBslnRstCnt = 0u; + } + + /* Reset baseline */ + if (ptrSnsContext->bsln > (ptrWdContext->nNoiseTh + ptrSnsContext->raw)) + { + if (ptrSnsContext->negBslnRstCnt >= ptrWdContext->lowBslnRst) + { + Cy_CapSense_FtInitializeBaseline(ptrSnsContext); + } + else + { + ptrSnsContext->negBslnRstCnt++; + } + } + else + { + /* + * Update baseline only if: + * - signal is in range between noiseThreshold and negativenoiseThreshold + * or + * - sensor Auto-reset is enabled + */ + if ((0u != context->ptrCommonConfig->swSensorAutoResetEn) || + (ptrSnsContext->raw <= (ptrWdContext->noiseTh + ptrSnsContext->bsln))) + { + /* Get real baseline */ + bslnHistory = ((uint32_t)ptrSnsContext->bsln << CY_CAPSENSE_IIR_BL_SHIFT) | ptrSnsContext->bslnExt; + /* Calculate baseline value */ + bslnHistory = Cy_CapSense_FtIIR1stOrder((uint32_t)ptrSnsContext->raw << CY_CAPSENSE_IIR_BL_SHIFT, bslnHistory, (uint32_t)ptrWdContext->bslnCoeff); + /* Split baseline */ + ptrSnsContext->bsln = CY_LO16(bslnHistory >> CY_CAPSENSE_IIR_BL_SHIFT); + ptrSnsContext->bslnExt = CY_LO8(bslnHistory); + } + } + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeAllBaselines +****************************************************************************//** +* +* Initializes the baselines of all the sensors of all the widgets. +* +* This function initializes baselines for all sensors and widgets in the project. +* It can also be used to re-initialize baselines at any time, however, note +* that all sensor data history information and sensor status shall be reset +* along with re-initialization of baseline. +* +* Following functions to initialize sensor and widgets and filter history +* should be called after initializing baseline for proper operation of +* the CapSense middleware: +* * Cy_CapSense_InitializeAllStatuses() +* * Cy_CapSense_InitializeAllFilters() +* +* These functions are called by the CapSense_Enable() function, hence it is +* not required to use this function if above function is used. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeAllBaselines(cy_stc_capsense_context_t * context) +{ + uint32_t wdIndex; + + for(wdIndex = context->ptrCommonConfig->numWd; wdIndex-- > 0u;) + { + Cy_CapSense_InitializeWidgetBaseline(wdIndex, context); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeWidgetBaseline +****************************************************************************//** +* +* Initializes the baselines of all the sensors in a specific widget. +* +* This function initializes baselines for all sensors in a specific widget +* in the project. It can also be used to re-initialize baselines at any time, +* however, note that all sensor data history information and sensor status +* should be reset along with re-initialization of baseline. +* +* The following functions to initialize sensor and widgets and filter history +* should be called after initializing baselines for proper operation of +* middleware. +* * Cy_CapSense_InitializeWidgetStatus() +* * Cy_CapSense_InitializeWidgetFilter() +* +* These functions are called by CapSense_Enable() function, hence it is not +* required to use this function is above function is used. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeWidgetBaseline( + uint32_t widgetId, + cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + + for(snsIndex = context->ptrWdConfig[widgetId].numSns; snsIndex-- > 0u;) + { + Cy_CapSense_InitializeSensorBaseline(widgetId, snsIndex, context); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeSensorBaseline +****************************************************************************//** +* +* Initializes the baseline of a sensor in a widget specified +* by the input parameters. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeSensorBaseline( + uint32_t widgetId, + uint32_t sensorId, + cy_stc_capsense_context_t * context) +{ + uint32_t freqChIndex; + uint32_t freqChNumber; + uint32_t cxtOffset; + + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + cxtOffset = sensorId + (freqChIndex * context->ptrCommonConfig->numSns); + Cy_CapSense_FtInitializeBaseline(&context->ptrWdConfig[widgetId].ptrSnsContext[cxtOffset]); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_FtInitializeBaseline +****************************************************************************//** +* +* Initializes the baseline history for a sensor indicated by an input +* parameter. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +*******************************************************************************/ +void Cy_CapSense_FtInitializeBaseline(cy_stc_capsense_sensor_context_t * ptrSnsContext) +{ + ptrSnsContext->bslnExt = 0u; + ptrSnsContext->bsln = ptrSnsContext->raw; + ptrSnsContext->negBslnRstCnt = 0u; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeAllFilters +****************************************************************************//** +* +* Initializes (or re-initializes) all the firmware filter history, except +* the baseline. +* +* Calling this function is accompanied by +* * Cy_CapSense_InitializeAllStatuses() +* * Cy_CapSense_InitializeAllBaselines() +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeAllFilters(const cy_stc_capsense_context_t * context) +{ + uint32_t widgetId; + + for(widgetId = context->ptrCommonConfig->numWd; widgetId-- > 0u;) + { + Cy_CapSense_InitializeWidgetFilter(widgetId, context); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeWidgetFilter +****************************************************************************//** +* +* Initializes (or re-initializes) the raw count filter history of all +* the sensors in a widget specified by the input parameter. +* +* Calling this function is accompanied by +* - Cy_CapSense_InitializeWidgetStatus(). +* - Cy_CapSense_InitializeWidgetBaseline(). +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeWidgetFilter( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t freqChIndex; + uint32_t freqChNumber; + uint32_t snsHistorySize; + uint32_t cxtOffset; + uint32_t historyOffset; + + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + + uint32_t rawFilterCfg = ptrWdCfg->rawFilterConfig; + uint8_t * ptrHistoryLow = NULL; + uint16_t * ptrHistory; + cy_stc_capsense_sensor_context_t * ptrSnsCtx ; + cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNEHistory; + + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + for(snsIndex = 0u; snsIndex < ptrWdCfg->numSns; snsIndex++) + { + cxtOffset = snsIndex + (freqChIndex * context->ptrCommonConfig->numSns); + historyOffset = snsHistorySize * (snsIndex + (freqChIndex * context->ptrCommonConfig->numSns)); + ptrSnsCtx = &ptrWdCfg->ptrSnsContext[cxtOffset]; + ptrHistory = &ptrWdCfg->ptrRawFilterHistory[historyOffset]; + + if(CY_CAPSENSE_IIR_FILTER_PERFORMANCE == (ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + ptrHistoryLow = &ptrWdCfg->ptrRawFilterHistoryLow[cxtOffset]; + } + + if(0u != (CY_CAPSENSE_RC_FILTER_MEDIAN_EN_MASK & rawFilterCfg)) + { + Cy_CapSense_InitializeMedianInternal(ptrWdCfg, ptrSnsCtx, ptrHistory); + ptrHistory += CY_CAPSENSE_RC_MEDIAN_SIZE; + } + + if(0u != (CY_CAPSENSE_RC_FILTER_IIR_EN_MASK & rawFilterCfg)) + { + Cy_CapSense_InitializeIIRInternal(ptrWdCfg, ptrSnsCtx, ptrHistory, ptrHistoryLow); + ptrHistory += CY_CAPSENSE_RC_IIR_SIZE; + } + + if(0u != (CY_CAPSENSE_RC_FILTER_AVERAGE_EN_MASK & rawFilterCfg)) + { + Cy_CapSense_InitializeAverageInternal(ptrWdCfg, ptrSnsCtx, ptrHistory); + } + } + } + + if (CY_CAPSENSE_CSD_SS_HWTH_EN == context->ptrCommonConfig->csdAutotuneEn) + { + /* Noise envelope is available for CSD widgets only */ + if ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == ptrWdCfg->senseMethod) + { + ptrSnsCtx = ptrWdCfg->ptrSnsContext; + ptrNEHistory = ptrWdCfg->ptrNoiseEnvelope; + for(snsIndex = 0u; snsIndex < ptrWdCfg->numSns; snsIndex++) + { + Cy_CapSense_InitializeNoiseEnvelope_Lib(ptrSnsCtx->raw, ptrWdCfg->ptrWdContext->sigPFC, ptrNEHistory); + ptrSnsCtx++; + ptrNEHistory++; + } + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeIIR +****************************************************************************//** +* +* Initializes the IIR filter history. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeIIR( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsHistorySize; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + const cy_stc_capsense_sensor_context_t * ptrSnsCtx; + + ptrWdCfg = &context->ptrWdConfig[widgetId]; + ptrSnsCtx = &ptrWdCfg->ptrSnsContext[sensorId]; + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + + Cy_CapSense_InitializeIIRInternal(ptrWdCfg, + ptrSnsCtx, + &ptrWdCfg->ptrRawFilterHistory[(sensorId * snsHistorySize) + 2uL], + &ptrWdCfg->ptrRawFilterHistoryLow[sensorId]); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunIIR +****************************************************************************//** +* +* Executes the IIR filter algorithm on a sensor indicated by an input +* parameter. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_RunIIR( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsHistorySize; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + cy_stc_capsense_sensor_context_t * ptrSnsCtx; + + ptrWdCfg = &context->ptrWdConfig[widgetId]; + ptrSnsCtx = &ptrWdCfg->ptrSnsContext[sensorId]; + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + + + Cy_CapSense_RunIIRInternal(ptrWdCfg, + ptrSnsCtx, + &ptrWdCfg->ptrRawFilterHistory[(sensorId * snsHistorySize) + 2uL], + &ptrWdCfg->ptrRawFilterHistoryLow[sensorId]); + +} + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeIIRInternal +****************************************************************************//** +* +* Initializes the IIR filter history. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +* \param ptrSnsRawHistoryLow +* The pointer to the extended filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_InitializeIIRInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow) +{ + ptrSnsRawHistory[0u] = ptrSnsContext->raw; + + if(CY_CAPSENSE_IIR_FILTER_PERFORMANCE == (ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + ptrSnsRawHistoryLow[0u] = 0u; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunIIRInternal +****************************************************************************//** +* +* Runs the IIR filter. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +* \param ptrSnsRawHistoryLow +* The pointer to the extended filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_RunIIRInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow) +{ + uint32_t tempHistory; + uint32_t tempRaw; + + if(CY_CAPSENSE_IIR_FILTER_PERFORMANCE == (ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + tempRaw = ((uint32_t)ptrSnsContext->raw) << CY_CAPSENSE_IIR_SHIFT_PERFORMANCE; + tempHistory = ((uint32_t)(*ptrSnsRawHistory)) << CY_CAPSENSE_IIR_SHIFT_PERFORMANCE; + tempHistory |= (uint32_t)(*ptrSnsRawHistoryLow); + tempRaw = Cy_CapSense_FtIIR1stOrder(tempRaw, tempHistory, ptrWdConfig->iirCoeff); + *ptrSnsRawHistory = CY_LO16(tempRaw >> CY_CAPSENSE_IIR_SHIFT_PERFORMANCE); + *ptrSnsRawHistoryLow = CY_LO8(tempRaw); + ptrSnsContext->raw = CY_LO16(tempRaw >> CY_CAPSENSE_IIR_SHIFT_PERFORMANCE); + } + else + { + tempRaw = Cy_CapSense_FtIIR1stOrder((uint32_t)ptrSnsContext->raw, (uint32_t)(*ptrSnsRawHistory), ptrWdConfig->iirCoeff); + *ptrSnsRawHistory = CY_LO16(tempRaw); + ptrSnsContext->raw = *ptrSnsRawHistory; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeMedian +****************************************************************************//** +* +* Initializes the median filter history. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeMedian( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsHistorySize; + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_sensor_context_t * ptrSnsCtx = &ptrWdCfg->ptrSnsContext[sensorId]; + + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + + Cy_CapSense_InitializeMedianInternal(ptrWdCfg, + ptrSnsCtx, + &ptrWdCfg->ptrRawFilterHistory[sensorId * snsHistorySize]); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunMedian +****************************************************************************//** +* +* Executes the median filter algorithm on a sensor raw count indicated by +* the input parameters. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_RunMedian( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsHistorySize; + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_sensor_context_t * ptrSnsCtx = &ptrWdCfg->ptrSnsContext[sensorId]; + + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + + Cy_CapSense_RunMedianInternal(ptrWdCfg, + ptrSnsCtx, + + &ptrWdCfg->ptrRawFilterHistory[sensorId * snsHistorySize]); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeMedianInternal +****************************************************************************//** +* +* Initializes the median filter. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_InitializeMedianInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory) +{ + (void)ptrWdConfig; + + ptrSnsRawHistory[0u] = ptrSnsContext->raw; + ptrSnsRawHistory[1u] = ptrSnsContext->raw; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunMedianInternal +****************************************************************************//** +* +* Runs the median filter. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_RunMedianInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory) +{ + uint32_t temp = Cy_CapSense_FtMedian( + (uint32_t)ptrSnsContext->raw, + (uint32_t)ptrSnsRawHistory[0u], + (uint32_t)ptrSnsRawHistory[1u]); + + (void)ptrWdConfig; + + ptrSnsRawHistory[1u] = ptrSnsRawHistory[0u]; + ptrSnsRawHistory[0u] = ptrSnsContext->raw; + ptrSnsContext->raw = CY_LO16(temp); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeAverage +****************************************************************************//** +* +* Initializes the average filter history. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeAverage( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsHistorySize; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + const cy_stc_capsense_sensor_context_t * ptrSnsCtx; + + ptrWdCfg = &context->ptrWdConfig[widgetId]; + ptrSnsCtx = &ptrWdCfg->ptrSnsContext[sensorId]; + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + + Cy_CapSense_InitializeAverageInternal( + ptrWdCfg, + ptrSnsCtx, + &ptrWdCfg->ptrRawFilterHistory[(sensorId * snsHistorySize) + 2u + 1u]); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunAverage +****************************************************************************//** +* +* Executes the average filter algorithm on a sensor indicated by an input +* parameter. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_RunAverage( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsHistorySize; + const cy_stc_capsense_widget_config_t * ptrWdCfg; + cy_stc_capsense_sensor_context_t * ptrSnsCtx; + + ptrWdCfg = &context->ptrWdConfig[widgetId]; + ptrSnsCtx = &ptrWdCfg->ptrSnsContext[sensorId]; + snsHistorySize = (uint32_t)ptrWdCfg->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + + Cy_CapSense_RunAverageInternal( + ptrWdCfg, + ptrSnsCtx, + &ptrWdCfg->ptrRawFilterHistory[(sensorId * snsHistorySize) + 2u + 1u]); + +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeAverageInternal +****************************************************************************//** +* +* Initializes the average filter. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_InitializeAverageInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory) +{ + (void)ptrWdConfig; + ptrSnsRawHistory[0u] = ptrSnsContext->raw; + ptrSnsRawHistory[1u] = ptrSnsContext->raw; + ptrSnsRawHistory[2u] = ptrSnsContext->raw; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunAverageInternal +****************************************************************************//** +* +* Runs the average filter. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_RunAverageInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory) +{ + uint32_t temp; + + if(CY_CAPSENSE_AVERAGE_FILTER_LEN_4 == (ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_AVERAGE_MODE_MASK)) + { + temp = ((uint32_t)ptrSnsContext->raw + ptrSnsRawHistory[0u] + ptrSnsRawHistory[1u] + ptrSnsRawHistory[2u]) >> 2u; + ptrSnsRawHistory[2u] = ptrSnsRawHistory[1u]; + ptrSnsRawHistory[1u] = ptrSnsRawHistory[0u]; + } + else + { + temp = ((uint32_t)ptrSnsContext->raw + ptrSnsRawHistory[0u]) >> 1u; + } + ptrSnsRawHistory[0u] = ptrSnsContext->raw; + ptrSnsContext->raw = CY_LO16(temp); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_FtRunEnabledFiltersInternal +****************************************************************************//** +* +* Runs all enabled filters. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history of the sensor. +* +* \param ptrSnsRawHistoryLow +* The pointer to the extended filter history of the sensor. +* +*******************************************************************************/ +void Cy_CapSense_FtRunEnabledFiltersInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow) +{ + uint16_t rawFilterCfg; + rawFilterCfg = ptrWdConfig->rawFilterConfig; + + if(0u != (CY_CAPSENSE_RC_FILTER_MEDIAN_EN_MASK & rawFilterCfg)) + { + Cy_CapSense_RunMedianInternal(ptrWdConfig, ptrSnsContext, ptrSnsRawHistory); + ptrSnsRawHistory += CY_CAPSENSE_RC_MEDIAN_SIZE; + } + + if(0u != (CY_CAPSENSE_RC_FILTER_IIR_EN_MASK & rawFilterCfg)) + { + Cy_CapSense_RunIIRInternal(ptrWdConfig, ptrSnsContext, ptrSnsRawHistory, ptrSnsRawHistoryLow); + ptrSnsRawHistory += CY_CAPSENSE_RC_IIR_SIZE; + } + + if(0u != (CY_CAPSENSE_RC_FILTER_AVERAGE_EN_MASK & rawFilterCfg)) + { + Cy_CapSense_RunAverageInternal(ptrWdConfig, ptrSnsContext, ptrSnsRawHistory); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_FtMedian +****************************************************************************//** +* +* Returns the median value from the three passed arguments. +* +* \param x1 +* The first value to be compared. +* +* \param x2 +* The second value to be compared. +* +* \param x3 +* The third value to be compared. +* +* \return +* Returns the median value of input arguments. +* +*******************************************************************************/ +uint32_t Cy_CapSense_FtMedian(uint32_t x1, uint32_t x2, uint32_t x3) +{ + uint32_t tmp; + + if (x1 > x2) + { + tmp = x2; + x2 = x1; + x1 = tmp; + } + + if (x2 > x3) + { + x2 = x3; + } + + return ((x1 > x2) ? x1 : x2); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_FtIIR1stOrder +****************************************************************************//** +* +* Returns the filtered data by the IIR 1-st order algorithm +* +* \param input +* The data to be filtered. +* +* \param prevOutput +* The previous filtered data. +* +* \param n +* The IIR filter coefficient (n/256). +* +* \return +* Returns the filtered data. +* +*******************************************************************************/ +uint32_t Cy_CapSense_FtIIR1stOrder(uint32_t input, uint32_t prevOutput, uint32_t n) +{ + uint32_t filteredOutput; + + filteredOutput = ((n * input) + ((CY_CAPSENSE_IIR_COEFFICIENT_K - n) * prevOutput)) >> 8u; + + return filteredOutput; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_FtJitter +****************************************************************************//** +* +* Returns the filtered data by the jitter algorithm. +* +* \param input +* The data to be filtered. +* +* \param prevOutput +* The previous filtered data. +* +* \return +* Returns the filtered data. +* +*******************************************************************************/ +uint32_t Cy_CapSense_FtJitter(uint32_t input, uint32_t prevOutput) +{ + if (prevOutput > input) + { + input++; + } + else if (prevOutput < input) + { + input--; + } + else + { + /* Nothing to do - MISRA 14.1 requirement*/ + } + return input; +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_filter.h b/cy_capsense_filter.h new file mode 100644 index 0000000..723b0f6 --- /dev/null +++ b/cy_capsense_filter.h @@ -0,0 +1,143 @@ +/***************************************************************************//** +* \file cy_capsense_filter.h +* \version 1.1 +* +* \brief +* This file contains the definitions for all the filters implementation. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_FILTER_H) +#define CY_CAPSENSE_FILTER_H + +#include "cy_syslib.h" + +#include "cy_capsense_structure.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_common.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/*************************************** +* Function Prototypes +***************************************/ + +/******************************************************************************* +* LOW LEVEL FUNCTIONS +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_InitializeAllBaselines(cy_stc_capsense_context_t * context); +void Cy_CapSense_InitializeWidgetBaseline(uint32_t widgetId, cy_stc_capsense_context_t * context); +void Cy_CapSense_InitializeSensorBaseline(uint32_t widgetId, uint32_t sensorId, cy_stc_capsense_context_t * context); + +void Cy_CapSense_InitializeAllFilters(const cy_stc_capsense_context_t * context); +void Cy_CapSense_InitializeWidgetFilter(uint32_t widgetId, const cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_UpdateAllBaselines(const cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_UpdateWidgetBaseline(uint32_t widgetId, const cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_UpdateSensorBaseline(uint32_t widgetId, uint32_t sensorId, const cy_stc_capsense_context_t * context); + +/** \} */ + + +/******************************************************************************* +* Function Prototypes - Internal functions +*******************************************************************************/ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_InitializeIIR( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); +void Cy_CapSense_RunIIR( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); + +void Cy_CapSense_InitializeMedian( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); +void Cy_CapSense_RunMedian( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); + +void Cy_CapSense_InitializeAverage( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); +void Cy_CapSense_RunAverage( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); + +void Cy_CapSense_FtInitializeBaseline( + cy_stc_capsense_sensor_context_t * ptrSnsContext); +uint32_t Cy_CapSense_FtUpdateBaseline( + const cy_stc_capsense_widget_context_t * ptrWdContext, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + const cy_stc_capsense_context_t * context); + +uint32_t Cy_CapSense_FtMedian(uint32_t x1, uint32_t x2, uint32_t x3); +uint32_t Cy_CapSense_FtIIR1stOrder(uint32_t input, uint32_t prevOutput, uint32_t n); +uint32_t Cy_CapSense_FtJitter(uint32_t input, uint32_t prevOutput); + +void Cy_CapSense_FtRunEnabledFiltersInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow); +void Cy_CapSense_InitializeIIRInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow); +void Cy_CapSense_RunIIRInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow); +void Cy_CapSense_InitializeMedianInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory); +void Cy_CapSense_RunMedianInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory); +void Cy_CapSense_InitializeAverageInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory); +void Cy_CapSense_RunAverageInternal( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory); + +/** \} \endcond */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_FILTER_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_gesture_lib.h b/cy_capsense_gesture_lib.h new file mode 100644 index 0000000..1e92f8e --- /dev/null +++ b/cy_capsense_gesture_lib.h @@ -0,0 +1,313 @@ +/***************************************************************************//** +* \file cy_capsense_gesture_lib.h +* \version 1.1 +* +* \brief +* Provides the gesture interface. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#ifndef CY_CAPSENSE_GESTURE_LIB_H +#define CY_CAPSENSE_GESTURE_LIB_H + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************************************/ +/** \addtogroup group_capsense_gesture_structures *//** \{ */ +/******************************************************************************/ + +/** Gesture configuration structure */ +typedef struct +{ + /* Common parameters */ + uint16_t resolutionX; /**< Widget maximum position X-axis */ + uint16_t resolutionY; /**< Widget maximum position Y-axis */ + + /* Enabled gesture */ + uint16_t gestureEnableMask; /**< Enabled gesture mask */ + + /* Timeout */ + uint16_t flickTimeoutMax; /**< Flick maximum timeout */ + uint16_t edgeTimeoutMax; /**< Edge Swipe maximum timeout */ + uint16_t clickTimeoutMax; /**< Click maximum timeout */ + uint16_t clickTimeoutMin; /**< Click minimum timeout */ + uint16_t secondClickIntervalMax; /**< Second Click maximum interval */ + uint16_t secondClickIntervalMin; /**< Second Click minimum interval */ + + /* Distance */ + uint16_t zoomDistanceMin; /**< Zoom minimum distance */ + uint16_t flickDistanceMin; /**< Flick minimum distance */ + uint16_t scrollDistanceMin; /**< Scroll minimum distance */ + uint16_t rotateDistanceMin; /**< Rotate minimum distance */ + uint16_t edgeDistanceMin; /**< Edge Swipe minimum distance */ + uint8_t secondClickDistanceMax; /**< Second Click maximum distance */ + uint8_t clickDistanceMax; /**< Click maximum distance */ + + /* Debounce */ + uint8_t zoomDebounce; /**< Zoom debounce */ + uint8_t scrollDebounce; /**< Scroll debounce */ + uint8_t rotateDebounce; /**< Rotate debounce */ + + /* Edge Swipe Specific */ + uint8_t edgeAngleMax; /**< Edge Swipe maximum angle */ + uint8_t edgeEdgeSize; /**< Edge Swipe border size */ +} cy_stc_capsense_gesture_config_t; + +/** Gesture position structure */ +typedef struct +{ + uint16_t x; /**< X axis position */ + uint16_t y; /**< Y axis position */ +} cy_stc_capsense_gesture_position_t; + +/** Gesture One Finger Single Click context structure */ +typedef struct +{ + uint32_t touchStartTime1; /**< Touchdown time */ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ +} cy_stc_capsense_ofsc_context_t; + +/** Gesture One Finger Double Click context structure */ +typedef struct +{ + uint32_t touchStartTime1; /**< Touchdown time */ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ +} cy_stc_capsense_ofdc_context_t; + +/** Gesture One Finger Click and Drag context structure */ +typedef struct +{ + uint32_t touchStartTime1; /**< Touchdown time */ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ +} cy_stc_capsense_ofcd_context_t; + +/** Gesture Two Finger Single Click context structure */ +typedef struct +{ + uint32_t touchStartTime1; /**< Touchdown time of the first touch */ + uint32_t touchStartTime2; /**< Touchdown time of the second touch */ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position of the first touch */ + cy_stc_capsense_gesture_position_t touchStartPosition2; /**< Touchdown position of the second touch */ + uint8_t state; /**< Gesture state */ +} cy_stc_capsense_tfsc_context_t; + +/** Gesture One Finger Scroll context structure */ +typedef struct +{ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ + uint8_t debounce; /**< Gesture debounce counter */ + uint8_t direction; /**< Last reported direction */ +} cy_stc_capsense_ofsl_context_t; + +/** Gesture Two Finger Scroll context structure */ +typedef struct +{ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position of the first touch */ + cy_stc_capsense_gesture_position_t touchStartPosition2; /**< Touchdown position of the second touch */ + uint8_t state; /**< Gesture state */ + uint8_t debounce; /**< Gesture debounce counter */ + uint8_t direction; /**< Last reported direction */ +} cy_stc_capsense_tfsl_context_t; + +/** Gesture One Finger Flick context structure */ +typedef struct +{ + uint32_t touchStartTime1; /**< Touchdown time */ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ +} cy_stc_capsense_offl_context_t; + +/** Gesture One Finger Edge Swipe context structure */ +typedef struct +{ + uint32_t touchStartTime1; /**< Touchdown time */ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ + uint8_t edge; /**< Detected edge */ +} cy_stc_capsense_ofes_context_t; + +/** Gesture Two Finger Zoom context structure */ +typedef struct +{ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position of the first touch */ + cy_stc_capsense_gesture_position_t touchStartPosition2; /**< Touchdown position of the second touch */ + uint16_t distanceX; /**< History of X-axis displacement */ + uint16_t distanceY; /**< History of Y-axis displacement */ + uint8_t state; /**< Gesture state */ + uint8_t debounce; /**< Gesture debounce counter */ +} cy_stc_capsense_tfzm_context_t; + +/** Gesture One Finger Rotate context structure */ +typedef struct +{ + cy_stc_capsense_gesture_position_t touchStartPosition1; /**< Touchdown position */ + uint8_t state; /**< Gesture state */ + uint8_t history; /**< History of detected movements */ + uint8_t debounce; /**< Gesture debounce counter */ +} cy_stc_capsense_ofrt_context_t; + +/** Gesture global context structure */ +typedef struct +{ + cy_stc_capsense_gesture_position_t position1; /**< Current position of the first touch */ + cy_stc_capsense_gesture_position_t positionLast1; /**< Previous position of the first touch */ + cy_stc_capsense_gesture_position_t position2; /**< Current position of the second touch */ + cy_stc_capsense_gesture_position_t positionLast2; /**< Previous position of the second touch */ + + uint32_t timestamp; /**< Current timestamp */ + uint16_t detected; /**< Detected gesture mask */ + uint16_t direction; /**< Mask of direction of detected gesture */ + + cy_stc_capsense_ofrt_context_t ofrtContext; /**< One-finger rotate gesture context */ + cy_stc_capsense_ofsl_context_t ofslContext; /**< One-finger scroll gesture context */ + cy_stc_capsense_tfzm_context_t tfzmContext; /**< Two-finger zoom gesture context */ + cy_stc_capsense_tfsc_context_t tfscContext; /**< Two-finger single click gesture context */ + cy_stc_capsense_ofes_context_t ofesContext; /**< One-finger edge swipe gesture context */ + cy_stc_capsense_offl_context_t offlContext; /**< One-finger flick gesture context */ + cy_stc_capsense_ofsc_context_t ofscContext; /**< One-finger single click gesture context */ + cy_stc_capsense_ofdc_context_t ofdcContext; /**< One-finger double click gesture context */ + cy_stc_capsense_ofcd_context_t ofcdContext; /**< One-finger click and drag gesture context */ + cy_stc_capsense_tfsl_context_t tfslContext; /**< Two-finger scroll gesture context */ + + uint8_t numPosition; /**< Current number of touches */ + uint8_t numPositionLast; /**< Previous number of touches */ +} cy_stc_capsense_gesture_context_t; + +/** \} */ + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ +void Cy_CapSense_Gesture_ResetState( + cy_stc_capsense_gesture_context_t * context); +void Cy_CapSense_Gesture_Decode( + uint32_t timestamp, + uint32_t touchNumber, + const cy_stc_capsense_gesture_position_t * position, + const cy_stc_capsense_gesture_config_t * config, + cy_stc_capsense_gesture_context_t * context); + +/******************************************************************************* +* Macros +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_gesture *//** \{ */ +/******************************************************************************/ +/* Enable and Detection */ +/** No gesture detected */ +#define CY_CAPSENSE_GESTURE_NO_GESTURE (0x00u) +/** All gestures enable / detection mask */ +#define CY_CAPSENSE_GESTURE_ALL_GESTURES_MASK (0x03FFu) +/** Gesture enable filtering mask */ +#define CY_CAPSENSE_GESTURE_FILTERING_MASK (0x8000u) +/** Detection mask of Touchdown */ +#define CY_CAPSENSE_GESTURE_TOUCHDOWN_MASK (0x2000u) +/** Detection mask of Lift Off */ +#define CY_CAPSENSE_GESTURE_LIFTOFF_MASK (0x4000u) + +/** Enable / detection mask of one-finger single click gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_SINGLE_CLICK_MASK (0x0001u) +/** Enable / detection mask of one-finger double click gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_DOUBLE_CLICK_MASK (0x0002u) +/** Enable / detection mask of one-finger click and drag gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_CLICK_DRAG_MASK (0x0004u) +/** Enable / detection mask of two-finger single click gesture */ +#define CY_CAPSENSE_GESTURE_TWO_FNGR_SINGLE_CLICK_MASK (0x0008u) +/** Enable / detection mask of one-finger scroll gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_SCROLL_MASK (0x0010u) +/** Enable / detection mask of two-finger scroll gesture */ +#define CY_CAPSENSE_GESTURE_TWO_FNGR_SCROLL_MASK (0x0020u) +/** Enable / detection mask of one-finger edge swipe gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_EDGE_SWIPE_MASK (0x0040u) +/** Enable / detection mask of one-finger flick gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_FLICK_MASK (0x0080u) +/** Enable / detection mask of one-finger rotate gesture */ +#define CY_CAPSENSE_GESTURE_ONE_FNGR_ROTATE_MASK (0x0100u) +/** Enable / detection mask of two-finger zoom gesture */ +#define CY_CAPSENSE_GESTURE_TWO_FNGR_ZOOM_MASK (0x0200u) + +/* Direction Offsets */ +/** Offset of direction of one-finger scroll gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET_ONE_SCROLL (0x00u) +/** Offset of direction of two-finger scroll gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET_TWO_SCROLL (0x02u) +/** Offset of direction of one-finger edge swipe gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET_ONE_EDGE (0x04u) +/** Offset of direction of one-finger rotate gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET_ONE_ROTATE (0x06u) +/** Offset of direction of two-finger zoom gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET_TWO_ZOOM (0x07u) +/** Offset of direction of one-finger flick gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET_ONE_FLICK (0x08u) + +/* Direction Masks */ +/** Mask of direction of one-finger scroll gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_MASK_ONE_SCROLL (0x0003u) +/** Mask of direction of two-finger scroll gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_MASK_TWO_SCROLL (0x000Cu) +/** Mask of direction of one-finger edge swipe gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_MASK_ONE_EDGE (0x0030u) +/** Mask of direction of one-finger rotate gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_MASK_ONE_ROTATE (0x0040u) +/** Mask of direction of two-finger zoom gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_MASK_TWO_ZOOM (0x0080u) +/** Mask of direction of one-finger flick gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_MASK_ONE_FLICK (0x0700u) + +/** An extra direction offset returned by Cy_CapSense_DecodeWidgetGestures() */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OFFSET (16u) + +/* Direction */ +/** CLOCKWISE direction of Rotate gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_CW (0x00u) +/** COUNTER CLOCKWISE direction of Rotate gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_CCW (0x01u) + +/** ZOOM-IN direction of Zoom gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_IN (0x00u) +/** ZOOM-OUT direction of Zoom gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_OUT (0x01u) + +/** UP direction of Scroll, Flick and Edge Swipe gestures */ +#define CY_CAPSENSE_GESTURE_DIRECTION_UP (0x00u) +/** DOWN direction of Scroll, Flick and Edge Swipe gestures */ +#define CY_CAPSENSE_GESTURE_DIRECTION_DOWN (0x01u) +/** RIGHT direction of Scroll, Flick and Edge Swipe gestures */ +#define CY_CAPSENSE_GESTURE_DIRECTION_RIGHT (0x02u) +/** LEFT direction of Scroll, Flick and Edge Swipe gestures */ +#define CY_CAPSENSE_GESTURE_DIRECTION_LEFT (0x03u) +/** UP-RIGHT direction of Flick gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_UP_RIGHT (0x04u) +/** DOWN-LEFT direction of Flick gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_DOWN_LEFT (0x05u) +/** DOWN-RIGHT direction of Flick gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_DOWN_RIGHT (0x06u) +/** UP-LEFT direction of Flick gesture */ +#define CY_CAPSENSE_GESTURE_DIRECTION_UP_LEFT (0x07u) + +/** \} */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_GESTURE_LIB_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_lib.h b/cy_capsense_lib.h new file mode 100644 index 0000000..d428140 --- /dev/null +++ b/cy_capsense_lib.h @@ -0,0 +1,299 @@ +/***************************************************************************//** +* \file cy_capsense_lib.h +* \version 1.1 +* +* \brief +* The file contains application programming interface to the CapSense library. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_LIB_H) +#define CY_CAPSENSE_LIB_H + +#include "cy_syslib.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Public definitions +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_macros_touch *//** \{ */ +/******************************************************************************/ +/** No touch detected */ +#define CY_CAPSENSE_ADVANCED_CENTROID_NO_TOUCHES (0x00u) +/** Multiple touches detected */ +#define CY_CAPSENSE_ADVANCED_CENTROID_POSITION_ERROR (0xFFu) +/** \} */ + + +/******************************************************************************* +* Structures +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_structures *//** \{ */ +/******************************************************************************/ + +/** Declares Adaptive Filter configuration parameters */ +typedef struct +{ + uint8_t maxK; /**< Maximum filter coefficient */ + uint8_t minK; /**< Minimum filter coefficient */ + uint8_t noMovTh; /**< No-movement threshold */ + uint8_t littleMovTh; /**< Little movement threshold */ + uint8_t largeMovTh; /**< Large movement threshold */ + uint8_t divVal; /**< Divisor value */ + uint8_t reserved0; /**< Reserved field */ + uint8_t reserved1; /**< Reserved field */ +} cy_stc_capsense_adaptive_filter_config_t; + +/** Declares Advanced Centroid configuration parameters */ +typedef struct +{ + uint16_t fingerTh; /**< Finger threshold of widget */ + uint16_t penultimateTh; /**< Penultimate threshold */ + uint16_t virtualSnsTh; /**< Virtual sensor threshold */ + uint16_t resolutionX; /**< X axis maximum position */ + uint16_t resolutionY; /**< Y axis maximum position */ + uint8_t crossCouplingTh; /**< Cross-coupling threshold */ + uint8_t snsCountX; /**< Number of segments on X axis */ + uint8_t snsCountY; /**< Number of segments on Y axis */ + uint8_t edgeCorrectionEn; /**< Edge correction enabled */ + uint8_t twoFingersEn; /**< Two-finger detection enabled */ +} cy_stc_capsense_advanced_centroid_config_t; + +/** Declares position structure that keep information of a single touch. +* Depending on a widget type each structure field keeps the following +* information: +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +* +*
Structure FieldSliderMatrix ButtonsCSD TouchpadCSX Touchpad
xX-axis positionActive ColumnX-axis positionX-axis position
yReservedActive RowY-axis positionY-axis position
zReservedReservedReservedMSB = Age of touch; LSB = Z-value
idReservedLogical number of buttonReservedMSB = Debounce; LSB = touch ID
+*/ +typedef struct +{ + uint16_t x; /**< X position */ + uint16_t y; /**< Y position */ + uint16_t z; /**< Z value */ + uint16_t id; /**< ID of touch */ +} cy_stc_capsense_position_t; + +/** Declares touch structure used to store positions of Touchpad, Matrix buttons and Slider widgets */ +typedef struct +{ + cy_stc_capsense_position_t * ptrPosition; /**< Pointer to the array containing the position information. + A number of elements is defined by numPosition. */ + uint8_t numPosition; /**< Total number of detected touches on a widget: + * * 0 - no touch is detected + * * 1 - a single touch is detected + * * 2 - two touches are detected + * * 3 - three touches are detected + * * CY_CAPSENSE_POSITION_MULTIPLE - multiple touches are detected + * and information in position structure should be ignored. + */ +} cy_stc_capsense_touch_t; + +/** Declares HW SmartSense data structure for CSD widgets */ +typedef struct +{ + uint32_t sensorCap; /**< Sensor parasitic capacitance in fF 10^-15 */ + uint32_t iDacGain; /**< IDAC gain in pA */ + uint16_t * ptrSenseClk; /**< Pointer to SnsClk divider */ + uint16_t * sigPFC; /**< Pointer to sigPFC value (Signal Per Finger Capacitance) */ + uint16_t snsClkConstantR; /**< Resistance in series to a sensor */ + uint16_t vRef; /**< Vref in mVolts */ + uint16_t fingerCap; /**< Finger capacitance in fF 10^-15 (Set in Basic tab in pF 10^-12) */ + uint16_t snsClkInputClock; /**< Frequency for sense clock divider in kHz */ + uint16_t calTarget; /**< Calibration target in percentage */ + uint8_t iDacMod; /**< Modulation idac code */ + uint8_t iDacComp; /**< Compensation idac code */ +} cy_stc_capsense_auto_tune_config_t; + +/** Declares Noise envelope data structure for CSD widgets when SmartSense is enabled */ +typedef struct +{ + uint16_t param0; /**< Parameter 0 configuration */ + uint16_t param1; /**< Parameter 1 configuration */ + uint16_t param2; /**< Parameter 2 configuration */ + uint16_t param3; /**< Parameter 3 configuration */ + uint16_t param4; /**< Parameter 4 configuration */ + uint8_t param5; /**< Parameter 5 configuration */ + uint8_t param6; /**< Parameter 6 configuration */ +} cy_stc_capsense_smartsense_csd_noise_envelope_t; + +/** Declares Update Thresholds structure */ +typedef struct +{ + uint16_t fingerTh; /**< Widget finger threshold */ + uint8_t noiseTh; /**< Widget noise threshold */ + uint8_t nNoiseTh; /**< Widget negative noise threshold */ + uint8_t hysteresis; /**< Widget hysteresis for the signal crossing finger threshold */ +} cy_stc_capsense_smartsense_update_thresholds_t; + +/** Declares Ballistics Multiplier Configuration data structure */ +typedef struct +{ + uint8_t accelCoeff; /**< Acceleration Coefficient */ + uint8_t speedCoeff; /**< Speed Coefficient */ + uint8_t divisorValue; /**< Divisor Value */ + uint8_t speedThresholdX; /**< Speed Threshold X */ + uint8_t speedThresholdY; /**< Speed Threshold Y */ + uint8_t reserved0; /**< Reserved field */ + uint8_t reserved1; /**< Reserved field */ + uint8_t reserved2; /**< Reserved field */ +} cy_stc_capsense_ballistic_config_t; + +/** Declares Ballistics Multiplier Configuration data structure */ +typedef struct +{ + uint32_t currentTimestamp; /**< Current timestamp */ + uint32_t oldTimestamp; /**< Previous timestamp */ + int32_t deltaXfrac; /**< Fraction of X-axis displacement */ + int32_t deltaYfrac; /**< Fraction of Y-axis displacement */ + uint16_t x; /**< X-axis position */ + uint16_t y; /**< Y-axis position */ + uint8_t touchNumber; /**< Current number of touches */ + uint8_t oldTouchNumber; /**< Previous number of touches */ + uint8_t reserved0; /**< Reserved field */ + uint8_t reserved1; /**< Reserved field */ +} cy_stc_capsense_ballistic_context_t; + +/** Declares Ballistic Displacement structure */ +typedef struct +{ + int16_t deltaX; /**< X-axis displacement */ + int16_t deltaY; /**< Y-axis displacement */ +} cy_stc_capsense_ballistic_delta_t; + +/** \} */ + +/** Declares ALP filter data structure */ +typedef struct +{ + uint32_t dataParam0; /**< Parameter 0 context */ + uint16_t dataParam1; /**< Parameter 1 context */ + uint16_t dataParam2; /**< Parameter 2 context */ + uint16_t dataParam3; /**< Parameter 3 context */ + uint16_t dataParam4; /**< Parameter 4 context */ + uint16_t dataParam5; /**< Parameter 5 context */ + uint16_t dataParam6; /**< Parameter 6 context */ + uint8_t dataParam7; /**< Parameter 7 context */ +} cy_stc_capsense_alp_fltr_channel_t; + +/** Declares ALP filter configuration structure */ +typedef struct +{ + uint16_t configParam0; /**< Parameter 0 configuration */ + uint16_t configParam1; /**< Parameter 1 configuration */ + uint16_t configParam2; /**< Parameter 2 configuration */ + uint8_t configParam3; /**< Parameter 3 configuration */ + uint8_t configParam4; /**< Parameter 4 configuration */ + uint8_t configParam5; /**< Parameter 5 configuration */ +} cy_stc_capsense_alp_fltr_config_t; + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ +void Cy_CapSense_AdaptiveFilterInitialize_Lib( + const cy_stc_capsense_adaptive_filter_config_t * config, + cy_stc_capsense_position_t * context); +void Cy_CapSense_AdaptiveFilterRun_Lib( + const cy_stc_capsense_adaptive_filter_config_t * config, + cy_stc_capsense_position_t * context, + uint32_t * currentX, + uint32_t * currentY); +void Cy_CapSense_AdvancedCentroidGetTouchCoordinates_Lib( + const cy_stc_capsense_advanced_centroid_config_t * config, + const uint16_t * ptrSns, + cy_stc_capsense_touch_t * touch); +void Cy_CapSense_BallisticMultiplier_Lib( + const cy_stc_capsense_ballistic_config_t * config, + cy_stc_capsense_touch_t * touch, + cy_stc_capsense_ballistic_delta_t * delta, + uint32_t timestamp, + cy_stc_capsense_ballistic_context_t * context); +void Cy_CapSense_AlpRun_Lib( + cy_stc_capsense_alp_fltr_channel_t * ptrFilterObj, + const cy_stc_capsense_alp_fltr_config_t * ptrFilterConfig, + uint16_t * rawCount, + const uint16_t * baseline); +void Cy_CapSense_AlpInitialize_Lib( + cy_stc_capsense_alp_fltr_channel_t * ptrFilterObj, + const uint16_t * rawCount); +void Cy_CapSense_AlpResetState_Lib( + cy_stc_capsense_alp_fltr_channel_t * ptrFilterObj); +uint32_t Cy_CapSense_AlpGetAverage_Lib( + const cy_stc_capsense_alp_fltr_channel_t * ptrFilterObj); +uint32_t Cy_CapSense_TunePrescalers_Lib( + cy_stc_capsense_auto_tune_config_t * config); +uint8_t Cy_CapSense_TuneSensitivity_Lib( + cy_stc_capsense_auto_tune_config_t * config); +void Cy_CapSense_UpdateThresholds_Lib( + const cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNoiseEnvelope, + cy_stc_capsense_smartsense_update_thresholds_t * ptrThresholds, + uint16_t sigPFC, + uint32_t startFlag); +void Cy_CapSense_InitializeNoiseEnvelope_Lib( + uint16_t rawCount, + uint16_t sigPFC, + cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNoiseEnvelope); +void Cy_CapSense_RunNoiseEnvelope_Lib( + uint16_t rawCount, + uint16_t sigPFC, + cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNoiseEnvelope); + + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_LIB_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_processing.c b/cy_capsense_processing.c new file mode 100644 index 0000000..5551724 --- /dev/null +++ b/cy_capsense_processing.c @@ -0,0 +1,1470 @@ +/***************************************************************************//** +* \file cy_capsense_processing.c +* \version 1.1 +* +* \brief +* This file provides the source code for the Data Processing module functions. +* The Data Processing module is responsible for the low-level raw count +* processing provided by the sensing module, maintaining baseline and +* difference values and performing high-level widget processing like +* updating button status or calculating slider position. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include "cy_syslib.h" +#include +#include +#include "cy_capsense_common.h" +#include "cy_capsense_processing.h" +#include "cy_capsense_filter.h" +#include "cy_capsense_lib.h" +#include "cy_capsense_sensing.h" +#include "cy_capsense_centroid.h" + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeAllStatuses +****************************************************************************//** +* +* Performs initialization of all statuses and related modules including +* debounce counters and touch positions of all the widgets. +* +* The initialization includes the following tasks: +* * Reset the debounce counters of all the widgets. +* * Reset the number of touches. +* * Reset the position filter history for slider and touchpad widgets. +* * Clear all status of widgets and sensors. +* * Enable all the widgets. +* +* Calling this function is accompanied by +* * Cy_CapSense_InitializeAllBaselines(). +* * Cy_CapSense_InitializeAllFilters(). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeAllStatuses(const cy_stc_capsense_context_t * context) +{ + uint32_t widgetId; + + for(widgetId = context->ptrCommonConfig->numWd; widgetId-- > 0u;) + { + Cy_CapSense_InitializeWidgetStatus(widgetId, context); + Cy_CapSense_InitializeWidgetGestures(widgetId, context); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeWidgetStatus +****************************************************************************//** +* +* Performs initialization of all statuses, debounce counters, and touch positions +* of the specified widget. +* +* The initialization includes: +* * Resets the debounce counter of the widget. +* * Resets the number of touches. +* * Resets the position filter history for slider and touchpad widgets. +* * Clears widget and sensor statuses. +* * Enables the widget. +* +* The Button and Matrix Button widgets have individual debounce counters per +* sensor for the CSD widgets and per node for the CSX widgets. +* +* The Slider and Touchpad widgets have a single debounce counter per widget. +* +* The Proximity widget has two debounce counters per sensor. One is for the +* proximity event and the second is for the touch event. +* +* All debounce counters during initialization are set to the value of the +* onDebounce widget parameter. +* +* Calling this function is accompanied by +* * Cy_CapSense_InitializeWidgetBaseline(). +* * Cy_CapSense_InitializeWidgetFilter(). +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeWidgetStatus( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t filterSize; + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdCfg->ptrWdContext; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdCfg->ptrSnsContext; + uint32_t snsNumber = ptrWdCfg->numSns; + cy_stc_capsense_position_t * ptrHistory; + + /* Clear widget statuses (Non active, Not disabled, Working) */ + ptrWdCxt->status &= (uint8_t)~(CY_CAPSENSE_WD_ACTIVE_MASK | + CY_CAPSENSE_WD_DISABLE_MASK | + CY_CAPSENSE_WD_WORKING_MASK); + /* Clear sensor status */ + for (snsIndex = snsNumber; snsIndex-- >0u;) + { + ptrSnsCxt->status &= (uint8_t)~(CY_CAPSENSE_SNS_TOUCH_STATUS_MASK | CY_CAPSENSE_SNS_PROX_STATUS_MASK); + ptrSnsCxt++; + } + + /* Reset debounce counters */ + switch (ptrWdCfg->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E: + case (uint8_t)CY_CAPSENSE_WD_BUTTON_E: + /* Each button requires one debounce counter */ + (void)memset(ptrWdCfg->ptrDebounceArr, (int32_t)ptrWdCxt->onDebounce, (size_t)snsNumber); + break; + case (uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E: + case (uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E: + case (uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E: + /* Each widget requires one debounce counter */ + if (ptrWdCfg->senseMethod == (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E) + { + *(ptrWdCfg->ptrDebounceArr) = ptrWdCxt->onDebounce; + } + else + { + /* + * CSX Touchpad has debounce located in another place. Moreover, + * debounce counter is initialized at ID assignment, so no need + * to do it here. + */ + } + break; + case (uint8_t)CY_CAPSENSE_WD_PROXIMITY_E: + /* Proximity widgets have 2 debounce counters per sensor (for touch and prox detection) */ + (void)memset(ptrWdCfg->ptrDebounceArr, (int32_t)ptrWdCxt->onDebounce, (size_t)(snsNumber << 1u)); + break; + default: + break; + } + + /* Reset touch numbers */ + switch (ptrWdCfg->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E: + case (uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E: + case (uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E: + case (uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E: + /* Clean number of touches */ + ptrWdCxt->wdTouch.numPosition = CY_CAPSENSE_POSITION_NONE; + if (0u != (ptrWdCfg->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_MASK)) + { + ptrWdCfg->ptrPosFilterHistory->numPosition = CY_CAPSENSE_POSITION_NONE; + } + break; + default: + break; + } + + /* Reset ballistic displacement */ + if (0u != (ptrWdCfg->centroidConfig & CY_CAPSENSE_CENTROID_BALLISTIC_MASK)) + { + ptrWdCxt->xDelta = 0; + ptrWdCxt->yDelta = 0; + ptrWdCfg->ptrBallisticContext->oldTouchNumber = 0u; + } + + /* Reset touch history */ + if (0u != (ptrWdCfg->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_MASK)) + { + switch (ptrWdCfg->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E: + /* Clean position filter history */ + if (ptrWdCfg->senseMethod == (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E) + { + /* Reset all history IDs to undefined state */ + ptrHistory = ptrWdCfg->ptrPosFilterHistory->ptrPosition; + filterSize = (ptrWdCfg->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_SIZE_MASK) >> CY_CAPSENSE_POSITION_FILTERS_SIZE_OFFSET; + for (snsIndex = 0u; snsIndex < CY_CAPSENSE_MAX_CENTROIDS; snsIndex++) + { + ptrHistory->id = CY_CAPSENSE_CSX_TOUCHPAD_ID_UNDEFINED; + ptrHistory += filterSize; + } + } + break; + default: + break; + } + /* Init Adaptive IIR filter */ + if (0u != (ptrWdCfg->posFilterConfig & CY_CAPSENSE_POSITION_AIIR_MASK)) + { + Cy_CapSense_AdaptiveFilterInitialize_Lib(&ptrWdCfg->aiirConfig, + ptrWdCfg->ptrPosFilterHistory->ptrPosition); + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeWidgetGestures +****************************************************************************//** +* +* Performs initialization of all gestures for the specified widget. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeWidgetGestures( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdCfg->ptrWdContext; + + if (((uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrWdCfg->wdType)) + { + if (NULL != ptrWdCfg->ptrGestureConfig) + { + if (0u != (ptrWdCfg->ptrGestureConfig->gestureEnableMask & CY_CAPSENSE_GESTURE_ALL_GESTURES_MASK)) + { + ptrWdCxt->gestureDetected = 0u; + ptrWdCxt->gestureDirection = 0u; + Cy_CapSense_Gesture_ResetState(ptrWdCfg->ptrGestureContext); + } + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DecodeWidgetGestures +****************************************************************************//** +* +* Performs processing of all gestures for the specified widget. +* +* This function should be called by application program only after all sensors +* are scanned and all data processing is executed using +* Cy_CapSense_ProcessAllWidgets() or Cy_CapSense_ProcessWidget() functions +* for the widget. Calling this function multiple times without a new sensor +* scan and process causes unexpected behavior. +* +* \note The function (Gesture detection functionality) requires a timestamp +* for its operation. The timestamp should be initialized and maintained +* in the application program prior to calling this function. See the +* descriptions of the Cy_CapSense_SetGestureTimestamp() and +* Cy_CapSense_IncrementGestureTimestamp() functions for details. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the detected Gesture mask and direction of detected gestures. +* The same information is stored in ptrWdContext->gestureDetected and +* ptrWdContext->gestureDirection registers. Corresponding macros could be found +* \ref group_capsense_macros_gesture. +* * bit[0..15] - detected gesture masks gesture +* * bit[0] - one-finger single click gesture +* * bit[1] - one-finger double click gesture +* * bit[2] - one-finger click and drag gesture +* * bit[3] - two-finger single click gesture +* * bit[4] - one-finger scroll gesture +* * bit[5] - two-finger scroll gesture +* * bit[6] - one-finger edge swipe +* * bit[7] - one-finger flick +* * bit[8] - one-finger rotate +* * bit[9] - two-finger zoom +* * bit[13] - touchdown event +* * bit[14] - liftoff event +* * bit[16..31] - gesture direction if detected +* * bit[0..1] - direction of one-finger scroll gesture +* * bit[2..3] - direction of two-finger scroll gesture +* * bit[4..5] - direction of one-finger edge swipe gesture +* * bit[6] - direction of one-finger rotate gesture +* * bit[7] - direction of two-finger zoom gesture +* * bit[8..10] - direction of one-finger flick gesture +* +* \funcusage +* +* An example of gesture decoding: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Gesture +* +* An example of gesture status parsing: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Gesture_Macro +* +*******************************************************************************/ +uint32_t Cy_CapSense_DecodeWidgetGestures( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + uint32_t gestureStatus = 0u; + uint32_t posIndex; + uint32_t positionNum; + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdCfg->ptrWdContext; + cy_stc_capsense_gesture_position_t position[CY_CAPSENSE_MAX_CENTROIDS]; + + if (((uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrWdCfg->wdType)) + { + if (NULL != ptrWdCfg->ptrGestureConfig) + { + if (0u != (ptrWdCfg->ptrGestureConfig->gestureEnableMask & CY_CAPSENSE_GESTURE_ALL_GESTURES_MASK)) + { + positionNum = ptrWdCxt->wdTouch.numPosition; + if (positionNum > CY_CAPSENSE_MAX_CENTROIDS) + { + positionNum = 0u; + } + for (posIndex = 0u; posIndex < positionNum; posIndex++) + { + position[posIndex].x = ptrWdCxt->wdTouch.ptrPosition[posIndex].x; + position[posIndex].y = ptrWdCxt->wdTouch.ptrPosition[posIndex].y; + } + Cy_CapSense_Gesture_Decode(context->ptrCommonContext->timestamp, (uint32_t)ptrWdCxt->wdTouch.numPosition, + &position[0u], ptrWdCfg->ptrGestureConfig, ptrWdCfg->ptrGestureContext); + ptrWdCxt->gestureDetected = ptrWdCfg->ptrGestureContext->detected; + ptrWdCxt->gestureDirection = ptrWdCfg->ptrGestureContext->direction; + gestureStatus = (uint32_t)ptrWdCxt->gestureDetected | ((uint32_t)ptrWdCxt->gestureDirection << CY_CAPSENSE_GESTURE_DIRECTION_OFFSET); + } + } + } + return gestureStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsxWidgetRawCounts +****************************************************************************//** +* +* Performs default processing of the raw counts of the specified CSX widget. +* +* The processing includes the following tasks: +* - Run Filters. +* - Update Baselines. +* - Update Differences. +* The same process is applied to all the sensors of the specified widget. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified widget processing operation: +* - Zero - if operation was successfully completed; +* - Non-zero - if baseline processing of any sensor of the specified widget +* failed. The result is concatenated with the index of failed sensor. +* +*******************************************************************************/ +uint32_t Cy_CapSense_DpProcessCsxWidgetRawCounts( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = CY_RET_SUCCESS; + uint32_t snsIndex; + uint32_t snsHistorySize; + uint32_t freqChIndex; + uint32_t freqChNumber; + uint16_t * ptrHistoryCh; + uint16_t * ptrHistorySns; + uint8_t * ptrHistoryLowCh = NULL; + uint8_t * ptrHistoryLowSns = NULL; + cy_stc_capsense_sensor_context_t * ptrSnsCxtCh; + cy_stc_capsense_sensor_context_t * ptrSnsCxtSns; + + + snsHistorySize = (uint32_t)ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + + ptrSnsCxtCh = &ptrWdConfig->ptrSnsContext[0u]; + ptrHistoryCh = &ptrWdConfig->ptrRawFilterHistory[0u]; + if(CY_CAPSENSE_IIR_FILTER_PERFORMANCE == (ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + ptrHistoryLowCh = &ptrWdConfig->ptrRawFilterHistoryLow[0u]; + } + + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrSnsCxtSns = ptrSnsCxtCh; + ptrHistorySns = ptrHistoryCh; + ptrHistoryLowSns = ptrHistoryLowCh; + for (snsIndex = 0u; snsIndex < ptrWdConfig->numSns; snsIndex++) + { + Cy_CapSense_FtRunEnabledFiltersInternal(ptrWdConfig, ptrSnsCxtSns, ptrHistorySns, ptrHistoryLowSns); + + result |= Cy_CapSense_FtUpdateBaseline(ptrWdConfig->ptrWdContext, ptrSnsCxtSns, context); + Cy_CapSense_DpUpdateDifferences(ptrWdConfig->ptrWdContext, ptrSnsCxtSns); + + ptrSnsCxtSns++; + ptrHistorySns += snsHistorySize; + if(NULL != ptrHistoryLowSns) + { + ptrHistoryLowSns++; + } + } + + ptrSnsCxtCh += context->ptrCommonConfig->numSns; + ptrHistoryCh += context->ptrCommonConfig->numSns * snsHistorySize; + if(NULL != ptrHistoryLowCh) + { + ptrHistoryLowCh += context->ptrCommonConfig->numSns; + } + } + + if(CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) + { + ptrSnsCxtSns = ptrWdConfig->ptrSnsContext; + for (snsIndex = ptrWdConfig->numSns; snsIndex-- > 0u;) + { + Cy_CapSense_RunMfsFiltering(ptrSnsCxtSns, context); + ptrSnsCxtSns++; + } + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsxWidgetStatus +****************************************************************************//** +* +* Updates the status of the CSX widget in the Data Structure. +* +* This function determines the type of widget and runs the appropriate function +* that implements the status update algorithm for this type of widget. +* +* When the widget-specific processing completes this function updates the +* sensor and widget status registers in the data structure. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessCsxWidgetStatus( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + switch (ptrWdConfig->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_BUTTON_E: + case (uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E: + Cy_CapSense_DpProcessButton(ptrWdConfig, context); + break; + + case (uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E: + Cy_CapSense_DpProcessCsxTouchpad(ptrWdConfig, context); + break; + + default: + CY_ASSERT(0 != 0); + break; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsxSensorRawCountsExt +****************************************************************************//** +* +* Performs customized processing of the CSX sensor raw counts. +* +* If all bits are set at once, the default processing order will take place. +* For a custom order, this function can be called multiple times and execute +* one task at a time. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history. +* +* \param ptrSnsRawHistoryLow +* The pointer to the extended filter history. +* +* \param mode +* The bit-mask with the data processing tasks to be executed. +* The mode parameters can take the following values: +* - CY_CAPSENSE_PROCESS_FILTER (0x01) Run Firmware Filter +* - CY_CAPSENSE_PROCESS_BASELINE (0x02) Update Baselines +* - CY_CAPSENSE_PROCESS_DIFFCOUNTS (0x04) Update Difference Counts +* - CY_CAPSENSE_PROCESS_ALL Execute all tasks +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified sensor processing operation: +* - CY_RET_SUCCESS if operation was successfully completed; +* - CY_CAPSENSE_PROCESS_BASELINE_FAILED if baseline processing of any +* sensor of the specified widget failed. The result is concatenated with the index +* of failed sensor. +* +*******************************************************************************/ +uint32_t Cy_CapSense_DpProcessCsxSensorRawCountsExt( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow, + uint32_t mode, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = CY_RET_SUCCESS; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + + if (0u != (mode & CY_CAPSENSE_PROCESS_FILTER)) + { + Cy_CapSense_FtRunEnabledFiltersInternal(ptrWdConfig, + ptrSnsContext, + ptrSnsRawHistory, + ptrSnsRawHistoryLow); + } + + if (0u != (mode & CY_CAPSENSE_PROCESS_BASELINE)) + { + result = Cy_CapSense_FtUpdateBaseline(ptrWdCxt, ptrSnsContext, context); + } + if (0u != (mode & CY_CAPSENSE_PROCESS_DIFFCOUNTS)) + { + Cy_CapSense_DpUpdateDifferences(ptrWdCxt, ptrSnsContext); + } + + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsdWidgetRawCounts +****************************************************************************//** +* +* Performs default processing of the raw counts of the specified CSD widget. +* +* The processing includes the following tasks: +* - Run Filters. +* - Update Baselines. +* - Update Differences. +* The same process is applied to all the sensors of the specified widget. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified widget processing operation: +* - Zero - if operation was successfully completed. +* - Non-zero - if baseline processing of any sensor of the specified widget +* failed. The result is concatenated with the index of failed sensor. +* +*******************************************************************************/ +uint32_t Cy_CapSense_DpProcessCsdWidgetRawCounts( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = CY_RET_SUCCESS; + uint32_t snsIndex; + uint32_t snsHistorySize; + uint32_t freqChIndex; + uint32_t freqChNumber; + uint16_t * ptrHistoryCh; + uint16_t * ptrHistorySns; + uint8_t * ptrHistoryLowCh = NULL; + uint8_t * ptrHistoryLowSns = NULL; + cy_stc_capsense_sensor_context_t * ptrSnsCxtCh; + cy_stc_capsense_sensor_context_t * ptrSnsCxtSns; + cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNEHistory = ptrWdConfig->ptrNoiseEnvelope; + + snsHistorySize = (uint32_t)ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_SNS_HISTORY_SIZE_MASK; + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + + ptrSnsCxtCh = &ptrWdConfig->ptrSnsContext[0u]; + ptrHistoryCh = &ptrWdConfig->ptrRawFilterHistory[0u]; + if(CY_CAPSENSE_IIR_FILTER_PERFORMANCE == (ptrWdConfig->rawFilterConfig & CY_CAPSENSE_RC_FILTER_IIR_MODE_MASK)) + { + ptrHistoryLowCh = &ptrWdConfig->ptrRawFilterHistoryLow[0u]; + } + + for(freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrSnsCxtSns = ptrSnsCxtCh; + ptrHistorySns = ptrHistoryCh; + ptrHistoryLowSns = ptrHistoryLowCh; + for (snsIndex = 0u; snsIndex < ptrWdConfig->numSns; snsIndex++) + { + Cy_CapSense_FtRunEnabledFiltersInternal(ptrWdConfig, ptrSnsCxtSns, ptrHistorySns, ptrHistoryLowSns); + + /* Run auto-tuning activities */ + if (CY_CAPSENSE_CSD_SS_HWTH_EN == context->ptrCommonConfig->csdAutotuneEn) + { + Cy_CapSense_RunNoiseEnvelope_Lib(ptrSnsCxtSns->raw, ptrWdConfig->ptrWdContext->sigPFC, ptrNEHistory); + Cy_CapSense_DpUpdateThresholds(ptrWdConfig->ptrWdContext, ptrNEHistory, snsIndex); + if ((uint8_t)CY_CAPSENSE_WD_PROXIMITY_E == ptrWdConfig->wdType) + { + ptrWdConfig->ptrWdContext->proxTh = (uint16_t)(((uint32_t)ptrWdConfig->ptrWdContext->fingerTh * + context->ptrCommonConfig->proxTouchCoeff) / CY_CAPSENSE_PERCENTAGE_100); + } + ptrNEHistory++; + } + + result |= Cy_CapSense_FtUpdateBaseline(ptrWdConfig->ptrWdContext, ptrSnsCxtSns, context); + Cy_CapSense_DpUpdateDifferences(ptrWdConfig->ptrWdContext, ptrSnsCxtSns); + + ptrSnsCxtSns++; + ptrHistorySns += snsHistorySize; + if(NULL != ptrHistoryLowSns) + { + ptrHistoryLowSns++; + } + + } + + ptrSnsCxtCh += context->ptrCommonConfig->numSns; + ptrHistoryCh += context->ptrCommonConfig->numSns * snsHistorySize; + if(NULL != ptrHistoryLowCh) + { + ptrHistoryLowCh += context->ptrCommonConfig->numSns; + } + + } + + if(CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) + { + ptrSnsCxtSns = ptrWdConfig->ptrSnsContext; + for (snsIndex = ptrWdConfig->numSns; snsIndex-- > 0u;) + { + Cy_CapSense_RunMfsFiltering(ptrSnsCxtSns, context); + ptrSnsCxtSns++; + } + } + + return result; + +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsdSensorRawCountsExt +****************************************************************************//** +* +* Performs customized processing of the CSX sensor raw counts. +* +* If all bits are set at once, the default processing order will take place. +* For a custom order, this function can be called multiple times and execute +* one task at a time. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +* \param ptrSnsRawHistory +* The pointer to the filter history. +* +* \param ptrSnsRawHistoryLow +* The pointer to the extended filter history. +* +* \param mode +* The bit-mask with the data processing tasks to be executed. +* The mode parameters can take the following values: +* - CY_CAPSENSE_PROCESS_FILTER (0x01) Run Firmware Filter +* - CY_CAPSENSE_PROCESS_BASELINE (0x02) Update Baselines +* - CY_CAPSENSE_PROCESS_DIFFCOUNTS (0x04) Update Difference Counts +* - CY_CAPSENSE_PROCESS_CALC_NOISE (0x08) Calculate Noise (only if FW Tuning is enabled) +* - CY_CAPSENSE_PROCESS_THRESHOLDS (0x10) Update Thresholds (only if FW Tuning is enabled) +* - CY_CAPSENSE_PROCESS_ALL Execute all tasks +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified sensor processing operation: +* - CY_RET_SUCCESS if operation was successfully completed. +* - CY_CAPSENSE_PROCESS_BASELINE_FAILED if baseline processing of any +* sensor of the specified widget failed. The result is concatenated with the index +* of the failed sensor. +* +*******************************************************************************/ +uint32_t Cy_CapSense_DpProcessCsdSensorRawCountsExt( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow, + uint32_t mode, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = CY_RET_SUCCESS; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + + if (0u != (mode & CY_CAPSENSE_PROCESS_FILTER)) + { + Cy_CapSense_FtRunEnabledFiltersInternal(ptrWdConfig, + ptrSnsContext, + ptrSnsRawHistory, + ptrSnsRawHistoryLow); + } + + if (0u != (mode & CY_CAPSENSE_PROCESS_BASELINE)) + { + result = Cy_CapSense_FtUpdateBaseline(ptrWdCxt, ptrSnsContext, context); + } + if (0u != (mode & CY_CAPSENSE_PROCESS_DIFFCOUNTS)) + { + Cy_CapSense_DpUpdateDifferences(ptrWdCxt, ptrSnsContext); + } + + return result; +} + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsdWidgetStatus +****************************************************************************//** +* +* Updates the status of the CSD widget in the Data Structure. +* +* This function determines the type of widget and runs the appropriate function +* that implements the status update algorithm for this type of widget. +* +* When the widget-specific processing completes this function updates the +* sensor and widget status registers in the data structure. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessCsdWidgetStatus( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + switch (ptrWdConfig->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_BUTTON_E: + Cy_CapSense_DpProcessButton(ptrWdConfig, context); + break; + + case (uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E: + case (uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E: + Cy_CapSense_DpProcessSlider(ptrWdConfig, context); + break; + + case (uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E: + Cy_CapSense_DpProcessCsdMatrix(ptrWdConfig, context); + break; + + case (uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E: + Cy_CapSense_DpProcessCsdTouchpad(ptrWdConfig, context); + break; + + case (uint8_t)CY_CAPSENSE_WD_PROXIMITY_E: + Cy_CapSense_DpProcessProximity(ptrWdConfig); + break; + + default: + break; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpUpdateThresholds +****************************************************************************//** +* +* Updates noise and finger thresholds for a specified widget. +* +* This algorithm is a part of SmartSense feature. +* +* \param ptrWdContext +* The pointer to the widget context structure. +* +* \param ptrNoiseEnvelope +* The pointer to the noise-envelope history structure. +* +* \param startFlag +* The flag indicates when a new widget is processed. +* +*******************************************************************************/ +void Cy_CapSense_DpUpdateThresholds( + cy_stc_capsense_widget_context_t * ptrWdContext, + const cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNoiseEnvelope, + uint32_t startFlag) +{ + cy_stc_capsense_smartsense_update_thresholds_t thresholds; + + /* Calculate Thresholds */ + thresholds.fingerTh = ptrWdContext->fingerTh; + Cy_CapSense_UpdateThresholds_Lib(ptrNoiseEnvelope, &thresholds, ptrWdContext->sigPFC, startFlag); + + /* Update CapSense context */ + ptrWdContext->fingerTh = thresholds.fingerTh; + ptrWdContext->noiseTh = thresholds.noiseTh; + ptrWdContext->nNoiseTh = thresholds.nNoiseTh; + ptrWdContext->hysteresis = thresholds.hysteresis; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpUpdateDifferences +****************************************************************************//** +* +* Calculates new difference values. +* +* This function calculates the difference between the baseline and raw counts. +* If the difference is positive (raw > baseline), and higher than the widget +* noise threshold, it is saved into the data structure for further processing. +* Otherwise the difference is set to zero. The final difference value is saved +* with the subtracted noise threshold value. +* +* \param ptrWdContext +* The pointer to the widget context structure. +* +* \param ptrSnsContext +* The pointer to the sensor context structure. +* +*******************************************************************************/ +void Cy_CapSense_DpUpdateDifferences( + const cy_stc_capsense_widget_context_t * ptrWdContext, + cy_stc_capsense_sensor_context_t * ptrSnsContext) +{ + ptrSnsContext->diff = 0u; + if (ptrSnsContext->raw > (ptrSnsContext->bsln + ptrWdContext->noiseTh)) + { + ptrSnsContext->diff = ptrSnsContext->raw - ptrSnsContext->bsln; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessButton +****************************************************************************//** +* +* Processes the status of the Button widget. +* +* This function processes the status of the CSD/CSX Button widget and +* CSX Matrix Button widget. It applies the hysteresis and debounce algorithm +* to each sensor difference value. This function is expected to be called +* after each new widget scan. If it is called multiple times for the same +* scan data, the debounce algorithm will not work properly. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessButton( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t activeCount = 0u; + uint32_t startIndex = 0u; + uint32_t touchTh; + uint8_t * ptrDebounceCnt = ptrWdConfig->ptrDebounceArr; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + + ptrWdCxt->status &= (uint8_t)~CY_CAPSENSE_WD_ACTIVE_MASK; + + /* Go through all widget's sensors */ + for (snsIndex = 0u; snsIndex < ptrWdConfig->numSns; snsIndex++) + { + /* Calculate touch threshold based on current sensor state */ + touchTh = (0u == ptrSnsCxt->status) ? + ((uint32_t)ptrWdCxt->fingerTh + ptrWdCxt->hysteresis) : + ((uint32_t)ptrWdCxt->fingerTh - ptrWdCxt->hysteresis); + + if (0u < (*ptrDebounceCnt)) + { + /* Decrement debounce counter */ + (*ptrDebounceCnt)--; + } + + /* No touch */ + if (ptrSnsCxt->diff <= touchTh) + { + /* Reset debounce counter */ + *ptrDebounceCnt = ptrWdCxt->onDebounce; + ptrSnsCxt->status = 0u; + } + + /* New touch or touch still exists */ + if (0u == (*ptrDebounceCnt)) + { + ptrSnsCxt->status = CY_CAPSENSE_SNS_TOUCH_STATUS_MASK; + activeCount++; + startIndex = snsIndex; + } + + /* Update widget status */ + if (0u != ptrSnsCxt->status) + { + ptrWdCxt->status |= (uint8_t)CY_CAPSENSE_WD_ACTIVE_MASK; + } + + ptrSnsCxt++; + ptrDebounceCnt++; + } + /* Update position struct */ + if (((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == ptrWdConfig->wdType) && + ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E == ptrWdConfig->senseMethod)) + { + ptrWdCxt->wdTouch.numPosition = (uint8_t)activeCount; + ptrWdCxt->wdTouch.ptrPosition->id = (uint16_t)startIndex; + ptrWdCxt->wdTouch.ptrPosition->x = (uint16_t)(startIndex / ptrWdConfig->numRows); + ptrWdCxt->wdTouch.ptrPosition->y = (uint16_t)(startIndex % ptrWdConfig->numRows); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessProximity +****************************************************************************//** +* +* Processes the status of the Proximity widget. +* +* This function processes the status of the CSD Proximity widget. It applies the +* hysteresis and debounce algorithm to each sensor difference value. +* The proximity and touch events are considered independently so debounce and +* hysteresis are also applied independently. +* +* This function is expected to be called after each new widget scan. If it is +* called multiple times for the same scan data the debounce algorithm +* will not work properly. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessProximity(const cy_stc_capsense_widget_config_t * ptrWdConfig) +{ + uint32_t snsTh; + uint32_t snsIndex; + uint32_t snsStMask; + + uint8_t * ptrDebounceCnt = ptrWdConfig->ptrDebounceArr; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + + /* Reset widget status */ + ptrWdCxt->status &= (uint8_t)~CY_CAPSENSE_WD_ACTIVE_MASK; + + /* Go through all sensor's status bits */ + for (snsIndex = 0u; snsIndex < ((uint32_t)ptrWdConfig->numSns << 1u); snsIndex++) + { + /* + * Proximity - odd; Touch - even. Example: + * Bit 0 -> touch event + * Bit 1 -> proximity event + */ + snsTh = ptrWdCxt->proxTh; + snsStMask = CY_CAPSENSE_SNS_PROX_STATUS_MASK; + if (0u == (snsIndex & 0x01u)) + { + snsTh = ptrWdCxt->fingerTh; + snsStMask = CY_CAPSENSE_SNS_TOUCH_STATUS_MASK; + } + /* Calculate threshold based on current sensor state */ + snsTh = (0u == (snsStMask & ptrSnsCxt->status)) ? + (snsTh + ptrWdCxt->hysteresis) : + (snsTh - ptrWdCxt->hysteresis); + + if (0u < (*ptrDebounceCnt)) + { + /* Decrement debounce counter */ + (*ptrDebounceCnt)--; + } + + /* No touch */ + if (ptrSnsCxt->diff <= snsTh) + { + /* Reset debounce counter */ + *ptrDebounceCnt = ptrWdCxt->onDebounce; + ptrSnsCxt->status &= (uint8_t)(~snsStMask); + } + + /* New touch or touch still exists */ + if (0u == (*ptrDebounceCnt)) + { + ptrSnsCxt->status |= (uint8_t)snsStMask; + } + + /* Update widget status */ + if (0u != (ptrSnsCxt->status & (uint8_t)snsStMask)) + { + ptrWdCxt->status |= (uint8_t)CY_CAPSENSE_WD_ACTIVE_MASK; + } + + if (0u != (snsIndex & 0x01u)) + { + ptrSnsCxt++; + } + ptrDebounceCnt++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessSlider +****************************************************************************//** +* +* Processes the status of the Linear/Radial Slider widget. +* The process involves running the Linear/Radial centroid algorithm. +* +* It applies the hysteresis and debounce algorithm to the widget ignoring +* the individual states of the sensors. +* +* This function is expected to be called after each new widget scan. If it is +* called multiple times for the same scan data, the debounce algorithm +* will not work properly. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessSlider( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t touchTh; + uint32_t wdActive = 0u; + uint8_t * ptrDebounceCnt = ptrWdConfig->ptrDebounceArr; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + uint32_t sensorNumber = ptrWdConfig->numSns; + cy_stc_capsense_position_t newPosition[CY_CAPSENSE_MAX_CENTROIDS]; + cy_stc_capsense_touch_t newTouch = {&newPosition[0u], CY_CAPSENSE_POSITION_NONE}; + + /* Calculate touch threshold based on current slider state */ + touchTh = (0u == (ptrWdCxt->status & CY_CAPSENSE_WD_ACTIVE_MASK)) ? + ((uint32_t)ptrWdCxt->fingerTh + ptrWdCxt->hysteresis) : + ((uint32_t)ptrWdCxt->fingerTh - ptrWdCxt->hysteresis); + + if (0u < (*ptrDebounceCnt)) + { + /* Decrement debounce counter */ + (*ptrDebounceCnt)--; + } + + /* Check new widget activity */ + for (snsIndex = sensorNumber; snsIndex-- > 0u;) + { + ptrSnsCxt->status = (touchTh < ptrSnsCxt->diff) ? CY_CAPSENSE_SNS_TOUCH_STATUS_MASK : 0u; + wdActive |= ptrSnsCxt->status; + ptrSnsCxt++; + } + + /* No touch detected */ + if (0u == wdActive) + { + /* Reset debounce counter */ + (*ptrDebounceCnt) = ptrWdCxt->onDebounce; + ptrWdCxt->status &= (uint8_t)(~CY_CAPSENSE_WD_ACTIVE_MASK); + } + + if (0u == (*ptrDebounceCnt)) + { + /* New touch detected or touch still exists from previous cycle */ + ptrWdCxt->status |= CY_CAPSENSE_WD_ACTIVE_MASK; + } + else + { + if (0u != wdActive) + { + /* Clear sensor state if activity was detected but debounce was not passed */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + + for (snsIndex = sensorNumber; snsIndex-- > 0u;) + { + ptrSnsCxt->status = 0u; + ptrSnsCxt++; + } + } + } + + /* Centroid processing */ + if (CY_CAPSENSE_WD_ACTIVE_MASK == (ptrWdCxt->status & CY_CAPSENSE_WD_ACTIVE_MASK)) + { + switch (ptrWdConfig->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E: + Cy_CapSense_DpCentroidRadial(&newTouch, ptrWdConfig); + break; + + case (uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E: + if ((0u != (ptrWdConfig->centroidConfig & CY_CAPSENSE_DIPLEXING_MASK))) + { + /* Run local maximum search for diplexed slider */ + Cy_CapSense_DpCentroidDiplex(&newTouch, ptrWdConfig); + } + else + { + Cy_CapSense_DpCentroidLinear(&newTouch, ptrWdConfig); + } + break; + + default: + break; + } + } + + /* Position filtering */ + if (0u != (ptrWdConfig->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_MASK)) + { + Cy_CapSense_ProcessPositionFilters(&newTouch, ptrWdConfig, context); + } + + /* Copy positions into public structure */ + ptrWdConfig->ptrWdContext->wdTouch.numPosition = newTouch.numPosition; + for (snsIndex = 0u; snsIndex < newTouch.numPosition; snsIndex++) + { + ptrWdConfig->ptrWdContext->wdTouch.ptrPosition[snsIndex] = newTouch.ptrPosition[snsIndex]; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsdMatrix +****************************************************************************//** +* +* Processes the status of the CSD Matrix Button widget. +* +* This function processes the status of the CSD Matrix Button widget. +* It applies the hysteresis and debounce algorithm to each sensor value. +* +* Then the function analyzes how many row and column sensors are active. +* If only one per row and one per column, the function considers this as +* a valid touch and updates the corresponding Data Structure registers +* with the button id and active row and column sensors. +* +* If multiple sensors are active in row or column sensors, this function sets +* the corresponding registers to the CY_CAPSENSE_POSITION_MULTIPLE +* value that indicates that it is not possible to detect the touched button id. +* +* This function is expected to be called after each new widget scan. If it is +* called multiple times for the same scan data, the debounce algorithm +* will not work properly. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessCsdMatrix( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t touchTh; + uint32_t colNumber = ptrWdConfig->numCols; + uint8_t * ptrDebounceCnt = ptrWdConfig->ptrDebounceArr; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + cy_stc_capsense_position_t * ptrSnsTouch = ptrWdCxt->wdTouch.ptrPosition; + + uint32_t numActiveRows = 0u; + uint32_t numActiveCols = 0u; + + uint32_t activeRow = 0u; + uint32_t activeCol = 0u; + + /* Reset status */ + ptrWdCxt->status &= (uint8_t)~CY_CAPSENSE_WD_ACTIVE_MASK; + + /* Go through all widget's sensors */ + for (snsIndex = 0u; snsIndex < ptrWdConfig->numSns; snsIndex++) + { + /* Calculate touch threshold based on current sensor state */ + touchTh = (0u == ptrSnsCxt->status) ? + ((uint32_t)ptrWdCxt->fingerTh + ptrWdCxt->hysteresis) : + ((uint32_t)ptrWdCxt->fingerTh - ptrWdCxt->hysteresis); + + if (0u < (*ptrDebounceCnt)) + { + /* Decrement debounce counter */ + (*ptrDebounceCnt)--; + } + + /* No touch */ + if (ptrSnsCxt->diff <= touchTh) + { + /* Reset debounce counter */ + *ptrDebounceCnt = ptrWdCxt->onDebounce; + ptrSnsCxt->status = 0u; + } + + /* New touch or touch still exists */ + if (0u == (*ptrDebounceCnt)) + { + ptrSnsCxt->status = CY_CAPSENSE_SNS_TOUCH_STATUS_MASK; + } + + /* Update information about active row/col sensors */ + if (0u != ptrSnsCxt->status) + { + if (snsIndex < colNumber) + { + numActiveCols++; + activeCol = snsIndex; + } + else + { + numActiveRows++; + activeRow = snsIndex - colNumber; + } + } + + ptrSnsCxt++; + ptrDebounceCnt++; + } + + /* + * Number of touches (numActiveCols * numActiveRows): + * 0 -> No touch + * 1 -> One touch + * 2+ -> Multiple touches + */ + + ptrWdCxt->wdTouch.numPosition = (uint8_t)(numActiveCols * numActiveRows); + if (ptrWdCxt->wdTouch.numPosition > CY_CAPSENSE_POSITION_ONE) + { + ptrWdCxt->wdTouch.numPosition = CY_CAPSENSE_POSITION_MULTIPLE; + } + + if (CY_CAPSENSE_POSITION_ONE == ptrWdCxt->wdTouch.numPosition) + { + ptrSnsTouch->x = (uint16_t)activeCol; + ptrSnsTouch->y = (uint16_t)activeRow; + ptrSnsTouch->z = 0u; + ptrSnsTouch->id = (uint16_t)((activeRow * colNumber) + activeCol); + } + + /* Update widget status if any activity is detected (even non-valid) */ + if ((0u != numActiveRows) || (0u != numActiveCols)) + { + ptrWdCxt->status |= (uint8_t)CY_CAPSENSE_WD_ACTIVE_MASK; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsdTouchpad +****************************************************************************//** +* +* Processes status of the CSD Touchpad widget. This includes running +* Centroid algorithm and updating status in the Data Structure registers. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessCsdTouchpad( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context) +{ + uint32_t snsIndex; + uint32_t touchTh; + uint32_t wdActiveCol = 0uL; + uint32_t wdActiveRow = 0uL; + uint8_t * ptrDebounceCnt = ptrWdConfig->ptrDebounceArr; + cy_stc_capsense_sensor_context_t * ptrSnsCxt = ptrWdConfig->ptrSnsContext; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdConfig->ptrWdContext; + uint32_t sensorNumber = ptrWdConfig->numSns; + uint32_t colNumber = ptrWdConfig->numCols; + uint32_t rowNumber = ptrWdConfig->numRows; + cy_stc_capsense_position_t newPosition[CY_CAPSENSE_MAX_CENTROIDS]; + cy_stc_capsense_touch_t newTouch = {&newPosition[0u], CY_CAPSENSE_POSITION_NONE}; + cy_stc_capsense_ballistic_delta_t delta; + + /* Calculate touch threshold based on current sensor state */ + touchTh = (0u == (ptrWdCxt->status & CY_CAPSENSE_WD_ACTIVE_MASK)) ? + ((uint32_t)ptrWdCxt->fingerTh + ptrWdCxt->hysteresis) : + ((uint32_t)ptrWdCxt->fingerTh - ptrWdCxt->hysteresis); + + if (0u < (*ptrDebounceCnt)) + { + /* Decrement debounce counter */ + (*ptrDebounceCnt)--; + } + + /* Widget is considered as active if at least one sensor is active on both axes */ + for (snsIndex = colNumber; snsIndex-- > 0uL;) + { + ptrSnsCxt->status = (touchTh < ptrSnsCxt->diff) ? CY_CAPSENSE_SNS_TOUCH_STATUS_MASK : 0u; + wdActiveCol |= ptrSnsCxt->status; + ptrSnsCxt++; + } + for (snsIndex = rowNumber; snsIndex-- > 0uL;) + { + ptrSnsCxt->status = (touchTh < ptrSnsCxt->diff) ? CY_CAPSENSE_SNS_TOUCH_STATUS_MASK : 0u; + wdActiveRow |= ptrSnsCxt->status; + ptrSnsCxt++; + } + + /* No touch detected */ + if ((0uL == wdActiveCol) || (0uL == wdActiveRow)) + { + /* Reset debounce counter */ + (*ptrDebounceCnt) = ptrWdCxt->onDebounce; + ptrWdCxt->status &= (uint8_t)(~CY_CAPSENSE_WD_ACTIVE_MASK); + } + if (0u == (*ptrDebounceCnt)) + { + /* New touch detected or touch still exists from previous cycle */ + ptrWdCxt->status |= CY_CAPSENSE_WD_ACTIVE_MASK; + } + else + { + if ((0uL != wdActiveCol) && (0uL != wdActiveRow)) + { + /* Clear sensor state if activity was detected but debounce was not passed */ + ptrSnsCxt = ptrWdConfig->ptrSnsContext; + for (snsIndex = sensorNumber; snsIndex-- > 0uL;) + { + ptrSnsCxt->status = 0u; + ptrSnsCxt++; + } + } + } + + /* If widget is still active after debounce run the centroid algorithm */ + if (CY_CAPSENSE_WD_ACTIVE_MASK == (ptrWdCxt->status & CY_CAPSENSE_WD_ACTIVE_MASK)) + { + /* 3x3 CSD Touchpad processing */ + if (0u != (ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_3X3_MASK)) + { + /* Centroid processing */ + Cy_CapSense_DpCentroidTouchpad(&newTouch, ptrWdConfig); + } + /* 5x5 Advanced CSD Touchpad processing */ + if (0u != (ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_5X5_MASK)) + { + /* Centroid processing */ + Cy_CapSense_DpAdvancedCentroidTouchpad(&newTouch, ptrWdConfig); + } + } + + /* Position filtering */ + if (0u != (ptrWdConfig->posFilterConfig & CY_CAPSENSE_POSITION_FILTERS_MASK)) + { + Cy_CapSense_ProcessPositionFilters(&newTouch, ptrWdConfig, context); + } + + /* Copy positions into public structure */ + ptrWdCxt->wdTouch.numPosition = newTouch.numPosition; + if (CY_CAPSENSE_POSITION_MULTIPLE != ptrWdCxt->wdTouch.numPosition) + { + for (snsIndex = 0u; snsIndex < newTouch.numPosition; snsIndex++) + { + ptrWdCxt->wdTouch.ptrPosition[snsIndex] = newTouch.ptrPosition[snsIndex]; + } + } + + /* Ballistic Multiplier Filtering */ + if (0u != (ptrWdConfig->centroidConfig & CY_CAPSENSE_CENTROID_BALLISTIC_MASK)) + { + Cy_CapSense_BallisticMultiplier_Lib( + &ptrWdConfig->ballisticConfig, + &ptrWdCxt->wdTouch, + &delta, + context->ptrCommonContext->timestamp, + ptrWdConfig->ptrBallisticContext); + ptrWdCxt->xDelta = delta.deltaX; + ptrWdCxt->yDelta = delta.deltaY; + } + +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DpProcessCsxTouchpad +****************************************************************************//** +* +* Processes the status of the CSX Touchpad widget. +* The process involves running the 3x3 centroid algorithm with the +* tracking of finger id. +* +* \param ptrWdConfig +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DpProcessCsxTouchpad( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_context_t * context) +{ + (void)context; + /* Check whether sensors are active and located all local maxima */ + Cy_CapSense_DpFindLocalMaxDd(ptrWdConfig); + /* Calculate centroid position for all found local maxima */ + Cy_CapSense_DpCalcTouchPadCentroid(ptrWdConfig); + /* Identify all touches and assign them correct ID based on historical data */ + Cy_CapSense_DpTouchTracking(ptrWdConfig); + /* Filter the position data and write it into data structure */ + Cy_CapSense_DpFilterTouchRecord(ptrWdConfig); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunMfsFiltering +****************************************************************************//** +* +* Selects the median difference signal when the multi-frequency scan is enabled. +* +* \param ptrSnsContext +* The pointer to the widget configuration structure. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_RunMfsFiltering( + cy_stc_capsense_sensor_context_t * ptrSnsContext, + const cy_stc_capsense_context_t * context) +{ + ptrSnsContext->diff = (uint16_t)Cy_CapSense_FtMedian((uint32_t)ptrSnsContext->diff, + (uint32_t)ptrSnsContext[CY_CAPSENSE_MFS_CH1_INDEX * context->ptrCommonConfig->numSns].diff, + (uint32_t)ptrSnsContext[CY_CAPSENSE_MFS_CH2_INDEX * context->ptrCommonConfig->numSns].diff); +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_processing.h b/cy_capsense_processing.h new file mode 100644 index 0000000..980da4c --- /dev/null +++ b/cy_capsense_processing.h @@ -0,0 +1,139 @@ +/***************************************************************************//** +* \file cy_capsense_processing.h +* \version 1.1 +* +* \brief +* This file provides the function prototypes for the Data Processing module. +* The Data Processing module is responsible for the low level raw counts +* processing provided by the sensing module, maintaining baseline and +* difference values and performing high-level widget processing like updating +* button status or calculating slider position. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_PROCESSING_H) +#define CY_CAPSENSE_PROCESSING_H + +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_lib.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_high_level *//** \{ */ +/******************************************************************************/ +uint32_t Cy_CapSense_DecodeWidgetGestures( + uint32_t widgetId, + const cy_stc_capsense_context_t * context); +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level *//** \{ */ +/******************************************************************************/ +void Cy_CapSense_InitializeWidgetGestures( + uint32_t widgetId, + const cy_stc_capsense_context_t * context); +void Cy_CapSense_InitializeAllStatuses(const cy_stc_capsense_context_t * context); +void Cy_CapSense_InitializeWidgetStatus( + uint32_t widgetId, + const cy_stc_capsense_context_t * context); +/** \} */ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ +void Cy_CapSense_DpProcessButton( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpProcessCsxTouchpad( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpProcessProximity( + cy_stc_capsense_widget_config_t const * ptrWdConfig); + +void Cy_CapSense_DpProcessCsdTouchpad( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpProcessSlider( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); +void Cy_CapSense_DpProcessCsdMatrix( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpProcessCsdWidgetStatus( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +uint32_t Cy_CapSense_DpProcessCsdWidgetRawCounts( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_context_t * context); + +uint32_t Cy_CapSense_DpProcessCsdSensorRawCountsExt( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow, + uint32_t mode, + const cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpProcessCsdWidgetStatus( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpProcessCsxWidgetStatus( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_context_t * context); + +uint32_t Cy_CapSense_DpProcessCsxWidgetRawCounts( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + const cy_stc_capsense_context_t * context); + +uint32_t Cy_CapSense_DpProcessCsxSensorRawCountsExt( + const cy_stc_capsense_widget_config_t * ptrWdConfig, + cy_stc_capsense_sensor_context_t * ptrSnsContext, + uint16_t * ptrSnsRawHistory, + uint8_t * ptrSnsRawHistoryLow, + uint32_t mode, + const cy_stc_capsense_context_t * context); + +void Cy_CapSense_DpUpdateDifferences( + const cy_stc_capsense_widget_context_t * ptrWdContext, + cy_stc_capsense_sensor_context_t * ptrSnsContext); + +void Cy_CapSense_DpUpdateThresholds( + cy_stc_capsense_widget_context_t * ptrWdContext, + const cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNoiseEnvelope, + uint32_t startFlag); + +void Cy_CapSense_RunMfsFiltering( + cy_stc_capsense_sensor_context_t * ptrSnsContext, + const cy_stc_capsense_context_t * context); + +/** \} \endcond */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_PROCESSING_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_sensing.c b/cy_capsense_sensing.c new file mode 100644 index 0000000..7b8c830 --- /dev/null +++ b/cy_capsense_sensing.c @@ -0,0 +1,2600 @@ +/***************************************************************************//** +* \file cy_capsense_sensing.c +* \version 1.1 +* +* \brief +* This file contains the source of functions common for different sensing +* methods. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include +#include "cy_gpio.h" +#include "cy_sysclk.h" +#include "cy_csd.h" + +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_sensing.h" +#include "cy_capsense_csx.h" +#include "cy_capsense_csd.h" +#include "cy_capsense_lib.h" + + +/******************************************************************************* +* Constants +*******************************************************************************/ +#define CY_CAPSENSE_AUTOTUNE_CALIBRATION_RESOLUTION (12u) +#define CY_CAPSENSE_AUTOTUNE_CALIBRATION_FREQ_KHZ (1500u) +#define CY_CAPSENSE_CSD_SNS_FREQ_KHZ_MAX (6000u) +#define CY_CAPSENSE_CSD_AUTOTUNE_CAL_UNITS (1000u) +#define CY_CAPSENSE_AUTOTUNE_CP_MAX (69000Lu) + +#define CY_CAPSENSE_EXT_CAP_DISCHARGE_TIME (1u) + +#define CY_CAPSENSE_VREF_GAIN_MAX (32u) +#define CY_CAPSENSE_VREF_VDDA_MIN_DIFF (600u) +#define CY_CAPSENSE_VREF_SRSS_MV (800u) +#define CY_CAPSENSE_VREF_PASS_MV (1200u) + + + +const cy_stc_csd_config_t cy_capsense_csdCfg = CY_CAPSENSE_CSD_CONFIG_DEFAULT; + + +/******************************************************************************* +* Function Name: Cy_CapSense_IsBusy +****************************************************************************//** +* +* This function returns a status of the CapSense middleware whether a scan is +* currently in progress or not. +* +* If the middleware is busy, a new scan or setup widgets should not be initiated. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the middleware: +* - CY_CAPSENSE_NOT_BUSY - No scan is in progress and a next scan +* can be initiated. +* - CY_CAPSENSE_SW_STS_BUSY - The previously initiated scan is in progress. +* +*******************************************************************************/ +uint32_t Cy_CapSense_IsBusy(const cy_stc_capsense_context_t * context) +{ + return (context->ptrCommonContext->status & CY_CAPSENSE_SW_STS_BUSY); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetBusyFlags +****************************************************************************//** +* +* Sets BUSY flags of the cy_capsense_context.status register specified +* by the flags parameter. +* +* \details +* This is an internal function. Do not call this function directly from +* the application program. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SetBusyFlags(cy_stc_capsense_context_t * context) +{ + context->ptrCommonContext->status |= CY_CAPSENSE_SW_STS_BUSY; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ClrBusyFlags +****************************************************************************//** +* +* Clears BUSY flags of the cy_capsense_context.status register specified +* by the flags parameter. +* +* This is an internal function. Do not call this function directly from +* the application program. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_ClrBusyFlags(cy_stc_capsense_context_t * context) +{ + /* Clear busy flag */ + context->ptrCommonContext->status &= (uint32_t)(~((uint32_t)CY_CAPSENSE_SW_STS_BUSY)); + + /* Reset scan flags */ + context->ptrActiveScanSns->scanScopeAll = CY_CAPSENSE_SCAN_SCOPE_SGL_WD; + context->ptrActiveScanSns->scanScopeSns = CY_CAPSENSE_SCAN_SCOPE_UND; + + /* Mark completion of scan cycle */ + context->ptrCommonContext->scanCounter++; + + if(NULL != context->ptrCommonContext->ptrEOSCallback) + { + context->ptrCommonContext->ptrEOSCallback(context->ptrActiveScanSns); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetupWidget +****************************************************************************//** +* +* Performs the initialization required to scan the specified widget. +* +* This function prepares the middleware to scan all the sensors in the specified +* widget by executing the following tasks: +* 1. Configure the CSD HW block if it is not configured to perform the +* sensing method used by the specified widget. This happens only if the +* CSD and CSX methods are used in a user's project. +* 2. Initialize the CSD HW block with specific sensing configuration (e.g. +* sensor clock, scan resolution) used by the widget. +* 3. Disconnect all previously connected electrodes, if the electrodes are +* connected by the Cy_CapSense_CSDSetupWidgetExt(), +* Cy_CapSense_CSXSetupWidgetExt(), or Cy_CapSense_CSDConnectSns() +* functions and are not disconnected. +* +* This function does not start sensor scanning. The Cy_CapSense_Scan() +* function must be called to start the scan sensors in the widget. If this +* function is called more than once, it does not break the middleware operation, +* but only the last initialized widget is in effect. +* +* The status of a sensor scan must be checked using the Cy_CapSense_IsBusy() +* function prior to starting a next scan or setting up another widget. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the widget setting up operation: +* - CY_RET_SUCCESS - The operation is successfully completed. +* - CY_RET_BAD_PARAM - The widget is invalid or if the specified widget is +* disabled. +* - CY_RET_INVALID_STATE - The previous scanning is not completed and +* the CSD HW block is busy. +* - CY_RET_UNKNOWN - An unknown sensing method is used by the widget or +* any other spurious error occurred. +* +**********************************************************************************/ +cy_status Cy_CapSense_SetupWidget( + uint32_t widgetId, + cy_stc_capsense_context_t * context) +{ + cy_status widgetStatus; + + if (CY_CAPSENSE_SW_STS_BUSY == Cy_CapSense_IsBusy(context)) + { + /* Previous widget is being scanned. Return error. */ + widgetStatus = CY_RET_INVALID_STATE; + } + /* + * Check whether widget id is valid, specified widget is enabled and widget did not + * detect any fault conditions. If all conditions are met, + * set widgetStatus as good, if not, set widgetStatus as bad. + */ + else if ((context->ptrCommonConfig->numWd > widgetId) && + (0u == (context->ptrWdConfig[widgetId].ptrWdContext->status & CY_CAPSENSE_WD_DISABLE_MASK))) + { + /* Check widget sensing method and call corresponding setup function */ + switch(context->ptrWdConfig[widgetId].senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDSetupWidget(widgetId, context); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXSetupWidget(widgetId, context); + break; + + default: + widgetStatus = CY_RET_UNKNOWN; + break; + } + widgetStatus = CY_RET_SUCCESS; + } + else + { + widgetStatus = CY_RET_BAD_PARAM; + } + + return (widgetStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_Scan +****************************************************************************//** +* +* Initiates scanning of all the sensors in the widget initialized by +* Cy_CapSense_SetupWidget(), if no scan is in progress. +* +* Prior to calling this function to scan sensors, the widget required +* to be scanned must be initialized using Cy_CapSense_SetupWidget() function. +* +* This function initiates scan only for the first sensor in the widget and then +* exits the function. The scan for the remaining sensors in the widget is +* initiated in the interrupt service routine (part of middleware) trigged +* at the end of each scan completion. Hence, status of the current scan +* should be checked using the Cy_CapSense_IsBusy() and wait until all scans +* in the current widget are finished prior to starting the next scan or +* initializing another widget. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the scan initiation operation: +* - CY_RET_SUCCESS - Scanning is successfully started. +* - CY_RET_INVALID_STATE - The previous scan is not completed and +* the CSD HW block is busy. +* - CY_RET_UNKNOWN - An unknown sensing method is used by the widget. +* +********************************************************************************/ +cy_status Cy_CapSense_Scan(cy_stc_capsense_context_t * context) +{ + cy_status scanStatus = CY_RET_SUCCESS; + + if (CY_CAPSENSE_SW_STS_BUSY == Cy_CapSense_IsBusy(context)) + { + /* Previous widget is being scanned. Return error. */ + scanStatus = CY_RET_INVALID_STATE; + } + else + { + /* Check widget sensing method and call appropriate functions */ + switch(context->ptrActiveScanSns->ptrWdConfig->senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDScan(context); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXScan(context); + break; + + default: + scanStatus = CY_RET_UNKNOWN; + break; + } + } + return (scanStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetupWidgetExt +****************************************************************************//** +* +* Performs extended initialization for the specified widget and also performs +* initialization required for a specific sensor in the widget. +* +* This function requires using the Cy_CapSense_ScanExt() function to +* initiate a scan. +* +* This function does the same as Cy_CapSense_SetupWidget() and also +* does the following tasks: +* 1. Connects the specified sensor of the widget. +* 2. Configures the CSD HW block to perform a scan of the specified sensor. +* +* Once this function is called to initialize a widget and a sensor, the +* Cy_CapSense_ScanExt() function is called to scan the sensor. +* +* This function is called when no scanning is in progress. I.e. +* Cy_CapSense_IsBusy() returns a non-busy status. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for faster execution time or pipeline scanning, for example). +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +**********************************************************************************/ +cy_status Cy_CapSense_SetupWidgetExt( + uint32_t widgetId, + uint32_t sensorId, + cy_stc_capsense_context_t * context) +{ + cy_status widgetStatus = CY_RET_BAD_PARAM; + + if (CY_CAPSENSE_SW_STS_BUSY == Cy_CapSense_IsBusy(context)) + { + /* Previous widget is being scanned. Return error. */ + widgetStatus = CY_RET_INVALID_STATE; + } + /* + * Check whether widget id is valid, specified widget is enabled and widget did not + * detect any fault conditions. If all conditions are met, + * set widgetStatus as good, if not, set widgetStatus as bad. + */ + else if (context->ptrCommonConfig->numWd > widgetId) + { + if (context->ptrWdConfig[widgetId].numSns > sensorId) + { + /* Check widget sensing method and call corresponding setup function */ + switch(context->ptrWdConfig[widgetId].senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDSetupWidgetExt(widgetId, sensorId, context); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXSetupWidgetExt(widgetId, sensorId, context); + break; + + default: + widgetStatus = CY_RET_UNKNOWN; + break; + } + widgetStatus = CY_RET_SUCCESS; + } + } + else + { + /* Do nothing */ + } + + return (widgetStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ScanExt +****************************************************************************//** +* +* Starts a conversion on the pre-configured sensor. This function requires +* using the Cy_CapSense_SetupWidgetExt() function to set up the a +* widget. +* +* This function performs single scanning of one sensor in the widget configured +* by the Cy_CapSense_SetupWidgetExt() function. +* +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the user's specific +* use cases (for faster execution time or pipeline scanning, for example). +* This function is called when no scanning is in progress. I.e. +* Cy_CapSense_IsBusy() returns a non-busy status. +* +* The sensor must be pre-configured by using the +* Cy_CapSense_SetupWidgetExt() prior to calling this function. +* The sensor remains ready for the next scan if a previous scan was triggered +* by using the Cy_CapSense_ScanExt() function. In this case, calling +* Cy_CapSense_SetupWidgetExt() is not required every time before the +* Cy_CapSense_ScanExt() function. If a previous scan was triggered in +* any other way - Cy_CapSense_Scan(), Cy_CapSense_ScanAllWidgets(), or +* Cy_CapSense_RunTuner() - (see the Cy_CapSense_RunTuner() function +* description for more details), the sensor must be pre-configured again by +* using the Cy_CapSense_SetupWidgetExt() prior to calling the +* Cy_CapSense_ScanExt() function. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +cy_status Cy_CapSense_ScanExt(cy_stc_capsense_context_t * context) +{ + cy_status scanStatus = CY_RET_SUCCESS; + + if (CY_CAPSENSE_SW_STS_BUSY == Cy_CapSense_IsBusy(context)) + { + /* Previous widget is being scanned. Return error. */ + scanStatus = CY_RET_INVALID_STATE; + } + else + { + /* Check widget sensing method and call appropriate functions */ + switch(context->ptrActiveScanSns->ptrWdConfig->senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDScan(context); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXScan(context); + break; + + default: + scanStatus = CY_RET_UNKNOWN; + break; + } + } + return (scanStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_ScanAllWidgets +****************************************************************************//** +* +* Initiates scanning of all enabled widgets (and sensors) in the project. +* +* The tasks of both Cy_CapSense_SetupWidget() and Cy_CapSense_Scan() functions +* are executed by this function. The status of a sensor scan must be checked +* using the Cy_CapSense_IsBusy() prior to starting the next scan or setting +* up another widget. +* +* This function initiates a scan only for the first sensor in the first widget +* and then exits the function. The scan for the remaining sensors are initiated +* in the interrupt service routine (part of middleware) trigged at the end +* of each scan completion. Hence, the status of the current scan should be +* checked using the Cy_CapSense_IsBusy() and wait until all scans is finished +* prior to starting a next scan or initializing another widget. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the operation: +* - CY_RET_SUCCESS - Scanning is successfully started. +* - CY_RET_BAD_PARAM - All the widgets are disabled. +* - CY_RET_INVALID_STATE - The previous scanning is not completed and the +* CSD HW block is busy. +* - CY_RET_UNKNOWN - There are unknown errors. +* +*******************************************************************************/ +cy_status Cy_CapSense_ScanAllWidgets(cy_stc_capsense_context_t * context) +{ + uint32_t wdgtIndex; + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + cy_status scanStatus = CY_RET_UNKNOWN; + + if (CY_CAPSENSE_SW_STS_BUSY == Cy_CapSense_IsBusy(context)) + { + /* Previous widget is being scanned. Return error. */ + scanStatus = CY_RET_INVALID_STATE; + } + else + { + /* + * Set up first widget. If widget returned error, + * set up next, continue same until widget does not return error. + */ + for (wdgtIndex = 0u; wdgtIndex < context->ptrCommonConfig->numWd; wdgtIndex++) + { + scanStatus = Cy_CapSense_SetupWidget(wdgtIndex, context); + if (CY_RET_SUCCESS == scanStatus) + { + ptrActive->scanScopeAll = CY_CAPSENSE_SCAN_SCOPE_ALL_WD; + + /* Initiate scan and quit loop */ + scanStatus = Cy_CapSense_Scan(context); + + break; + } + } + } + + return (scanStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InternalPreCalculation +****************************************************************************//** +* +* Calculate different internal parameters, register values in advance to +* speed up execution time. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return status +* Returns status of operation: +* - Zero - Indicates successful initialization. +* - Non-zero - One or more errors occurred in the initialization process. +* +*******************************************************************************/ +cy_status Cy_CapSense_InternalPreCalculation(cy_stc_capsense_context_t * context) +{ + cy_status initStatus = CY_RET_SUCCESS; + uint32_t wdgtIndex; + uint32_t temp; + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdEn) + { + if ((context->ptrCommonConfig->portCmodPadNum == context->ptrCommonConfig->portCmodNum) && + (context->ptrCommonConfig->pinCmodPad == context->ptrCommonConfig->pinCmod)) + { + context->ptrInternalContext->csdCmodConnection = (uint8_t)CY_CAPSENSE_CMODPAD_E; + } + else if ((context->ptrCommonConfig->portCshPadNum == context->ptrCommonConfig->portCmodNum) && + (context->ptrCommonConfig->pinCshPad == context->ptrCommonConfig->pinCmod)) + { + context->ptrInternalContext->csdCmodConnection = (uint8_t)CY_CAPSENSE_CTANKPAD_E; + } + else if ((context->ptrCommonConfig->portShieldPadNum == context->ptrCommonConfig->portCmodNum) && + (context->ptrCommonConfig->pinShieldPad == context->ptrCommonConfig->pinCmod)) + { + context->ptrInternalContext->csdCmodConnection = (uint8_t)CY_CAPSENSE_CSHIELDPAD_E; + } + else if ((context->ptrCommonConfig->portVrefExtPadNum == context->ptrCommonConfig->portCmodNum) && + (context->ptrCommonConfig->pinVrefExtPad == context->ptrCommonConfig->pinCmod)) + { + context->ptrInternalContext->csdCmodConnection = (uint8_t)CY_CAPSENSE_VREFEXTPAD_E; + } + else + { + context->ptrInternalContext->csdCmodConnection = (uint8_t)CY_CAPSENSE_CMODPAD_E; + initStatus = CY_RET_BAD_PARAM; + } + + if(CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdCTankShieldEn) + { + /* Csh Capacitor Placement */ + if ((context->ptrCommonConfig->portCmodPadNum == context->ptrCommonConfig->portCshNum) && + (context->ptrCommonConfig->pinCmodPad == context->ptrCommonConfig->pinCsh)) + { + context->ptrInternalContext->csdCshConnection = (uint8_t)CY_CAPSENSE_CMODPAD_E; + } + else if ((context->ptrCommonConfig->portCshPadNum == context->ptrCommonConfig->portCshNum) && + (context->ptrCommonConfig->pinCshPad == context->ptrCommonConfig->pinCsh)) + { + context->ptrInternalContext->csdCshConnection = (uint8_t)CY_CAPSENSE_CTANKPAD_E; + } + else if ((context->ptrCommonConfig->portShieldPadNum == context->ptrCommonConfig->portCshNum) && + (context->ptrCommonConfig->pinShieldPad == context->ptrCommonConfig->pinCsh)) + { + context->ptrInternalContext->csdCshConnection = (uint8_t)CY_CAPSENSE_CSHIELDPAD_E; + } + else if ((context->ptrCommonConfig->portVrefExtPadNum == context->ptrCommonConfig->portCshNum) && + (context->ptrCommonConfig->pinVrefExtPad == context->ptrCommonConfig->pinCsh)) + { + context->ptrInternalContext->csdCshConnection = (uint8_t)CY_CAPSENSE_VREFEXTPAD_E; + } + else + { + context->ptrInternalContext->csdCshConnection = (uint8_t)CY_CAPSENSE_CTANKPAD_E; + initStatus = CY_RET_BAD_PARAM; + } + } + + /* Switch CSD Comparator Selection */ + switch (context->ptrInternalContext->csdCmodConnection) + { + case (uint8_t)CY_CAPSENSE_CMODPAD_E: + context->ptrInternalContext->csdRegSwCmpPSel = CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPM_STATIC_CLOSE; + break; + case (uint8_t)CY_CAPSENSE_CSHIELDPAD_E: + context->ptrInternalContext->csdRegSwCmpPSel = CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPS_STATIC_CLOSE; + break; + default: + context->ptrInternalContext->csdRegSwCmpPSel = CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPT_STATIC_CLOSE; + break; + } + + /* Defines the drive mode of pins depending on the Inactive sensor connection setting */ + switch (context->ptrCommonConfig->csdInactiveSnsConnection) + { + case CY_CAPSENSE_SNS_CONNECTION_HIGHZ: + context->ptrInternalContext->csdInactiveSnsDm = CY_GPIO_DM_ANALOG; + context->ptrInternalContext->csdInactiveSnsHsiom = CY_CAPSENSE_HSIOM_SEL_GPIO; + break; + case CY_CAPSENSE_SNS_CONNECTION_SHIELD: + context->ptrInternalContext->csdInactiveSnsDm = CY_GPIO_DM_STRONG_IN_OFF; + context->ptrInternalContext->csdInactiveSnsHsiom = CY_CAPSENSE_HSIOM_SEL_CSD_SHIELD; + break; + case CY_CAPSENSE_SNS_CONNECTION_GROUND: + default: + context->ptrInternalContext->csdInactiveSnsDm = CY_GPIO_DM_STRONG; + context->ptrInternalContext->csdInactiveSnsHsiom = CY_CAPSENSE_HSIOM_SEL_GPIO; + break; + } + + /* Prepares CONFIG register value */ + context->ptrInternalContext->csdRegConfig = 0u; + /* Iref Source */ + if (CY_CAPSENSE_IREF_PASS == context->ptrCommonConfig->ssIrefSource) + { + context->ptrInternalContext->csdRegConfig |= CSD_CONFIG_IREF_SEL_Msk; + } + /* Filter Delay */ + temp = context->ptrCommonConfig->periClkHz / context->ptrCommonContext->modCsdClk; + if (temp > CY_CAPSENSE_MOD_CSD_CLK_24000000_HZ) + { + context->ptrInternalContext->csdRegConfig |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_48MHZ; + } + else if (temp > CY_CAPSENSE_MOD_CSD_CLK_12000000_HZ) + { + context->ptrInternalContext->csdRegConfig |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_24MHZ; + } + else + { + context->ptrInternalContext->csdRegConfig |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_12MHZ; + } + /* Shield Delay */ + context->ptrInternalContext->csdRegConfig |= (((uint32_t)context->ptrCommonConfig->csdShieldDelay) << CY_CAPSENSE_CSD_CONFIG_SHIELD_DELAY_POS); + /* Sense Enable */ + context->ptrInternalContext->csdRegConfig |= CSD_CONFIG_SENSE_EN_Msk; + /* Power On */ + context->ptrInternalContext->csdRegConfig |= CSD_CONFIG_ENABLE_Msk; + + /* High Speed comparator positive input selection */ + context->ptrInternalContext->csdRegSwHsPSelScan = 0u; + context->ptrInternalContext->csdRegSwHsPSelInit = 0u; + /* Switch Comparator Selection */ + switch (context->ptrInternalContext->csdCmodConnection) + { + case (uint8_t)CY_CAPSENSE_CMODPAD_E: + context->ptrInternalContext->csdRegSwHsPSelInit = CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPM_STATIC_CLOSE; + break; + case (uint8_t)CY_CAPSENSE_CSHIELDPAD_E: + context->ptrInternalContext->csdRegSwHsPSelInit = CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPS_STATIC_CLOSE; + break; + default: + context->ptrInternalContext->csdRegSwHsPSelInit = CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPT_STATIC_CLOSE; + break; + } + if (0u != context->ptrCommonConfig->csdShieldEn) + { + context->ptrInternalContext->csdRegSwHsPSelScan = CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMMB_STATIC_CLOSE; + } + + /* BYP switch selection */ + context->ptrInternalContext->csdRegSwBypSel = CY_CAPSENSE_CSD_SW_BYP_SEL_SW_BYA_MSK; + if (0u != context->ptrCommonConfig->csdShieldEn) + { + context->ptrInternalContext->csdRegSwBypSel = CY_CAPSENSE_CSD_SW_BYP_SEL_SW_BYA_MSK | CY_CAPSENSE_CSD_SW_BYP_SEL_SW_BYB_MSK; + } + + /* Switch resistance selection */ + context->ptrInternalContext->csdRegSwResScan = ((uint32_t)context->ptrCommonConfig->csdShieldSwRes << CSD_SW_RES_RES_HCBV_Pos) | + ((uint32_t)context->ptrCommonConfig->csdShieldSwRes << CSD_SW_RES_RES_HCBG_Pos); + /* Switch resistance selection */ + context->ptrInternalContext->csdRegSwResInit = ((uint32_t)context->ptrCommonConfig->csdInitSwRes << CSD_SW_RES_RES_HCAV_Pos); + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdShieldEn) + { + if (CY_CAPSENSE_2000_MV > context->ptrCommonConfig->vdda) + { + + context->ptrInternalContext->csdRegAmuxbufInit = CY_CAPSENSE_CSD_AMBUF_PWR_MODE_NORM; + } + else + { + context->ptrInternalContext->csdRegAmuxbufInit = CY_CAPSENSE_CSD_AMBUF_PWR_MODE_HI; + } + } + else + { + context->ptrInternalContext->csdRegAmuxbufInit = CY_CAPSENSE_CSD_AMBUF_PWR_MODE_OFF; + } + + /* Switch AMUXBUF selection */ + context->ptrInternalContext->csdRegSwAmuxbufSel = 0u; + if (0u != context->ptrCommonConfig->csdShieldEn) + { + if (((CY_CAPSENSE_2000_MV > context->ptrCommonConfig->vdda) && + (CY_CAPSENSE_IDAC_SINKING == context->ptrCommonConfig->csdChargeTransfer)) || + ((CY_CAPSENSE_2000_MV <= context->ptrCommonConfig->vdda) && + (CY_CAPSENSE_IDAC_SOURCING == context->ptrCommonConfig->csdChargeTransfer))) + { + context->ptrInternalContext->csdRegSwAmuxbufSel = CY_CAPSENSE_CSD_SW_AMUXBUF_SEL_SW_IRH_STATIC_CLOSE | CY_CAPSENSE_CSD_SW_AMUXBUF_SEL_SW_ICB_PHI2; + } + } + /* Switch Shield selection */ + context->ptrInternalContext->csdRegSwShieldSelInit = CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_HSCMP; + context->ptrInternalContext->csdRegSwShieldSelScan = 0u; + if (0u != context->ptrCommonConfig->csdShieldEn) + { + if (0u != context->ptrCommonConfig->csdCTankShieldEn) + { + if (CY_CAPSENSE_IDAC_SINKING == context->ptrCommonConfig->csdChargeTransfer) + { + context->ptrInternalContext->csdRegSwShieldSelScan = CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_HSCMP; + } + else + { + context->ptrInternalContext->csdRegSwShieldSelScan = CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_HSCMP; + } + } + else + { + if (CY_CAPSENSE_IDAC_SINKING == context->ptrCommonConfig->csdChargeTransfer) + { + context->ptrInternalContext->csdRegSwShieldSelScan = CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_PHI1 | + CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_PHI2_HSCMP; + } + else + { + context->ptrInternalContext->csdRegSwShieldSelScan = CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_PHI1 | + CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_PHI2_HSCMP; + } + } + } + + /* High-Speed Comparator config */ + context->ptrInternalContext->csdRegHscmpInit = CY_CAPSENSE_CSD_HSCMP_HSCMP_EN_MSK; + + if (CY_CAPSENSE_IDAC_SINKING == context->ptrCommonConfig->csdChargeTransfer) + { + context->ptrInternalContext->csdRegHscmpScan = CY_CAPSENSE_CSD_HSCMP_HSCMP_EN_MSK | + CY_CAPSENSE_CSD_HSCMP_HSCMP_INVERT_MSK; + } + else + { + context->ptrInternalContext->csdRegHscmpScan = CY_CAPSENSE_CSD_HSCMP_HSCMP_EN_MSK; + } + + + /* IDACs Config */ + context->ptrInternalContext->csdIdacAConfig = 0u; + context->ptrInternalContext->csdIdacBConfig = 0u; + + /* IDACs Ranges */ + temp = context->ptrCommonConfig->csdIdacGainInit; + /* Initialize idacGain parameters only for CSD widgets */ + for (wdgtIndex = context->ptrCommonConfig->numWd; wdgtIndex-- > 0u;) + { + if ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == context->ptrWdConfig[wdgtIndex].senseMethod) + { + context->ptrWdContext[wdgtIndex].idacGainIndex = (uint8_t)temp; + } + } + context->ptrInternalContext->csdIdacAConfig |= context->ptrCommonConfig->idacGainTable[temp].gainReg; + context->ptrInternalContext->csdIdacBConfig |= context->ptrCommonConfig->idacGainTable[temp].gainReg; + + /* IDACs Polarities */ + if (CY_CAPSENSE_IDAC_SINKING == context->ptrCommonConfig->csdChargeTransfer) + { + context->ptrInternalContext->csdIdacAConfig |= (CY_CAPSENSE_CSD_IDACA_POLARITY_VDDA_SNK << CY_CAPSENSE_CSD_IDACA_POLARITY_POS); + context->ptrInternalContext->csdIdacBConfig |= (CY_CAPSENSE_CSD_IDACB_POLARITY_VDDA_SNK << CY_CAPSENSE_CSD_IDACB_POLARITY_POS); + } + else + { + context->ptrInternalContext->csdIdacAConfig |= (CY_CAPSENSE_CSD_IDACA_POLARITY_VSSA_SRC << CY_CAPSENSE_CSD_IDACA_POLARITY_POS); + context->ptrInternalContext->csdIdacBConfig |= (CY_CAPSENSE_CSD_IDACB_POLARITY_VSSA_SRC << CY_CAPSENSE_CSD_IDACB_POLARITY_POS); + } + /* IDACs Balancing Mode */ + context->ptrInternalContext->csdIdacAConfig |= (CY_CAPSENSE_CSD_IDACA_BALL_MODE_FULL << CY_CAPSENSE_CSD_IDACA_BALL_MODE_POS); + context->ptrInternalContext->csdIdacBConfig |= (CY_CAPSENSE_CSD_IDACB_BALL_MODE_FULL << CY_CAPSENSE_CSD_IDACB_BALL_MODE_POS); + /* Legs Config */ + context->ptrInternalContext->csdIdacAConfig |= (CY_CAPSENSE_CSD_IDACA_LEG1_MODE_CSD << CY_CAPSENSE_CSD_IDACA_LEG1_MODE_POS); + context->ptrInternalContext->csdIdacAConfig |= (CY_CAPSENSE_CSD_IDACA_LEG2_MODE_CSD << CY_CAPSENSE_CSD_IDACA_LEG2_MODE_POS); + context->ptrInternalContext->csdIdacAConfig |= (CY_CAPSENSE_CSD_IDACA_LEG1_EN_MSK); + + context->ptrInternalContext->csdIdacBConfig |= (CY_CAPSENSE_CSD_IDACB_LEG1_MODE_CSD_STATIC << CY_CAPSENSE_CSD_IDACB_LEG1_MODE_POS); + context->ptrInternalContext->csdIdacBConfig |= (CY_CAPSENSE_CSD_IDACB_LEG2_MODE_CSD_STATIC << CY_CAPSENSE_CSD_IDACB_LEG2_MODE_POS); + if (0u != context->ptrCommonConfig->csdIdacCompEn) + { + context->ptrInternalContext->csdIdacBConfig |= (CY_CAPSENSE_CSD_IDACB_LEG1_EN_MSK); + } + + /* Switch Csh tank selection */ + context->ptrInternalContext->csdRegSwFwTankSelScan = 0u; + context->ptrInternalContext->csdRegSwFwTankSelInit = 0u; + if ((0u != context->ptrCommonConfig->csdShieldEn) && + (0u != context->ptrCommonConfig->csdCTankShieldEn) && + ((uint8_t)CY_CAPSENSE_CTANKPAD_E == context->ptrInternalContext->csdCshConnection)) + { + context->ptrInternalContext->csdRegSwFwTankSelScan = (CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2PT_STATIC_CLOSE | + CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CB_STATIC_CLOSE); + } + + if (((uint8_t)CY_CAPSENSE_CTANKPAD_E == context->ptrInternalContext->csdCmodConnection) || + ((uint8_t)CY_CAPSENSE_CTANKPAD_E == context->ptrInternalContext->csdCshConnection)) + { + context->ptrInternalContext->csdRegSwFwTankSelInit = (CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2PT_STATIC_CLOSE | + CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2MA_STATIC_CLOSE | + CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CA_STATIC_CLOSE); + } + + /* IO Control Selection */ + if (CY_CAPSENSE_IDAC_SINKING == context->ptrCommonConfig->csdChargeTransfer) + { + if (0u != context->ptrCommonConfig->csdShieldEn) + { + context->ptrInternalContext->csdRegIoSel = (CY_CAPSENSE_CSD_TX_N_OUT_EN_PHI1 | + CY_CAPSENSE_CSD_TX_N_AMUXA_EN_PHI2 | + CY_CAPSENSE_CSD_TX_OUT_EN_PHI1_DELAY | + CY_CAPSENSE_CSD_TX_AMUXB_EN_PHI2_DELAY | + CY_CAPSENSE_CSD_TX_OUT_MSK | + CY_CAPSENSE_CSD_TX_N_OUT_STATIC_CLOSE); + } + else + { + context->ptrInternalContext->csdRegIoSel = (CY_CAPSENSE_CSD_TX_N_OUT_EN_PHI1 | + CY_CAPSENSE_CSD_TX_N_AMUXA_EN_PHI2 | + CY_CAPSENSE_CSD_TX_N_OUT_STATIC_CLOSE); + } + } + else + { + if (0u != context->ptrCommonConfig->csdShieldEn) + { + context->ptrInternalContext->csdRegIoSel = (CY_CAPSENSE_CSD_TX_N_OUT_EN_PHI1 | + CY_CAPSENSE_CSD_TX_N_AMUXA_EN_PHI2 | + CY_CAPSENSE_CSD_TX_OUT_EN_PHI1_DELAY | + CY_CAPSENSE_CSD_TX_AMUXB_EN_PHI2_DELAY); + } + else + { + context->ptrInternalContext->csdRegIoSel = (CY_CAPSENSE_CSD_TX_N_OUT_EN_PHI1 | + CY_CAPSENSE_CSD_TX_N_AMUXA_EN_PHI2); + } + } + + if(context->ptrCommonConfig->csdVref == 0u) + { + /* + * Get the recommended Vref voltage value if the Custom Vref option is not used. + */ + temp = Cy_CapSense_GetVrefAutoMv((uint32_t)context->ptrCommonConfig->vdda); + } + else + { + /* + * Initialize the Temp variable with the user defined Vref voltage if the + * Custom Vref option is used. + */ + temp = context->ptrCommonConfig->csdVref; + } + + if(CY_CAPSENSE_VREF_SRSS == context->ptrCommonConfig->ssVrefSource) + { + /* + * Calculate the VrefHigh Gain for the desired Vref voltage when SRSS is used as the Vref source. + */ + temp = (uint8_t)Cy_CapSense_GetVrefHighGain((uint32_t)context->ptrCommonConfig->vdda, + CY_CAPSENSE_VREF_SRSS_MV, temp); + /* + * Calculates the VrefHigh voltage, when SRSS is used as the Vref source. + */ + context->ptrInternalContext->csdVrefVoltageMv = (uint16_t)Cy_CapSense_GetVrefHighMv(CY_CAPSENSE_VREF_SRSS_MV, temp); + } + else if(CY_CAPSENSE_VREF_PASS == context->ptrCommonConfig->ssVrefSource) + { + /* + * Calculate the VrefHigh Gain for the desired Vref voltage when PASS is used as the Vref source. + */ + temp = (uint8_t)Cy_CapSense_GetVrefHighGain((uint32_t)context->ptrCommonConfig->vdda, + CY_CAPSENSE_VREF_PASS_MV, temp); + /* + * Calculates the VrefHigh voltage, when SRSS is used as the Vref source. + */ + context->ptrInternalContext->csdVrefVoltageMv = (uint16_t)Cy_CapSense_GetVrefHighMv(CY_CAPSENSE_VREF_PASS_MV, temp); + } + else + { + /* + * Pass the Vref source voltage to the VrefHigh output in case if the Vref source in unknown. + */ + temp = (uint8_t)(CY_CAPSENSE_VREF_GAIN_MAX - 1u); + } + + context->ptrInternalContext->csdVrefGain = (uint8_t)temp; + context->ptrInternalContext->csdRegRefgen = (CSD_REFGEN_REFGEN_EN_Msk | + CSD_REFGEN_RES_EN_Msk | + (temp << CSD_REFGEN_GAIN_Pos)); + } + + /* Common initialization */ + + /* Initialize RefGen Gain and Vref switches for sensing operation */ + if(CY_CAPSENSE_VREF_SRSS != context->ptrCommonConfig->ssVrefSource) + { + context->ptrInternalContext->csxRegRefgen = CY_CAPSENSE_DEFAULT_CSD_REFGEN_CFG | 0x00001F00uL; + context->ptrInternalContext->regSwRefGenSel = 0x00100000uL; + } + else + { + context->ptrInternalContext->csxRegRefgen = CY_CAPSENSE_DEFAULT_CSD_REFGEN_CFG | 0x00001500uL; + context->ptrInternalContext->regSwRefGenSel = 0x10000000uL; + } + + /* Initialize maxRawCount for all CSX widgets */ + for (wdgtIndex = context->ptrCommonConfig->numWd; wdgtIndex-- > 0u;) + { + if ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == context->ptrWdConfig[wdgtIndex].senseMethod) + { + context->ptrWdContext[wdgtIndex].maxRawCount = + (uint16_t)(((uint32_t)0x01u << context->ptrWdContext[wdgtIndex].resolution) - 1u); + } + if ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E == context->ptrWdConfig[wdgtIndex].senseMethod) + { + context->ptrWdContext[wdgtIndex].maxRawCount = (uint16_t)(context->ptrWdContext[wdgtIndex].resolution * + (context->ptrWdContext[wdgtIndex].snsClk - CY_CAPSENSE_CSX_DEADBAND_CYCLES_NUMBER)); + } + } + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) + { + + /* + * CSX Initialization + */ + /* Initialize CONFIG register values */ + context->ptrInternalContext->csxRegConfigInit = CY_CAPSENSE_DEFAULT_CSD_CONFIG_CFG; + context->ptrInternalContext->csxRegConfigScan = CY_CAPSENSE_PRESCAN_CSD_CONFIG_CFG; + + if(CY_CAPSENSE_IREF_SRSS != context->ptrCommonConfig->ssIrefSource) + { + context->ptrInternalContext->csxRegConfigInit |= 0x00000001uL; + context->ptrInternalContext->csxRegConfigScan |= 0x00000001uL; + } + + /* Initialize FilterDelay for CSX sensing */ + if (CY_CAPSENSE_MOD_CSD_CLK_12000000_HZ < context->ptrCommonConfig->periClkHz) + { + /* Calculate CSX modClk in Hz */ + temp = context->ptrCommonConfig->periClkHz / (uint32_t) context->ptrCommonContext->modCsxClk; + if(temp <= CY_CAPSENSE_MOD_CSD_CLK_12000000_HZ) + { + context->ptrInternalContext->csxRegConfigScan |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_12MHZ; + } + else if(temp <= CY_CAPSENSE_MOD_CSD_CLK_24000000_HZ) + { + context->ptrInternalContext->csxRegConfigScan |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_24MHZ; + } + else + { + context->ptrInternalContext->csxRegConfigScan |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_48MHZ; + } + } + else + { + context->ptrInternalContext->csxRegConfigScan |= CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_12MHZ; + } + + /* Default switch resistance selection */ + context->ptrInternalContext->csxRegSwResInit = + (((uint32_t)context->ptrCommonConfig->csxInitShieldSwRes << CSD_SW_RES_RES_HCAV_Pos) | + ((uint32_t)context->ptrCommonConfig->csxInitShieldSwRes << CSD_SW_RES_RES_HCAG_Pos) | + ((uint32_t)context->ptrCommonConfig->csxInitShieldSwRes << CSD_SW_RES_RES_HCBV_Pos) | + ((uint32_t)context->ptrCommonConfig->csxInitShieldSwRes << CSD_SW_RES_RES_HCBG_Pos) | + ((uint32_t)context->ptrCommonConfig->csxInitSwRes << CSD_SW_RES_RES_F1PM_Pos) | + ((uint32_t)context->ptrCommonConfig->csxInitSwRes << CSD_SW_RES_RES_F2PT_Pos)); + /* Switch resistance selection for scan */ + context->ptrInternalContext->csxRegSwResScan = + (((uint32_t)context->ptrCommonConfig->csxScanShieldSwRes << CSD_SW_RES_RES_HCAV_Pos) | + ((uint32_t)context->ptrCommonConfig->csxScanShieldSwRes << CSD_SW_RES_RES_HCAG_Pos) | + ((uint32_t)context->ptrCommonConfig->csxScanShieldSwRes << CSD_SW_RES_RES_HCBV_Pos) | + ((uint32_t)context->ptrCommonConfig->csxScanShieldSwRes << CSD_SW_RES_RES_HCBG_Pos) | + ((uint32_t)context->ptrCommonConfig->csxScanSwRes << CSD_SW_RES_RES_F1PM_Pos) | + ((uint32_t)context->ptrCommonConfig->csxScanSwRes << CSD_SW_RES_RES_F2PT_Pos)); + /* Switch resistance selection for precharge */ + context->ptrInternalContext->csxRegSwResPrech = context->ptrInternalContext->csxRegSwResInit; + } + + return (initStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsInitialize +****************************************************************************//** +* +* Performs hardware and firmware initialization required for proper operation +* of the CapSense middleware. This function is called from +* the Cy_CapSense_Init() prior to calling any other function of the middleware. +* +* This function +* 1. Depending on the configuration, the function initializes the CSD HW block +* for the corresponding sensing mode. +* 2. Sets all IOs into the default state. +* 3. Performs pre-calculations of register values depending on configuration. +* +* Calling the Cy_CapSense_Init() is the recommended method to initialize +* the CapSense middleware at power-up. The Cy_CapSense_SsInitialize() +* should not be used for initialization, resume, or wake-up operations. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return status +* Returns status of operation: +* - Zero - Indicates successful initialization. +* - Non-zero - One or more errors occurred in the initialization process. +* +*******************************************************************************/ +cy_status Cy_CapSense_SsInitialize(cy_stc_capsense_context_t * context) +{ + cy_status initStatus; + + initStatus = Cy_CapSense_InternalPreCalculation(context); + + Cy_CapSense_InitializeSourceSenseClk(context); + + /* Set all IO states to default state */ + Cy_CapSense_SetIOsInDefaultState(context); + Cy_CapSense_SetSpecificIOsInDefaultState(context); + + /* + * The CSD HW block is initialized in the Setup Widget functions based + * on widget sensing method. + */ + Cy_CapSense_SwitchSensingMode((uint8_t)CY_CAPSENSE_UNDEFINED_E, context); + + return (initStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetPinState +****************************************************************************//** +* +* Sets the state (drive mode and HSIOM state) of the GPIO used by a sensor. +* +* The possible states are GND, Shield, High-Z, Tx, Rx, and Sensor. +* If the sensor specified in the input parameter is a ganged sensor, then +* the state of all GPIOs associated with the ganged sensor is updated. +* +* To access a sensor of CSD of button or slider widgets, use the sensor ID. +* To access a sensor of CSD matrix button or touchpad widgets, +* use either row ID or column ID as appropriate. +* To access sensor CSX widgets, use either Rx ID or Tx ID as appropriate. +* +* This function accepts the CY_CAPSENSE_SHIELD and CY_CAPSENSE_SENSOR states +* as an input only if there is at least one CSD widget in the project. +* Similarly, this function accepts the CY_CAPSENSE_TX_PIN and +* CY_CAPSENSE_RX_PIN states as an input only if there is at least one +* CSX widget in the project. +* +* This function must not be called while the middleware is in the busy state. +* Calling this function directly from the application program is not +* recommended. This function is used to implement only the custom-specific +* use cases. +* +* Functions that perform a setup and scan of a sensor/widget automatically +* set the required pin states for a sensor as required and overwrite changes +* made by this function to a sensor that are going to be scanned. Therefore +* the Cy_CapSense_SetPinState() function could be called in StartSample +* callback (see the \ref group_capsense_callbacks section for details) +* or with low-level functions that perform a single-sensor scanning. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorElement +* Specifies the ID of the sensor element within the widget to change +* its pin state. +* * For the CSD widgets use the sensor ID. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* * For the CSX widgets use either Rx ID or Tx ID. +* The first Rx in a widget corresponds to sensorElement = 0; the second +* Rx in a widget corresponds to sensorElement = 1, and so on. +* The last Tx in a widget corresponds to sensorElement = (RxNum + TxNum - 1). +* A macro for the Rx ID or Tx ID can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE___ID. +* +* \param state +* Specifies the state of the sensor to be set: +* 1. CY_CAPSENSE_GROUND - The pin is connected to the ground. +* 2. CY_CAPSENSE_HIGHZ - The drive mode of the pin is set to High-Z +* Analog. +* 3. CY_CAPSENSE_SHIELD - The shield signal is routed to the pin +* (available only if CSD sensing method with +* shield electrode is enabled). +* 4. CY_CAPSENSE_SENSOR - The pin is connected to the scanning bus +* (available only if CSD sensing method is enabled). +* 5. CY_CAPSENSE_TX_PIN - The Tx signal is routed to the sensor +* (available only if CSX sensing method is enabled). +* 6. CY_CAPSENSE_RX_PIN - The pin is connected to the scanning bus +* (available only if CSX sensing method is enabled). +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return status +* Returns the operation status: +* - CY_RET_SUCCESS - Indicates the successful electrode setting. +* - CY_RET_BAD_PARAM - 1) widgetID or sensorElement are not valid; +* 2) the CSD sensing method is disabled for desired +* CY_CAPSENSE_SHIELD or CY_CAPSENSE_SENSOR states; +* 3) the CSX sensing method is disabled for desired +* CY_CAPSENSE_TX_PIN or CY_CAPSENSE_RX_PIN states. +* +* \funcusage +* +* An example of using the Cy_CapSense_SetPinState() function to perform +* sensor state re-configuration: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_SetPinState +* +*******************************************************************************/ +cy_status Cy_CapSense_SetPinState( + uint32_t widgetId, + uint32_t sensorElement, + uint32_t state, + cy_stc_capsense_context_t * context) +{ + cy_status connState = CY_RET_BAD_PARAM; + uint32_t eltdNum; + uint32_t eltdIndex; + uint32_t interruptState; + cy_stc_capsense_pin_config_t const * ioPtr; + cy_stc_capsense_widget_config_t const * ptrWdCfg = &context->ptrWdConfig[widgetId]; + + if (context->ptrCommonConfig->numWd > widgetId) + { + /* Get number of electrodes within the widget */ + eltdNum = (uint32_t)ptrWdCfg->numCols + ptrWdCfg->numRows; + if (((uint8_t)CY_CAPSENSE_CSD_SENSING_METHOD == (uint32_t)ptrWdCfg->senseMethod) && + (((uint8_t)CY_CAPSENSE_WD_BUTTON_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E == ptrWdCfg->wdType))) + { + eltdNum = context->ptrWdConfig->numSns; + } + + if (eltdNum > sensorElement) + { + /* Get number of electrode's pins and a pointer to the electrode's pin structure */ + eltdNum = ptrWdCfg->ptrEltdConfig->numPins; + ioPtr = ptrWdCfg->ptrEltdConfig->ptrPin; + /* Loop through all pins of the specified sensor electrode */ + for (eltdIndex = 0u; eltdIndex < eltdNum; eltdIndex++) + { + /* Reset HSIOM and PC registers */ + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetHSIOM(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_SysLib_ExitCriticalSection(interruptState); + + switch (state) + { + case CY_CAPSENSE_GROUND: + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetDrivemode(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber, CY_GPIO_DM_STRONG_IN_OFF); + Cy_GPIO_Clr(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber); + Cy_SysLib_ExitCriticalSection(interruptState); + + connState = CY_RET_SUCCESS; + break; + + case CY_CAPSENSE_HIGHZ: + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetDrivemode(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber, CY_GPIO_DM_ANALOG); + Cy_GPIO_Clr(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber); + Cy_SysLib_ExitCriticalSection(interruptState); + + connState = CY_RET_SUCCESS; + break; + + case CY_CAPSENSE_SENSOR: + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdEn) + { + /* Enable sensor */ + Cy_CapSense_CSDConnectSns(ioPtr, context); + + connState = CY_RET_SUCCESS; + } + break; + + case CY_CAPSENSE_SHIELD: + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdShieldEn) + { + Cy_CapSense_SsConfigPinRegisters(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber, + CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_CSD_SHIELD); + connState = CY_RET_SUCCESS; + } + break; + + case CY_CAPSENSE_TX_PIN: + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) + { + Cy_CapSense_SsConfigPinRegisters(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber, + CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_CSD_SHIELD); + connState = CY_RET_SUCCESS; + } + break; + + case CY_CAPSENSE_RX_PIN: + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) + { + Cy_CapSense_SsConfigPinRegisters(ioPtr->pcPtr, (uint32_t)ioPtr->pinNumber, + CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_AMUXA); + connState = CY_RET_SUCCESS; + } + break; + + default: + break; + } + + ioPtr++; + } + } + } + return (connState); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SwitchSensingMode +****************************************************************************//** +* +* This function changes the mode for case when both CSD and CSX widgets are +* scanned. +* +* Once the function is called it performs the following tasks: +* 1. Releasing the CSD HW block by existing sensing method. +* 2. Configuring corresponding external capacitors and sensor pins into +* default states. +* 3. Setting new mode. +* 4. Configuring HW to the new sensing mode. +* +* \param mode +* Specifies the scan mode: +* - CY_CAPSENSE_SENSE_METHOD_CSD_E +* - CY_CAPSENSE_SENSE_METHOD_CSX_E +* - CY_CAPSENSE_UNDEFINED_E +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SwitchSensingMode(uint8_t mode, cy_stc_capsense_context_t * context) +{ + if (context->ptrActiveScanSns->currentSenseMethod != mode) + { + /* The requested mode differs from the current one. Disable the current mode. */ + switch(context->ptrActiveScanSns->currentSenseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDDisableMode(context); + break; + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXDisableMode(context); + break; + default: + break; + } + + context->ptrActiveScanSns->currentSenseMethod = mode; + + /* Enable the specified mode */ + switch(context->ptrActiveScanSns->currentSenseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDInitialize(context); + break; + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXInitialize(context); + break; + default: + break; + } + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetIOsInDefaultState +****************************************************************************//** +* +* Sets all CapSense pins into a default state. +* +* \details +* Sets all the CSD/CSX IOs into a default state: +* - HSIOM - Disconnected, the GPIO mode. +* - DM - Strong drive. +* - State - Zero. +* +* Do not call this function directly from the application program. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SetIOsInDefaultState(const cy_stc_capsense_context_t * context) +{ + uint32_t loopIndex; + uint32_t interruptState; + const cy_stc_capsense_pin_config_t * ptrPinCfg = context->ptrPinConfig; + + /* Loop through all electrodes */ + for (loopIndex = 0u; loopIndex < context->ptrCommonConfig->numPin; loopIndex++) + { + interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_Pin_FastInit(ptrPinCfg->pcPtr, (uint32_t)ptrPinCfg->pinNumber, + CY_GPIO_DM_STRONG, 0u, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_SysLib_ExitCriticalSection(interruptState); + + /* Get next electrode */ + ptrPinCfg++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetSpecificIOsInDefaultState +****************************************************************************//** +* +* Sets all CapSense pins into a default state. +* +* \details +* Sets all external capacitors and shield electrodes into a default state: +* - HSIOM - Disconnected, the GPIO mode. +* - DM - High-Z Analog. +* +* Do not call this function directly from the application program. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SetSpecificIOsInDefaultState(const cy_stc_capsense_context_t * context) +{ + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdEn) + { + /* Cmod pin to default state */ + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_GPIO); + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdShieldEn) + { + /* Disconnect shields */ + Cy_CapSense_CSDDisableShieldElectrodes(context); + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdCTankShieldEn) + { + /* Csh pin to default state */ + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, (uint32_t)context->ptrCommonConfig->pinCsh, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_GPIO); + } + } + } + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) + { + /* CintA pin to default state */ + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCintA, (uint32_t)context->ptrCommonConfig->pinCintA, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_GPIO); + + /* CintB pin to default state */ + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCintB, (uint32_t)context->ptrCommonConfig->pinCintB, CY_GPIO_DM_ANALOG, CY_CAPSENSE_HSIOM_SEL_GPIO); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsPostAllWidgetsScan +****************************************************************************//** +* +* Configures and triggers the scan of the next widget if queue is not empty. +* This function should not be used by the application program. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SsPostAllWidgetsScan(cy_stc_capsense_context_t * context) +{ + /* + * 1. Increment widget index + * 2. Check whether all the widgets are scanned + * 3. If all the widgets are not scanned, set up and scan next widget + */ + cy_status postScanStatus; + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + uint32_t widgetId = (uint32_t)ptrActive->widgetIndex + 1u; + + do + { + if (context->ptrCommonConfig->numWd > widgetId) + { + /* Set up the next widget */ + context->ptrCommonContext->status = 0u; + postScanStatus = Cy_CapSense_SetupWidget(widgetId, context); + if (CY_RET_SUCCESS == postScanStatus) + { + (void)Cy_CapSense_Scan(context); + } + else + { + /* The next widget is not available for scanning. Skip it. */ + widgetId++; + } + } + else + { + /* All the widgets are scanned. Reset BUSY flag. */ + Cy_CapSense_ClrBusyFlags(context); + + /* Set postScanStatus to exit the while loop */ + postScanStatus = CY_RET_SUCCESS; + } + } while (CY_RET_SUCCESS != postScanStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InterruptHandler +****************************************************************************//** +* +* Implements interrupt service routine for CapSense Middleware. +* +* The CSD HW block generates an interrupt at end of every sensor scan. +* The CapSense middleware uses this interrupt to implement a +* non-blocking sensor scan method, in which only the first sensor scan is +* initiated by the application program and subsequent sensor scans are +* initiated in the interrupt service routine as soon as the current scan +* is completed. The above stated interrupt service routine is implemented +* as a part of the CapSense middleware. +* +* The CapSense middleware does not initialize or modify the priority +* of interrupts. For the operation of middleware, the application program +* must configure CSD interrupt and assign interrupt vector to +* the Cy_CapSense_InterruptHandler() function. Refer to function +* usage example for details. +* +* \param base +* The pointer to the base register address of the CSD HW block. A macro for +* the pointer can be found in cycfg_peripherals.h file defined as +* \_HW. If no name is specified then the default name +* is used csd_\_csd_\_HW. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \note +* The calls of the Start Sample and End Of Scan callbacks +* (see the \ref group_capsense_callbacks section for details) are the part of the +* Cy_CapSense_InterruptHandler() routine and they lengthen its execution. These +* callbacks will lengthen the CSD ISR execution in case of a direct call of the +* Cy_CapSense_InterruptHandler() function from a CSD ISR. +* +* \funcusage +* +* An example of the ISR initialization: +* +* The CapSense_ISR_cfg variable should be declared by the application +* program according to the examples below:
+* For Core CM0+: +* \snippet capsense\1.1\snippet\main.c snippet_m0p_capsense_interrupt_source_declaration +* +* For Core CM4: +* \snippet capsense\1.1\snippet\main.c snippet_m4_capsense_interrupt_source_declaration +* +* The CapSense interrupt handler should be defined by the application program +* according to the example below: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_IntHandler +* +* Then, the application program should configure and enable the CSD block interrupt +* between calls of the Cy_CapSense_Init() and Cy_CapSense_Enable() functions: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Initialization +* +* CapSense_HW is the pointer to the base register address of +* the CSD HW block. A macro for the pointer can be found in the cycfg_peripherals.h +* file defined as \_HW. If no name specified, +* the default name is used csd_\_csd_\_HW. +* +* An example of sharing the CSD HW block by the CapSense and CSDADC middleware.
+* Declares the CapSense_ISR_cfg variable: +* \snippet capsense\1.1\snippet\main.c snippet_m4_capsense_interrupt_source_declaration +* +* Declares the CSDADC_ISR_cfg variable: +* \snippet capsense\1.1\snippet\main.c snippet_m4_adc_interrupt_source_declaration +* +* Defines the CapSense interrupt handler: +* \snippet capsense\1.1\snippet\main.c snippet_CapSense_Interrupt +* +* Defines the CSDADC interrupt handler: +* \snippet capsense\1.1\snippet\main.c snippet_CSDADC_Interrupt +* +* The part of the main.c FW flow: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_TimeMultiplex +* +*******************************************************************************/ +void Cy_CapSense_InterruptHandler(const CSD_Type * base, cy_stc_capsense_context_t * context) +{ + (void)base; + context->ptrActiveScanSns->ptrISRCallback((void *)context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalibrateWidget +****************************************************************************//** +* +* Executes the IDAC calibration for all the sensors in the specified widget +* to the default target value. +* +* This function performs exactly the same tasks as +* Cy_CapSense_CalibrateAllWidgets(), but only for a specified widget. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified widget calibration: +* - CY_RET_SUCCESS - The operation is successfully completed. +* - CY_RET_BAD_PARAM - The input parameter is invalid. +* - CY_RET_BAD_DATA - The calibration failed and the middleware may not +* operate as expected. +* +*******************************************************************************/ +cy_status Cy_CapSense_CalibrateWidget(uint32_t widgetId, cy_stc_capsense_context_t * context) +{ + cy_status calibrateStatus = CY_RET_BAD_PARAM; + + if(context->ptrCommonConfig->numWd > widgetId) + { + switch(context->ptrWdConfig[widgetId].senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + calibrateStatus = Cy_CapSense_CSDCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csdRawTarget, context); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + calibrateStatus = Cy_CapSense_CSXCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csxRawTarget, context); + break; + + default: + break; + } + } + + return calibrateStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalibrateAllWidgets +****************************************************************************//** +* +* Executes the IDAC calibration for all the sensors in all widgets in +* the middleware to default target value. +* +* This function detects the sensing method used by each widget and performs +* a successive approximation search algorithm to find the appropriate modulator +* and compensation IDAC (if enabled) values for all sensors in CSD widgets +* and/or IDAC values for all sensors in CSX widgets to make sensor raw count +* to the default value level. +* +* Calibration returns CYRET_BAD_DATA if resulted raw count is outside +* the limits. +* +* This function could be used only if Enable IDAC auto-calibration parameter +* is enabled for CSD and/or CSX widgets. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the calibration process: +* - CY_RET_SUCCESS - The operation is successfully completed. +* - CY_RET_BAD_DATA - The calibration failed and the middleware may not +* operate as expected. +* +*******************************************************************************/ +cy_status Cy_CapSense_CalibrateAllWidgets(cy_stc_capsense_context_t * context) +{ + cy_status calibrateStatus = CY_RET_SUCCESS; + uint32_t wdgtIndex; + + for (wdgtIndex = 0u; wdgtIndex < context->ptrCommonConfig->numWd; wdgtIndex++) + { + calibrateStatus |= Cy_CapSense_CalibrateWidget(wdgtIndex, context); + } + + return calibrateStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalibrateAllCsdWidgets +****************************************************************************//** +* +* Executes the IDAC calibration for all the sensors in CSD widgets to +* the default target value. +* +* This function performs exact same tasks of Cy_CapSense_CalibrateAllWidgets(), +* but only for CSD widgets. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the operation: +* - Zero - All the widgets are calibrated successfully. +* - Non-zero - Calibration failed for at least one widget. +* +*******************************************************************************/ +cy_status Cy_CapSense_CalibrateAllCsdWidgets(cy_stc_capsense_context_t * context) +{ + uint32_t widgetId; + cy_status calibrateStatus = CY_RET_SUCCESS; + + for(widgetId = 0uL; widgetId < context->ptrCommonConfig->numWd; widgetId++) + { + if((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == context->ptrWdConfig[widgetId].senseMethod) + { + calibrateStatus |= Cy_CapSense_CSDCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csdRawTarget, context); + } + } + + return(calibrateStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalibrateAllCsxWidgets +****************************************************************************//** +* +* Executes the IDAC calibration for all the sensors in CSX widgets to +* the default target value. +* +* This function performs the exact same tasks of Cy_CapSense_CalibrateAllWidgets(), +* but only for CSX widgets. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the operation: +* - Zero - All the widgets are calibrated successfully. +* - Non-zero - Calibration failed for at least one widget. +* +*******************************************************************************/ +cy_status Cy_CapSense_CalibrateAllCsxWidgets(cy_stc_capsense_context_t * context) +{ + uint32_t widgetId; + cy_status calibrateStatus = CY_RET_SUCCESS; + + for(widgetId = 0uL; widgetId < context->ptrCommonConfig->numWd; widgetId++) + { + if((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E == context->ptrWdConfig[widgetId].senseMethod) + { + calibrateStatus |= Cy_CapSense_CSXCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csxRawTarget, context); + } + } + + return(calibrateStatus); + +} + + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsAutoTune +****************************************************************************//** +* +* Performs the parameters auto-tuning for the optimal CapSense operation when +* SmartSense is enabled. +* +* This function performs the following tasks: +* - Calibrate Modulator and Compensation IDACs. +* - Tune the Sense Clock optimal value to get a Sense Clock period greater +* than 2*5*R*Cp. +* - Calculate the resolution for the optimal finger capacitance. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the operation: +* - Zero - All the widgets are auto-tuned successfully. +* - Non-zero - Auto-tuning failed for any widget. +* +*******************************************************************************/ +cy_status Cy_CapSense_SsAutoTune(cy_stc_capsense_context_t * context) +{ + cy_status autoTuneStatus = CY_RET_SUCCESS; + uint32_t wdIndex; + + for (wdIndex = 0u; wdIndex < context->ptrCommonConfig->numWd; wdIndex++) + { + if ((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == context->ptrWdConfig[wdIndex].senseMethod) + { + autoTuneStatus |= Cy_CapSense_SsAutoTuneWidget(wdIndex, context); + } + } + + return autoTuneStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsAutoTuneWidget +****************************************************************************//** +* +* Performs the parameters auto-tuning for the optimal CapSense operation when +* SmartSense is enabled. +* +* This function performs the following tasks: +* - Calibrate Modulator and Compensation IDACs. +* - Tune the Sense Clock optimal value to get a Sense Clock period greater +* than 2*5*R*Cp. +* - Calculate the resolution for the optimal finger capacitance. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the operation: +* - Zero - All the widgets are auto-tuned successfully. +* - Non-zero - Auto-tuning failed. +* +*******************************************************************************/ +cy_status Cy_CapSense_SsAutoTuneWidget( + uint32_t widgetId, + cy_stc_capsense_context_t * context) +{ + cy_status autoTuneStatus = CY_RET_SUCCESS; + + uint32_t snsIndex; + uint32_t inputSnsClk; + uint32_t minSnsClkDiv; + uint32_t snsClkSourceAuto; + + cy_stc_capsense_auto_tune_config_t autoTuneConfig; + + uint32_t maxRaw = 0u; + uint32_t maxCp = 0u; + uint32_t maxIdacComp = 0u; + + uint32_t maxCpSnsId = 0u; + uint32_t maxCpRowSnsId = 0u; + + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_widget_context_t * ptrWdCxt = ptrWdCfg->ptrWdContext; + cy_stc_capsense_sensor_context_t * ptrSnsCtx; + + /* Store sense clock source to be restored at the end of function */ + snsClkSourceAuto = ptrWdCxt->snsClkSource; + + /* Find input of sensor clock frequency */ + inputSnsClk = context->ptrCommonConfig->periClkHz / + context->ptrCommonContext->modCsdClk / + CY_CAPSENSE_CSD_AUTOTUNE_CAL_UNITS; + + minSnsClkDiv = context->ptrCommonConfig->periClkHz / + context->ptrCommonContext->modCsdClk / + CY_CAPSENSE_CSD_SNS_FREQ_KHZ_MAX; + if (CY_CAPSENSE_MIN_SNS_CLK_DIVIDER > minSnsClkDiv) + { + minSnsClkDiv = CY_CAPSENSE_MIN_SNS_CLK_DIVIDER; + } + minSnsClkDiv = (minSnsClkDiv + (CY_CAPSENSE_CSD_AUTOTUNE_CAL_UNITS - 1u)) / CY_CAPSENSE_CSD_AUTOTUNE_CAL_UNITS; + /* Make divider even */ + if (0u != (minSnsClkDiv & 0x01u)) + { + minSnsClkDiv++; + } + + /* Initialize auto-tuning configuration structure */ + autoTuneConfig.snsClkInputClock = (uint16_t)inputSnsClk; + autoTuneConfig.snsClkConstantR = context->ptrCommonConfig->csdRConst; + autoTuneConfig.vRef = context->ptrInternalContext->csdVrefVoltageMv; + autoTuneConfig.fingerCap = ptrWdCxt->fingerCap; + autoTuneConfig.sigPFC = &(ptrWdCxt->sigPFC); + + /* + * Autotune phase #1: + * - performing the first calibration at fixed settings + * - getting maximum sensor Cp + * - getting sense clock frequency based on Cp + */ + + ptrWdCxt->resolution = CY_CAPSENSE_AUTOTUNE_CALIBRATION_RESOLUTION; + ptrWdCxt->maxRawCount = (uint16_t)(0x01uL << CY_CAPSENSE_AUTOTUNE_CALIBRATION_RESOLUTION) - 1u; + ptrWdCxt->snsClkSource = CY_CAPSENSE_CLK_SOURCE_DIRECT; + ptrWdCxt->snsClk = (uint16_t)(inputSnsClk / CY_CAPSENSE_AUTOTUNE_CALIBRATION_FREQ_KHZ); + ptrWdCxt->rowSnsClk = ptrWdCxt->snsClk; + + /* Calibrate CSD widget to the default calibration target */ + (void)Cy_CapSense_CSDCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csdRawTarget, context); + + /* Find raw count and IDAC of a sensor with maximum Cp */ + ptrSnsCtx = ptrWdCfg->ptrSnsContext; + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + for (snsIndex = 0u; snsIndex < ptrWdCfg->numCols; snsIndex++) + { + if (maxIdacComp < ptrSnsCtx->idacComp) + { + maxCpSnsId = snsIndex; + maxIdacComp = ptrSnsCtx->idacComp; + maxRaw = ptrSnsCtx->raw; + } + ptrSnsCtx++; + } + } + else + { + for (snsIndex = 0u; snsIndex < ptrWdCfg->numCols; snsIndex++) + { + if (maxRaw < ptrSnsCtx->raw) + { + maxCpSnsId = snsIndex; + maxRaw = ptrSnsCtx->raw; + } + ptrSnsCtx++; + } + } + + /* Update auto-tuning configuration structure */ + autoTuneConfig.iDacMod = ptrWdCxt->idacMod[CY_CAPSENSE_MFS_CH0_INDEX]; + autoTuneConfig.iDacComp = (uint8_t)maxIdacComp; + autoTuneConfig.iDacGain = context->ptrCommonConfig->idacGainTable[ptrWdCxt->idacGainIndex].gainValue; + autoTuneConfig.ptrSenseClk = &ptrWdCxt->snsClk; + autoTuneConfig.calTarget = (uint16_t)((maxRaw * CY_CAPSENSE_CSD_AUTOTUNE_CAL_UNITS) / + ((uint32_t)(0x01uL << CY_CAPSENSE_AUTOTUNE_CALIBRATION_RESOLUTION) - 1u)); + + /* Find sensor Cp and optimum sense clock value */ + maxCp = Cy_CapSense_TunePrescalers_Lib(&autoTuneConfig); + autoTuneConfig.sensorCap = maxCp; + + /* Increase sensor clock divider to valid value */ + if (((uint32_t)ptrWdCxt->snsClk) < minSnsClkDiv) + { + ptrWdCxt->snsClk = (uint16_t)minSnsClkDiv; + } + + if (((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == ptrWdCfg->wdType)) + { + /* Find a sensor with maximum Cp */ + maxRaw = 0u; + maxIdacComp = 0u; + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdIdacCompEn) + { + for (snsIndex = 0u; snsIndex < ptrWdCfg->numCols; snsIndex++) + { + if (maxIdacComp < ptrSnsCtx->idacComp) + { + maxCpRowSnsId = snsIndex; + maxIdacComp = ptrSnsCtx->idacComp; + maxRaw = ptrSnsCtx->raw; + } + ptrSnsCtx++; + } + } + else + { + for (snsIndex = 0u; snsIndex < ptrWdCfg->numCols; snsIndex++) + { + if (maxRaw < ptrSnsCtx->raw) + { + maxCpRowSnsId = snsIndex; + maxRaw = ptrSnsCtx->raw; + } + ptrSnsCtx++; + } + } + + /* Configure auto-tuning configuration structure */ + autoTuneConfig.iDacMod = ptrWdCxt->rowIdacMod[CY_CAPSENSE_MFS_CH0_INDEX]; + autoTuneConfig.iDacComp = (uint8_t)maxIdacComp; + autoTuneConfig.ptrSenseClk = &ptrWdCxt->rowSnsClk; + autoTuneConfig.calTarget = (uint16_t)((maxRaw * CY_CAPSENSE_CSD_AUTOTUNE_CAL_UNITS) / + ((uint32_t)(0x01uL << CY_CAPSENSE_AUTOTUNE_CALIBRATION_RESOLUTION) - 1u)); + + /* Find correct sense clock value */ + maxCp = Cy_CapSense_TunePrescalers_Lib(&autoTuneConfig); + /* Save maximum sensor Cp and corresponding sensor Id */ + if (autoTuneConfig.sensorCap < maxCp) + { + autoTuneConfig.sensorCap = maxCp; + maxCpSnsId = maxCpRowSnsId; + } + + /* Increase sensor clock divider to valid value */ + if (((uint32_t)ptrWdCxt->rowSnsClk) < minSnsClkDiv) + { + ptrWdCxt->rowSnsClk = (uint16_t)minSnsClkDiv; + } + } + + /* Check tuning results */ + if (CY_CAPSENSE_AUTOTUNE_CP_MAX < maxCp) + { + autoTuneStatus = CYRET_BAD_DATA; + } + + /* + * Autotune phase #2: + * - repeating calibration with new sense clock frequency + * - getting resolution + */ + + /* Calibrate CSD widget to the default calibration target with newly defined sense frequency */ + (void)Cy_CapSense_CSDCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csdRawTarget, context); + + autoTuneConfig.iDacGain = context->ptrCommonConfig->idacGainTable[ptrWdCxt->idacGainIndex].gainValue; + autoTuneConfig.iDacMod = ptrWdCxt->idacMod[CY_CAPSENSE_MFS_CH0_INDEX]; + autoTuneConfig.ptrSenseClk = &ptrWdCxt->snsClk; + + if (((uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E == ptrWdCfg->wdType) || + ((uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E == ptrWdCfg->wdType)) + { + if (maxCpSnsId >= ptrWdCfg->numCols) + { + autoTuneConfig.iDacMod = ptrWdCxt->rowIdacMod[CY_CAPSENSE_MFS_CH0_INDEX]; + autoTuneConfig.ptrSenseClk = &ptrWdCxt->rowSnsClk; + } + } + + /* Find resolution */ + ptrWdCxt->resolution = Cy_CapSense_TuneSensitivity_Lib(&autoTuneConfig); + ptrWdCxt->maxRawCount = (uint16_t)(0x01uL << ptrWdCxt->resolution) - 1u; + + + /* + * Autotune phase #3: + * - selecting a widget clock source if AUTO + * - repeating calibration with found clock frequency, resolution and clock source + * - updating sensitivity + */ + + /* Update clock source */ + ptrWdCxt->snsClkSource = (uint8_t)snsClkSourceAuto; + Cy_CapSense_CSDSetWidgetSenseClkSrc(ptrWdCfg); + + /* Calibrate CSD widget to the default calibration target with newly defined resolution */ + autoTuneStatus |= Cy_CapSense_CSDCalibrateWidget(widgetId, (uint32_t)context->ptrCommonConfig->csdRawTarget, context); + + return autoTuneStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitializeSourceSenseClk +****************************************************************************//** +* +* Sets a source for Sense/Tx clock for all widgets. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitializeSourceSenseClk(const cy_stc_capsense_context_t * context) +{ + uint32_t wdIndex; + const cy_stc_capsense_widget_config_t * ptrWdCfg = context->ptrWdConfig; + + for (wdIndex = 0u; wdIndex < context->ptrCommonConfig->numWd; wdIndex++) + { + switch(ptrWdCfg->senseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + Cy_CapSense_CSDSetWidgetSenseClkSrc(ptrWdCfg); + break; + + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + Cy_CapSense_CSXSetWidgetTxClkSrc(ptrWdCfg); + break; + + default: + break; + } + /* Switch to the next widget */ + ptrWdCfg++; + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsCalcLfsrSize +****************************************************************************//** +* +* Finds a SSC polynomial size when clock source is configured to Auto mode. +* +* The SSC polynomial size in the auto mode is found based on the following +* requirements: +* - an LFSR value should be selected so that the max clock dither +* is limited with +/-10%. +* - at least one full spread spectrum polynomial should pass during +* the scan time. +* - the value of the number of conversions should be an integer multiple +* of the repeat period of the programmed LFSR_SIZE. +* +* \param snsClkDivider +* The divider value for the sense/Tx clock. +* +* \param conversionsNum +* The widget conversion number. +* +* \return +* Returns the size of LFSR value for the SENSE_PERIOD register. +* +*******************************************************************************/ +uint32_t Cy_CapSense_SsCalcLfsrSize(uint32_t clkDivider, uint32_t conversionsNum) +{ + uint32_t lfsrSize = 0u; + + if(CY_CAPSENSE_SNSCLK_LFSR_THRESHOLD <= clkDivider) + { + /* Find LFSR value */ + if((CY_CAPSENSE_SNSCLK_SSC4_PERIOD <= conversionsNum) && + (0uL == (conversionsNum % CY_CAPSENSE_SNSCLK_SSC4_PERIOD))) + { + lfsrSize = CY_CAPSENSE_CLK_SOURCE_SSC10; + } + else if((CY_CAPSENSE_SNSCLK_SSC3_PERIOD <= conversionsNum) && + (0uL == (conversionsNum % CY_CAPSENSE_SNSCLK_SSC3_PERIOD))) + { + lfsrSize = CY_CAPSENSE_CLK_SOURCE_SSC9; + } + else if((CY_CAPSENSE_SNSCLK_SSC2_PERIOD <= conversionsNum) && + (0uL == (conversionsNum % CY_CAPSENSE_SNSCLK_SSC2_PERIOD))) + { + lfsrSize = CY_CAPSENSE_CLK_SOURCE_SSC7; + } + else if((CY_CAPSENSE_SNSCLK_SSC1_PERIOD <= conversionsNum) && + (0uL == (conversionsNum % CY_CAPSENSE_SNSCLK_SSC1_PERIOD))) + { + lfsrSize = CY_CAPSENSE_CLK_SOURCE_SSC6; + } + else + { + lfsrSize = CY_CAPSENSE_CLK_SOURCE_DIRECT; + } + } + + return lfsrSize; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_DischargeExtCapacitors +****************************************************************************//** +* +* Discharges available external capacitors. +* +* The function discharges available external capacitors by disconnecting them +* from an analog bus and configuring strong GPIO drive mode with 0. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_DischargeExtCapacitors(cy_stc_capsense_context_t * context) +{ + uint32_t cshPcReg = 0uL; + uint32_t cmodPcReg = 0uL; + uint32_t cintAPcReg = 0uL; + uint32_t cintBPcReg = 0uL; + + en_hsiom_sel_t cshHsiomReg = CY_CAPSENSE_HSIOM_SEL_GPIO; + en_hsiom_sel_t cmodHsiomReg = CY_CAPSENSE_HSIOM_SEL_GPIO; + en_hsiom_sel_t cintAHsiomReg = CY_CAPSENSE_HSIOM_SEL_GPIO; + en_hsiom_sel_t cintBHsiomReg = CY_CAPSENSE_HSIOM_SEL_GPIO; + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdEn) + { + Cy_CapSense_SsReadPinRegisters(context->ptrCommonConfig->portCmod, + (uint32_t)context->ptrCommonConfig->pinCmod, &cmodPcReg, &cmodHsiomReg); + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCmod, + (uint32_t)context->ptrCommonConfig->pinCmod, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_GPIO_Clr(context->ptrCommonConfig->portCmod, (uint32_t)context->ptrCommonConfig->pinCmod); + + if((CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdShieldEn) && + (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdCTankShieldEn)) + { + Cy_CapSense_SsReadPinRegisters(context->ptrCommonConfig->portCsh, + (uint32_t)context->ptrCommonConfig->pinCsh, &cshPcReg, &cshHsiomReg); + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, + (uint32_t)context->ptrCommonConfig->pinCsh, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_GPIO_Clr(context->ptrCommonConfig->portCsh, (uint32_t)context->ptrCommonConfig->pinCsh); + } + } + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) + { + Cy_CapSense_SsReadPinRegisters(context->ptrCommonConfig->portCintA, + (uint32_t)context->ptrCommonConfig->pinCintA, &cintAPcReg, &cintAHsiomReg); + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCintA, + (uint32_t)context->ptrCommonConfig->pinCintA, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_GPIO_Clr(context->ptrCommonConfig->portCintA, (uint32_t)context->ptrCommonConfig->pinCintA); + + Cy_CapSense_SsReadPinRegisters(context->ptrCommonConfig->portCintB, + (uint32_t)context->ptrCommonConfig->pinCintB, &cintBPcReg, &cintBHsiomReg); + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCintB, + (uint32_t)context->ptrCommonConfig->pinCintB, CY_GPIO_DM_STRONG_IN_OFF, CY_CAPSENSE_HSIOM_SEL_GPIO); + Cy_GPIO_Clr(context->ptrCommonConfig->portCintB, (uint32_t)context->ptrCommonConfig->pinCintB); + } + + Cy_SysLib_DelayUs(CY_CAPSENSE_EXT_CAP_DISCHARGE_TIME); + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdEn) + { + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCmod, + (uint32_t)context->ptrCommonConfig->pinCmod, cmodPcReg, cmodHsiomReg); + + if((CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdShieldEn) && + (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csdCTankShieldEn)) + { + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCsh, + (uint32_t)context->ptrCommonConfig->pinCsh, cshPcReg, cshHsiomReg); + } + } + + if (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->csxEn) + { + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCintA, + (uint32_t)context->ptrCommonConfig->pinCintA, cintAPcReg, cintAHsiomReg); + + Cy_CapSense_SsConfigPinRegisters(context->ptrCommonConfig->portCintB, + (uint32_t)context->ptrCommonConfig->pinCintB, cintBPcReg, cintBHsiomReg); + } +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitActivePtr +****************************************************************************//** +* +* Initializes active scan sensor structure with all available +* pointers for further faster access to widget/sensor parameters. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitActivePtr( + uint32_t widgetId, + uint32_t sensorId, + cy_stc_capsense_context_t * context) +{ + Cy_CapSense_InitActivePtrWd(widgetId, context); + Cy_CapSense_InitActivePtrSns(sensorId, context); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_InitActivePtrSns +****************************************************************************//** +* +* Initializes active scan sensor structure with pointers to sensor +* for further faster access to widget/sensor parameters. +* +* This function supposes that the Cy_CapSense_InitActivePtrWd() function +* is called before. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitActivePtrSns( + uint32_t sensorId, + cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + uint32_t numberRows; + uint32_t numberCols; + + ptrActive->mfsChannelIndex = 0u; + switch(context->ptrActiveScanSns->currentSenseMethod) + { + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E: + ptrActive->sensorIndex = (uint16_t)sensorId; + ptrActive->ptrEltdConfig = &ptrActive->ptrWdConfig->ptrEltdConfig[sensorId]; + ptrActive->ptrSnsContext = &ptrActive->ptrWdConfig->ptrSnsContext[sensorId]; + ptrActive->connectedSnsState = CY_CAPSENSE_SNS_DISCONNECTED; + break; + case (uint8_t)CY_CAPSENSE_SENSE_METHOD_CSX_E: + ptrActive->sensorIndex = (uint16_t)sensorId; + ptrActive->ptrSnsContext = &ptrActive->ptrWdConfig->ptrSnsContext[sensorId]; + ptrActive->connectedSnsState = CY_CAPSENSE_SNS_DISCONNECTED; + + numberRows = ptrActive->ptrWdConfig->numRows; + numberCols = ptrActive->ptrWdConfig->numCols; + ptrActive->rxIndex = (uint8_t)numberCols; + ptrActive->txIndex = (uint8_t)numberRows; + ptrActive->ptrRxConfig = &ptrActive->ptrWdConfig->ptrEltdConfig[sensorId / numberRows]; + ptrActive->ptrTxConfig = &ptrActive->ptrWdConfig->ptrEltdConfig[numberCols + (sensorId % numberRows)]; + + break; + default: + break; + } +} + +/******************************************************************************* +* Function Name: Cy_CapSense_InitActivePtrWd +****************************************************************************//** +* +* Initializes active scan sensor structure with pointers to current widget +* for further faster access to widget/sensor parameters. +* +* This function does not update pointers to current sensor and the +* Cy_CapSense_InitActivePtrSns() function should be called after current one. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_InitActivePtrWd( + uint32_t widgetId, + cy_stc_capsense_context_t * context) +{ + cy_stc_active_scan_sns_t * ptrActive = context->ptrActiveScanSns; + + ptrActive->widgetIndex = (uint8_t)widgetId; + ptrActive->ptrWdConfig = &context->ptrWdConfig[widgetId]; + ptrActive->ptrWdContext = ptrActive->ptrWdConfig->ptrWdContext; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsConfigPinRegisters +****************************************************************************//** +* +* Configures drive mode and HSIOM state of a desired pin. The action +* is performed inside the critical section. +* +* \param base +* The pointer to the pin's port register base address. +* +* \param pinNum +* Position of the pin bit-field within the port register. +* +* \param dm +* Specifies drive mode of the pin. +* +* \param hsiom +* Specifies HSIOM state of the pin. +* +*******************************************************************************/ +void Cy_CapSense_SsConfigPinRegisters( + GPIO_PRT_Type * base, + uint32_t pinNum, + uint32_t dm, + en_hsiom_sel_t hsiom) +{ + uint32_t interruptState = Cy_SysLib_EnterCriticalSection(); + Cy_GPIO_SetDrivemode(base, pinNum, dm); + Cy_GPIO_SetHSIOM(base, pinNum, hsiom); + Cy_SysLib_ExitCriticalSection(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SsReadPinRegisters +****************************************************************************//** +* +* Reads drive mode and HSIOM registers of the specified pin. +* +* \param base +* The pointer to the pin's port register base address. +* +* \param pinNum +* Position of the pin bit-field within the port register. +* +* \param dm +* The pointer to the drive mode variable. +* +* \param hsiom +* The pointer to the HSIOM variable. +* +* +*******************************************************************************/ +void Cy_CapSense_SsReadPinRegisters(GPIO_PRT_Type * base, uint32_t pinNum, uint32_t * dm, en_hsiom_sel_t * hsiom) +{ + uint32_t interruptState = Cy_SysLib_EnterCriticalSection(); + *dm = Cy_GPIO_GetDrivemode(base, pinNum); + *hsiom = Cy_GPIO_GetHSIOM(base, pinNum); + Cy_SysLib_ExitCriticalSection(interruptState); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_SetClkDivider +****************************************************************************//** +* +* Sets the modulator clock and then starts it. +* +* Do not call this function directly from the application program. +* +* \param dividerValue +* The divider value for the modulator clock. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +void Cy_CapSense_SetClkDivider( + uint32_t dividerValue, + const cy_stc_capsense_context_t * context) +{ + uint32_t dividerIndex = (uint32_t)context->ptrCommonConfig->periDividerIndex; + cy_en_divider_types_t dividerType = (cy_en_divider_types_t)context->ptrCommonConfig->periDividerType; + + (void)Cy_SysClk_PeriphDisableDivider(dividerType, dividerIndex); + if ((CY_SYSCLK_DIV_8_BIT == dividerType) || (CY_SYSCLK_DIV_16_BIT == dividerType)) + { + (void)Cy_SysClk_PeriphSetDivider(dividerType, dividerIndex, dividerValue); + } + else + { + (void)Cy_SysClk_PeriphSetFracDivider(dividerType, dividerIndex, dividerValue, 0u); + } + (void)Cy_SysClk_PeriphEnableDivider(dividerType, dividerIndex); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_WatchdogCyclesNum +****************************************************************************//** +* +* Converts the specified time into number of CPU cycles. +* +* \param desiredTimeUs +* The time (delay) specified in us. +* +* \param cpuFreqMHz +* The CPU frequency in MHz. +* +* \param cyclesPerLoop +* The number of cycles per a loop. +* +*******************************************************************************/ +uint32_t Cy_CapSense_WatchdogCyclesNum( + uint32_t desiredTimeUs, + uint32_t cpuFreqMHz, + uint32_t cyclesPerLoop) +{ + uint32_t retVal; + + if(0uL != cyclesPerLoop) + { + retVal = (desiredTimeUs * cpuFreqMHz) / cyclesPerLoop; + } + else + { + retVal = 0xFFFFFFFFuL; + } + + return(retVal); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalibrateCheck +****************************************************************************//** +* +* Verifies that the calibrated widget meets the configured conditions. +* +* This function checks whether the raw count of each sensor of the specified widget +* is within the raw count range defined by raw count target and +/- calibration +* error. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param target +* The raw count target in percentage. +* +* \param senseMethod +* The widget sensing method. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +*******************************************************************************/ +cy_status Cy_CapSense_CalibrateCheck( + uint32_t widgetId, + uint32_t target, + uint32_t senseMethod, + const cy_stc_capsense_context_t * context) +{ + cy_status calibrateStatus = CY_RET_SUCCESS; + uint32_t rawcount; + uint32_t snsIndex; + uint32_t upperLimit; + uint32_t lowerLimit; + uint8_t freqChIndex; + uint8_t freqChNumber; + uint8_t calibrationError; + const cy_stc_capsense_widget_config_t * ptrWdCfg = &context->ptrWdConfig[widgetId]; + cy_stc_capsense_sensor_context_t * ptrChCxt = ptrWdCfg->ptrSnsContext; + cy_stc_capsense_sensor_context_t * ptrSnsCxt; + + /* Calculate acceptable raw count range based on the resolution, target and error */ + if((uint8_t)CY_CAPSENSE_SENSE_METHOD_CSD_E == senseMethod) + { + rawcount = (1uL << context->ptrWdContext[widgetId].resolution) - 1u; + calibrationError = context->ptrCommonConfig->csdCalibrationError; + } + else + { + rawcount = context->ptrWdContext[widgetId].maxRawCount; + calibrationError = context->ptrCommonConfig->csxCalibrationError; + } + + lowerLimit = 0u; + + if (target > calibrationError) + { + lowerLimit = target - calibrationError; + } + upperLimit = target + calibrationError; + if (upperLimit > CY_CAPSENSE_PERCENTAGE_100) + { + upperLimit = CY_CAPSENSE_PERCENTAGE_100; + } + lowerLimit = (rawcount * lowerLimit) / CY_CAPSENSE_PERCENTAGE_100; + upperLimit = (rawcount * upperLimit) / CY_CAPSENSE_PERCENTAGE_100; + + freqChNumber = (CY_CAPSENSE_ENABLE == context->ptrCommonConfig->mfsEn) ? 3u : 1u; + + /* Check whether rawcount is in the defined range */ + for (freqChIndex = 0u; freqChIndex < freqChNumber; freqChIndex++) + { + ptrSnsCxt = ptrChCxt; + for(snsIndex = 0u; snsIndex < ptrWdCfg->numSns; snsIndex++) + { + rawcount = ptrSnsCxt->raw; + if ((rawcount < lowerLimit) || (rawcount > upperLimit)) + { + calibrateStatus = CYRET_BAD_DATA; + break; + } + ptrSnsCxt++; + } + ptrChCxt += context->ptrCommonConfig->numSns; + } + + return (calibrateStatus); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_GetVrefAutoMv +****************************************************************************//** +* +* Finds the optimal Vref value based on the VDDA voltage. +* +* \param vddaMv +* Device VDDA voltage. +* +*******************************************************************************/ +uint32_t Cy_CapSense_GetVrefAutoMv(uint32_t vddaMv) +{ + uint32_t vrefHighVoltageMv; + + if(vddaMv >= 2750u) + { + /* + * The recommended VrefHigh Voltage for the VDDA >= 2.75V. + */ + vrefHighVoltageMv = 2133u; + } + else if(vddaMv >= 2200u) + { + /* + * The recommended VrefHigh Voltage for the 2.2V - 2.75V VDDA range. + */ + vrefHighVoltageMv = 1600u; + } + else if(vddaMv >= 1800u) + { + /* + * The recommended VrefHigh Voltage for the 1.8V - 2.20V VDDA range. + */ + vrefHighVoltageMv = 1164u; + } + else + { + /* + * The recommended VrefHigh Voltage for the VDDA < 1.80V. + */ + vrefHighVoltageMv = 800u; + } + + return(vrefHighVoltageMv); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_GetVrefHighGain +****************************************************************************//** +* +* Calculates the VrefHigh Gain, based on the values of the device VDDA voltage, +* the Vref source voltage, and the desired VrefHigh voltage. +* +* \param vddaMv +* Device VDDA voltage. +* +* \param vrefInputMv +* Vref source voltage. +* +* \param vrefDesiredMv +* Desired VrefHigh voltage. +* +* \return +* Returns the lowest Gain code required to produce the VrefHigh voltage, +* when the VrefHigh is close to the desired voltage (passed through the +* vrefDesiredMv parameter) but not greater than the desired voltage. +* +*******************************************************************************/ +uint32_t Cy_CapSense_GetVrefHighGain(uint32_t vddaMv, uint32_t vrefInputMv, uint32_t vrefDesiredMv) +{ + uint32_t vferhiGain; + + if(vrefDesiredMv > (vddaMv - CY_CAPSENSE_VREF_VDDA_MIN_DIFF)) + { + vrefDesiredMv = (vddaMv - CY_CAPSENSE_VREF_VDDA_MIN_DIFF); + } + + vferhiGain = ((CY_CAPSENSE_VREF_GAIN_MAX * vrefInputMv) - 1u) / (vrefDesiredMv + 1u); + + if (vferhiGain > (uint32_t)(CY_CAPSENSE_VREF_GAIN_MAX - 1u)) + { + vferhiGain = (uint32_t)CY_CAPSENSE_VREF_GAIN_MAX - 1u; + } + + return (vferhiGain); +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_GetVrefhiAutoMv +****************************************************************************//** +* +* Calculates the VrefHigh voltage, based on the Gain code and the Vref source +* voltage. +* +* \param vrefInputMv +* Vref source voltage. +* +* \param vrefGain +* The Gain code. +* +* \return +* Returns the VrefHigh voltage in mV, to be produced for the specified vref Gain +* code and Vref source voltage. +* +*******************************************************************************/ +uint32_t Cy_CapSense_GetVrefHighMv(uint32_t vrefInputMv, uint32_t vrefGain) +{ + uint32_t vrefHighMv; + + vrefHighMv = (CY_CAPSENSE_VREF_GAIN_MAX * vrefInputMv) + ((vrefGain + 1u) >> 1u); + vrefHighMv /= (vrefGain + 1u); + + return (vrefHighMv); +} + +/* [] END OF FILE */ diff --git a/cy_capsense_sensing.h b/cy_capsense_sensing.h new file mode 100644 index 0000000..1dbba1d --- /dev/null +++ b/cy_capsense_sensing.h @@ -0,0 +1,583 @@ +/***************************************************************************//** +* \file cy_capsense_sensing.h +* \version 1.1 +* +* \brief +* This file provides the function prototypes specific to the sensing module. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_SENSING_H) +#define CY_CAPSENSE_SENSING_H + +#include "cy_gpio.h" +#include "cy_syslib.h" +#include "cy_sysclk.h" +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_high_level *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_SetupWidget(uint32_t widgetId, cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_Scan(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_ScanAllWidgets(cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_IsBusy(const cy_stc_capsense_context_t * context); +void Cy_CapSense_InterruptHandler(const CSD_Type * base, cy_stc_capsense_context_t * context); + +/** \} */ + +/******************************************************************************/ +/** \addtogroup group_capsense_low_level *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_SetupWidgetExt( + uint32_t widgetId, + uint32_t sensorId, + cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_ScanExt(cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_CalibrateWidget(uint32_t widgetId, cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_CalibrateAllWidgets(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_CalibrateAllCsdWidgets(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_CalibrateAllCsxWidgets(cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_SetPinState( + uint32_t widgetId, + uint32_t sensorElement, + uint32_t state, + cy_stc_capsense_context_t * context); + +/** \} */ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_SetBusyFlags(cy_stc_capsense_context_t * context); +void Cy_CapSense_ClrBusyFlags(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_SsInitialize(cy_stc_capsense_context_t * context); +void Cy_CapSense_SsPostAllWidgetsScan(cy_stc_capsense_context_t * context); +void Cy_CapSense_SetIOsInDefaultState(const cy_stc_capsense_context_t * context); +void Cy_CapSense_SetSpecificIOsInDefaultState(const cy_stc_capsense_context_t * context); + + +void Cy_CapSense_SwitchSensingMode(uint8_t mode, cy_stc_capsense_context_t * context); + +cy_status Cy_CapSense_SsAutoTune(cy_stc_capsense_context_t * context); +cy_status Cy_CapSense_SsAutoTuneWidget(uint32_t widgetId, cy_stc_capsense_context_t * context); + +void Cy_CapSense_InitializeSourceSenseClk(const cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_SsCalcLfsrSize(uint32_t clkDivider, uint32_t conversionsNum); + +void Cy_CapSense_DischargeExtCapacitors(cy_stc_capsense_context_t * context); + +void Cy_CapSense_InitActivePtrSns(uint32_t sensorId, cy_stc_capsense_context_t * context); +void Cy_CapSense_InitActivePtrWd(uint32_t widgetId, cy_stc_capsense_context_t * context); +void Cy_CapSense_InitActivePtr(uint32_t widgetId, uint32_t sensorId, cy_stc_capsense_context_t * context); + +void Cy_CapSense_SsConfigPinRegisters(GPIO_PRT_Type * base, uint32_t pinNum, uint32_t dm, en_hsiom_sel_t hsiom); +void Cy_CapSense_SsReadPinRegisters(GPIO_PRT_Type * base, uint32_t pinNum, uint32_t *dm, en_hsiom_sel_t *hsiom); + +void Cy_CapSense_SetClkDivider(uint32_t dividerValue, const cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_WatchdogCyclesNum(uint32_t desiredTimeUs, uint32_t cpuFreqMHz, uint32_t cyclesPerLoop); + +cy_status Cy_CapSense_CalibrateCheck(uint32_t widgetId, uint32_t target, uint32_t senseMethod, + const cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_GetVrefAutoMv(uint32_t vddaMv); +uint32_t Cy_CapSense_GetVrefHighGain(uint32_t vddaMv, uint32_t vrefInputMv, uint32_t vrefDesiredMv); +uint32_t Cy_CapSense_GetVrefHighMv(uint32_t vrefInputMv, uint32_t vrefGain); +cy_status Cy_CapSense_InternalPreCalculation(cy_stc_capsense_context_t * context); + +/** \} \endcond */ + + +/******************************************************************************* +* Local definition +*******************************************************************************/ + +/* + * Definition of the default configuration of the CSD HW registers that is + * intended to be used on the CSD HW block capturing stage. + * The configuration includes: + * 1. Start of the analog settling process: + * - Enables the CSD HW block; + * - Enables all the modules of the CSD HW block (AMBUF, REFGEN, CSDCMP, HSCMP); + * - Enables the Sense Modulator output; + * 2. Clear all of the pending interrupt requests of the CSD HW block (SAMPLE, INIT, ADC_RES); + * 3. Sets into default state the rest of the CSD HW block registers which are not related + * to actions #1 and #2. +*/ +#define CY_CAPSENSE_CSD_CONFIG_DEFAULT {\ + .config = 0x84001000uL, /* ENABLE = "1", SENSE_EN = "1". Set other fields into default state. */\ + .spare = 0x00000000uL, /* Set all fields into default state. */ \ + .status = 0x00000000uL, /* Set all fields into default state. */ \ + .statSeq = 0x00000000uL, /* Set all fields into default state. */ \ + .statCnts = 0x00000000uL, /* Set all fields into default state. */ \ + .statHcnt = 0x00000000uL, /* Set all fields into default state. */ \ + .resultVal1 = 0x00000000uL, /* Set all fields into default state. */ \ + .resultVal2 = 0x00000000uL, /* Set all fields into default state. */ \ + .adcRes = 0x00000000uL, /* Set all fields into default state. */ \ + .intr = 0x00000106uL, /* SAMPLE = "1", INIT = "1", ADC_RES = "1". */ \ + .intrSet = 0x00000000uL, /* Set all fields into default state. */ \ + .intrMask = 0x00000000uL, /* Set all fields into default state. */ \ + .intrMasked = 0x00000000uL, /* Set all fields into default state. */ \ + .hscmp = 0x00000001uL, /* HSCMP_EN = "1". Set all other fields into default state. */ \ + .ambuf = 0x00000001uL, /* PWR_MODE = "1". Set all other fields into default state. */ \ + .refgen = 0x00000001uL, /* REFGEN_EN = "1". Set all other fields into default state. */ \ + .csdCmp = 0x00000001uL, /* CSDCMP_EN = "1". Set all other fields into default state. */ \ + .swRes = 0x00000000uL, /* Set all fields into default state. */ \ + .sensePeriod = 0x0C000000uL, /* Set all fields into default state. */ \ + .senseDuty = 0x00000000uL, /* Set all fields into default state. */ \ + .swHsPosSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swHsNegSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swShieldSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swAmuxbufSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swBypSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swCmpPosSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swCmpNegSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swRefgenSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swFwModSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swFwTankSel = 0x00000000uL, /* Set all fields into default state. */ \ + .swDsiSel = 0x00000000uL, /* Set all fields into default state. */ \ + .ioSel = 0x00000000uL, /* Set all fields into default state. */ \ + .seqTime = 0x00000000uL, /* Set all fields into default state. */ \ + .seqInitCnt = 0x00000000uL, /* Set all fields into default state. */ \ + .seqNormCnt = 0x00000000uL, /* Set all fields into default state. */ \ + .adcCtl = 0x00000000uL, /* Set all fields into default state. */ \ + .seqStart = 0x00000000uL, /* Set all fields into default state. */ \ + .idacA = 0x00000000uL, /* Set all fields into default state. */ \ + .idacB = 0x00000000uL, /* Set all fields into default state. */ \ + } + +extern const cy_stc_csd_config_t cy_capsense_csdCfg; + + +/******************************************************************************* +* CSD HW Waveform Selection values +*******************************************************************************/ +#define CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN (0x00000000uL) +#define CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED (0x00000001uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI1 (0x00000002uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI2 (0x00000003uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI1_HSCMP (0x00000004uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI2_HSCMP (0x00000005uL) +#define CY_CAPSENSE_CSD_WAVEFORM_HSCMP (0x00000006uL) +#define CY_CAPSENSE_CSD_WAVEFORM_SENSE_INV (0x00000007uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI1_DELAY (0x00000008uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI2_DELAY (0x00000009uL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI1_INV (0x0000000AuL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI2_INV (0x0000000BuL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI1_HSCMP_INV (0x0000000CuL) +#define CY_CAPSENSE_CSD_WAVEFORM_PHI2_HSCMP_INV (0x0000000DuL) +#define CY_CAPSENSE_CSD_WAVEFORM_HSCMP_INV (0x0000000EuL) +#define CY_CAPSENSE_CSD_WAVEFORM_SENSE (0x0000000FuL) + + +/******************************************************************************* +* CSD HW Block Register Mask Definition +*******************************************************************************/ + +/* CSD_CONFIG register masks */ +#define CY_CAPSENSE_CSD_CONFIG_IREF_SEL_MSK (CSD_CONFIG_IREF_SEL_Msk) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_2_CYCLES (0x00000002uL) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_3_CYCLES (0x00000003uL) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_4_CYCLES (0x00000004uL) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_POS (CSD_CONFIG_FILTER_DELAY_Pos) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_MSK (CSD_CONFIG_FILTER_DELAY_Msk) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_12MHZ (CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_2_CYCLES << CSD_CONFIG_FILTER_DELAY_Pos) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_24MHZ (CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_3_CYCLES << CSD_CONFIG_FILTER_DELAY_Pos) +#define CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_48MHZ (CY_CAPSENSE_CSD_CONFIG_FILTER_DELAY_4_CYCLES << CSD_CONFIG_FILTER_DELAY_Pos) +#define CY_CAPSENSE_CSD_CONFIG_SHIELD_DELAY_MSK (CSD_CONFIG_SHIELD_DELAY_Msk) +#define CY_CAPSENSE_CSD_CONFIG_SHIELD_DELAY_POS (CSD_CONFIG_SHIELD_DELAY_Pos) +#define CY_CAPSENSE_CSD_CONFIG_SENSE_EN_MSK (CSD_CONFIG_SENSE_EN_Msk) +#define CY_CAPSENSE_CSD_CONFIG_DSI_COUNT_SEL_POS (CSD_CONFIG_DSI_COUNT_SEL_Pos) +#define CY_CAPSENSE_CSD_CONFIG_DSI_COUNT_SEL_MSK (CSD_CONFIG_DSI_COUNT_SEL_Msk) +#define CY_CAPSENSE_CSD_CONFIG_SAMPLE_SYNC_MSK (CSD_CONFIG_SAMPLE_SYNC_Msk) +#define CY_CAPSENSE_CSD_CONFIG_ENABLE_MSK (CSD_CONFIG_ENABLE_Msk) + +/* CSD_STAT_SEQ register masks */ +#define CY_CAPSENSE_CSD_STAT_SEQ_SEQ_STATE_MSK (CSD_STAT_SEQ_SEQ_STATE_Msk) + +/* CSD_RESULT_VAL1 register masks */ +#define CY_CAPSENSE_CSD_RESULT_VAL1_VALUE_MSK (CSD_RESULT_VAL1_VALUE_Msk) +#define CY_CAPSENSE_CSD_RESULT_VAL1_BAD_CONVS_MSK (CSD_RESULT_VAL1_BAD_CONVS_Msk) +#define CY_CAPSENSE_CSD_RESULT_VAL1_BAD_CONVS_POS (CSD_RESULT_VAL1_BAD_CONVS_Pos) + +/* CSD_RESULT_VAL2 register masks */ +#define CY_CAPSENSE_CSD_RESULT_VAL2_VALUE_MSK (CSD_RESULT_VAL2_VALUE_Msk) + +/* CSD_INTR register masks */ +#define CY_CAPSENSE_CSD_INTR_SAMPLE_MSK (CSD_INTR_SAMPLE_Msk) +#define CY_CAPSENSE_CSD_INTR_INIT_MSK (CSD_INTR_INIT_Msk) +#define CY_CAPSENSE_CSD_INTR_ADC_RES_MSK (CSD_INTR_ADC_RES_Msk) +#define CY_CAPSENSE_CSD_INTR_ALL_MSK (CSD_INTR_SAMPLE_Msk | CSD_INTR_INIT_Msk | CSD_INTR_ADC_RES_Msk) + +/* CSD_INTR_MASK register masks */ +#define CY_CAPSENSE_CSD_INTR_MASK_SAMPLE_MSK (CSD_INTR_MASK_SAMPLE_Msk) +#define CY_CAPSENSE_CSD_INTR_MASK_INIT_MSK (CSD_INTR_MASK_INIT_Msk) +#define CY_CAPSENSE_CSD_INTR_MASK_ADC_RES_MSK (CSD_INTR_MASK_ADC_RES_Msk) +#define CY_CAPSENSE_CSD_INTR_MASK_CLEAR_MSK (0uL) + +/* CSD_HSCMP register masks */ +#define CY_CAPSENSE_CSD_HSCMP_HSCMP_EN_MSK (CSD_HSCMP_HSCMP_EN_Msk) +#define CY_CAPSENSE_CSD_HSCMP_HSCMP_INVERT_MSK (CSD_HSCMP_HSCMP_INVERT_Msk) +#define CY_CAPSENSE_CSD_HSCMP_AZ_EN_MSK (CSD_HSCMP_AZ_EN_Msk) + +/* CSD_AMBUF register masks */ +#define CY_CAPSENSE_CSD_AMBUF_PWR_MODE_OFF (0uL) +#define CY_CAPSENSE_CSD_AMBUF_PWR_MODE_NORM (1uL) +#define CY_CAPSENSE_CSD_AMBUF_PWR_MODE_HI (2uL) + +/* CSD_REFGEN register masks */ +#define CY_CAPSENSE_CSD_REFGEN_REFGEN_EN_MSK (CSD_REFGEN_REFGEN_EN_Msk) +#define CY_CAPSENSE_CSD_REFGEN_BYPASS_MSK (CSD_REFGEN_BYPASS_Msk) +#define CY_CAPSENSE_CSD_REFGEN_VDDA_EN_MSK (CSD_REFGEN_VDDA_EN_Msk) +#define CY_CAPSENSE_CSD_REFGEN_RES_EN_MSK (CSD_REFGEN_RES_EN_Msk) +#define CY_CAPSENSE_CSD_REFGEN_GAIN_POS (CSD_REFGEN_GAIN_Pos) +#define CY_CAPSENSE_CSD_REFGEN_GAIN_MSK (CSD_REFGEN_GAIN_Msk) +#define CY_CAPSENSE_CSD_REFGEN_VREFLO_SEL_MSK (CSD_REFGEN_VREFLO_SEL_Msk) +#define CY_CAPSENSE_CSD_REFGEN_VREFLO_INT_MSK (CSD_REFGEN_VREFLO_INT_Msk) + +#define CY_CAPSENSE_VREF_HI_OVERSHOOT_CORRECTION (0x00000001uL) + +/* CSD_CSDCMP register masks */ +#define CY_CAPSENSE_CSD_CSDCMP_CSDCMP_DISABLED (0uL) +#define CY_CAPSENSE_CSD_CSDCMP_CSDCMP_EN_MSK (CSD_CSDCMP_CSDCMP_EN_Msk) +#define CY_CAPSENSE_CSD_CSDCMP_CMP_PHASE_FULL (0uL << CSD_CSDCMP_CMP_PHASE_Pos) +#define CY_CAPSENSE_CSD_CSDCMP_CMP_PHASE_PHI1 (1uL << CSD_CSDCMP_CMP_PHASE_Pos) +#define CY_CAPSENSE_CSD_CSDCMP_CMP_PHASE_PHI2 (2uL << CSD_CSDCMP_CMP_PHASE_Pos) +#define CY_CAPSENSE_CSD_CSDCMP_CMP_PHASE_PHI1_2 (3uL << CSD_CSDCMP_CMP_PHASE_Pos) +#define CY_CAPSENSE_CSD_CSDCMP_AZ_EN_MSK (CSD_CSDCMP_AZ_EN_Msk) + +/* CSD_SENSE_PERIOD register masks */ +#define CY_CAPSENSE_CSD_SENSE_PERIOD_SENSE_DIV_MSK (CSD_SENSE_PERIOD_SENSE_DIV_Msk) +#define CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SIZE_MSK (CSD_SENSE_PERIOD_LFSR_SIZE_Msk) +#define CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SIZE_POS (CSD_SENSE_PERIOD_LFSR_SIZE_Pos) +#define CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_SCALE_MSK (CSD_SENSE_PERIOD_LFSR_SCALE_Msk) +#define CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_CLEAR_MSK (CSD_SENSE_PERIOD_LFSR_CLEAR_Msk) +#define CY_CAPSENSE_CSD_SENSE_PERIOD_SEL_LFSR_MSB_MSK (CSD_SENSE_PERIOD_SEL_LFSR_MSB_Msk) +#define CY_CAPSENSE_CSD_SENSE_PERIOD_LFSR_BITS_MSK (CSD_SENSE_PERIOD_LFSR_BITS_Msk) + +/* CSD_SENSE_DUTY register masks */ +#define CY_CAPSENSE_CSD_SENSE_DUTY_SENSE_WIDTH_MSK (CSD_SENSE_DUTY_SENSE_WIDTH_Msk) +#define CY_CAPSENSE_CSD_SENSE_DUTY_SENSE_POL_MSK (CSD_SENSE_DUTY_SENSE_POL_Msk) +#define CY_CAPSENSE_CSD_SENSE_DUTY_SENSE_POL_PHI_LOW (0uL) +#define CY_CAPSENSE_CSD_SENSE_DUTY_SENSE_POL_PHI_HIGH (CSD_SENSE_DUTY_SENSE_POL_Msk) +#define CY_CAPSENSE_CSD_SENSE_DUTY_OVERLAP_PHI1_MSK (CSD_SENSE_DUTY_OVERLAP_PHI1_Msk) +#define CY_CAPSENSE_CSD_SENSE_DUTY_OVERLAP_PHI2_MSK (CSD_SENSE_DUTY_OVERLAP_PHI2_Msk) + +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPM_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_P_SEL_SW_HMPM_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPM_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_P_SEL_SW_HMPM_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPT_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_P_SEL_SW_HMPT_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPT_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_P_SEL_SW_HMPT_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPS_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_P_SEL_SW_HMPS_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMPS_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_P_SEL_SW_HMPS_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMMA_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_P_SEL_SW_HMMA_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMMA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_P_SEL_SW_HMMA_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMMB_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_P_SEL_SW_HMMB_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMMB_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_P_SEL_SW_HMMB_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMRH_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_P_SEL_SW_HMRH_Pos) +#define CY_CAPSENSE_CSD_SW_HS_P_SEL_SW_HMRH_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_P_SEL_SW_HMRH_Pos) + +#define CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCRH_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_N_SEL_SW_HCRH_Pos) +#define CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCRH_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_N_SEL_SW_HCRH_Pos) +#define CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCRL_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_N_SEL_SW_HCRL_Pos) +#define CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCRL_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_N_SEL_SW_HCRL_Pos) +#define CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCCD_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_HS_N_SEL_SW_HCCD_Pos) +#define CY_CAPSENSE_CSD_SW_HS_N_SEL_SW_HCCD_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_HS_N_SEL_SW_HCCD_Pos) + +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_HSCMP << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_PHI1 (CY_CAPSENSE_CSD_WAVEFORM_PHI1 << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_PHI1_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI1_HSCMP << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_PHI2_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI2_HSCMP << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAV_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_SHIELD_SEL_SW_HCAV_Pos) + +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_HSCMP << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_PHI1 (CY_CAPSENSE_CSD_WAVEFORM_PHI1 << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_PHI1_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI1_HSCMP << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_PHI2_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI2_HSCMP << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCAG_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_SHIELD_SEL_SW_HCAG_Pos) + +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_HSCMP << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_PHI1 (CY_CAPSENSE_CSD_WAVEFORM_PHI1 << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_PHI1_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI1_HSCMP << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_PHI2_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI2_HSCMP << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBV_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_SHIELD_SEL_SW_HCBV_Pos) + +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_HSCMP << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_PHI1 (CY_CAPSENSE_CSD_WAVEFORM_PHI1 << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_PHI1_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI1_HSCMP << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_PHI2_HSCMP (CY_CAPSENSE_CSD_WAVEFORM_PHI2_HSCMP << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) +#define CY_CAPSENSE_CSD_SW_SHIELD_SEL_SW_HCBG_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_SHIELD_SEL_SW_HCBG_Pos) + +#define CY_CAPSENSE_CSD_SW_AMUXBUF_SEL_SW_IRLB_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_AMUXBUF_SEL_SW_IRLB_Pos) +#define CY_CAPSENSE_CSD_SW_AMUXBUF_SEL_SW_IRH_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_AMUXBUF_SEL_SW_IRH_Pos) +#define CY_CAPSENSE_CSD_SW_AMUXBUF_SEL_SW_ICB_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_AMUXBUF_SEL_SW_ICB_Pos) +#define CY_CAPSENSE_CSD_SW_AMUXBUF_SEL_SW_DEFAULT (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN) + +/* CSD_SW_BYP_SEL register masks */ +#define CY_CAPSENSE_CSD_SW_BYP_SEL_SW_BYA_MSK (CSD_SW_BYP_SEL_SW_BYA_Msk) +#define CY_CAPSENSE_CSD_SW_BYP_SEL_SW_BYB_MSK (CSD_SW_BYP_SEL_SW_BYB_Msk) + +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPM_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_P_SEL_SW_SFPM_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPM_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_P_SEL_SW_SFPM_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPT_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_P_SEL_SW_SFPT_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPT_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_P_SEL_SW_SFPT_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPS_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_P_SEL_SW_SFPS_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFPS_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_P_SEL_SW_SFPS_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFMA_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_P_SEL_SW_SFMA_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFMA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_P_SEL_SW_SFMA_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFCA_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_P_SEL_SW_SFCA_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFCA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_P_SEL_SW_SFCA_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_P_SEL_SW_SFCA_MSK (CSD_SW_CMP_P_SEL_SW_SFCA_Msk) + +#define CY_CAPSENSE_CSD_SW_CMP_N_SEL_SW_SCRH_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_N_SEL_SW_SCRH_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_N_SEL_SW_SCRH_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_N_SEL_SW_SCRH_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_N_SEL_SW_SCRL_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_SW_CMP_N_SEL_SW_SCRL_Pos) +#define CY_CAPSENSE_CSD_SW_CMP_N_SEL_SW_SCRL_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_CMP_N_SEL_SW_SCRL_Pos) + +/* CSD_SW_REFGEN_SEL register masks */ +#define CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_IAIB_MSK (CSD_SW_REFGEN_SEL_SW_IAIB_Msk) +#define CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_IBCB_MSK (CSD_SW_REFGEN_SEL_SW_IBCB_Msk) +#define CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_SGMB_MSK (CSD_SW_REFGEN_SEL_SW_SGMB_Msk) +#define CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_SGRP_MSK (CSD_SW_REFGEN_SEL_SW_SGRP_Msk) +#define CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_SGRE_MSK (CSD_SW_REFGEN_SEL_SW_SGRE_Msk) +#define CY_CAPSENSE_CSD_SW_REFGEN_SEL_SW_SGR_MSK (CSD_SW_REFGEN_SEL_SW_SGR_Msk) + +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1PM_MSK (CSD_SW_FW_MOD_SEL_SW_F1PM_Msk) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1PM_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_F1PM_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1MA_MSK (CSD_SW_FW_MOD_SEL_SW_F1MA_Msk) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1MA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_F1MA_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1CA_MSK (CSD_SW_FW_MOD_SEL_SW_F1CA_Msk) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1CA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_F1CA_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_F1CA_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_FW_MOD_SEL_SW_F1CA_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_C1CC_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_C1CC_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_C1CC_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_C1CC_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_C1CD_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_C1CD_Pos) +#define CY_CAPSENSE_CSD_SW_FW_MOD_SEL_SW_C1CD_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_MOD_SEL_SW_C1CD_Pos) + +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2PT_MSK (CSD_SW_FW_TANK_SEL_SW_F2PT_Msk) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2PT_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_F2PT_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2MA_MSK (CSD_SW_FW_TANK_SEL_SW_F2MA_Msk) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2MA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_F2MA_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CA_MSK (CSD_SW_FW_TANK_SEL_SW_F2CA_Msk) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CA_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_F2CA_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CB_MSK (CSD_SW_FW_TANK_SEL_SW_F2CB_Msk) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CB_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_F2CB_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CA_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_FW_TANK_SEL_SW_F2CA_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_F2CB_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_SW_FW_TANK_SEL_SW_F2CB_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_C2CC_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_C2CC_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_C2CC_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_C2CC_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_C2CD_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_C2CD_Pos) +#define CY_CAPSENSE_CSD_SW_FW_TANK_SEL_SW_C2CD_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_SW_FW_TANK_SEL_SW_C2CD_Pos) + +#define CY_CAPSENSE_CSD_TX_OUT_MSK (CSD_IO_SEL_CSD_TX_OUT_Msk) +#define CY_CAPSENSE_CSD_TX_OUT_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_IO_SEL_CSD_TX_OUT_Pos) + +#define CY_CAPSENSE_CSD_TX_OUT_EN_MSK (CSD_IO_SEL_CSD_TX_OUT_EN_Msk) +#define CY_CAPSENSE_CSD_TX_OUT_EN_PHI1_DELAY (CY_CAPSENSE_CSD_WAVEFORM_PHI1_DELAY << 4u) +#define CY_CAPSENSE_CSD_TX_AMUXB_EN_MSK (CSD_IO_SEL_CSD_TX_AMUXB_EN_Msk) +#define CY_CAPSENSE_CSD_TX_AMUXB_EN_PHI2_DELAY (CY_CAPSENSE_CSD_WAVEFORM_PHI2_DELAY << 12u) +#define CY_CAPSENSE_CSD_TX_N_OUT_MSK (CSD_IO_SEL_CSD_TX_N_OUT_Msk) +#define CY_CAPSENSE_CSD_TX_N_OUT_STATIC_OPEN (CY_CAPSENSE_CSD_WAVEFORM_STATIC_OPEN << CSD_IO_SEL_CSD_TX_N_OUT_Pos) +#define CY_CAPSENSE_CSD_TX_N_OUT_STATIC_CLOSE (CY_CAPSENSE_CSD_WAVEFORM_STATIC_CLOSED << CSD_IO_SEL_CSD_TX_N_OUT_Pos) +#define CY_CAPSENSE_CSD_TX_N_OUT_EN_MSK (CSD_IO_SEL_CSD_TX_N_OUT_EN_Msk) +#define CY_CAPSENSE_CSD_TX_N_OUT_EN_PHI1 (CY_CAPSENSE_CSD_WAVEFORM_PHI1 << CSD_IO_SEL_CSD_TX_N_OUT_EN_Pos) +#define CY_CAPSENSE_CSD_TX_N_AMUXA_EN_MSK (CSD_IO_SEL_CSD_TX_N_AMUXA_EN_Msk) +#define CY_CAPSENSE_CSD_TX_N_AMUXA_EN_PHI2 (CY_CAPSENSE_CSD_WAVEFORM_PHI2 << CSD_IO_SEL_CSD_TX_N_AMUXA_EN_Pos) + +/* CSD_SEQ_INIT_CNT register masks */ +#define CY_CAPSENSE_CSD_SEQ_INIT_CNT_CONV_CNT_MSK (CSD_SEQ_INIT_CNT_CONV_CNT_Msk) + +/* CSD_SEQ_NORM_CNT register masks */ +#define CY_CAPSENSE_CSD_SEQ_NORM_CNT_CONV_CNT_MSK (CSD_SEQ_NORM_CNT_CONV_CNT_Msk) + +/* CSD_SEQ_START register masks */ +#define CY_CAPSENSE_CSD_SEQ_START_START_MSK (CSD_SEQ_START_START_Msk) +#define CY_CAPSENSE_CSD_SEQ_START_SEQ_MODE_MSK (CSD_SEQ_START_SEQ_MODE_Msk) +#define CY_CAPSENSE_CSD_SEQ_START_ABORT_MSK (CSD_SEQ_START_ABORT_Msk) +#define CY_CAPSENSE_CSD_SEQ_START_DSI_START_EN_MSK (CSD_SEQ_START_DSI_START_EN_Msk) +#define CY_CAPSENSE_CSD_SEQ_START_AZ0_SKIP_MSK (CSD_SEQ_START_AZ0_SKIP_Msk) +#define CY_CAPSENSE_CSD_SEQ_START_AZ1_SKIP_MSK (CSD_SEQ_START_AZ1_SKIP_Msk) + +#define CY_CAPSENSE_CSD_IDAC_BITS_USED (7u) + +#define CY_CAPSENSE_CAL_MIDDLE_VALUE (1u << (CY_CAPSENSE_CSD_IDAC_BITS_USED - 1u)) +#define CY_CAPSENSE_CAL_IDAC_MAX_VALUE ((uint8_t)(1u << CY_CAPSENSE_CSD_IDAC_BITS_USED) - 1u) + + +/* CSD_IDACA register masks */ +#define CY_CAPSENSE_CSD_IDACA_VAL_MSK (CSD_IDACA_VAL_Msk) +#define CY_CAPSENSE_CSD_IDACA_VAL_POS (CSD_IDACA_VAL_Pos) + +#define CY_CAPSENSE_CSD_IDACA_POL_DYN_MSK (CSD_IDACA_POL_DYN_Msk) +#define CY_CAPSENSE_CSD_IDACA_POL_DYN_POS (CSD_IDACA_POL_DYN_Pos) + +#define CY_CAPSENSE_CSD_IDACA_POLARITY_MSK (CSD_IDACA_POLARITY_Msk) +#define CY_CAPSENSE_CSD_IDACA_POLARITY_POS (CSD_IDACA_POLARITY_Pos) +#define CY_CAPSENSE_CSD_IDACA_POLARITY_VSSA_SRC (0uL) +#define CY_CAPSENSE_CSD_IDACA_POLARITY_VDDA_SNK (1uL) +#define CY_CAPSENSE_CSD_IDACA_POLARITY_SENSE (2uL) +#define CY_CAPSENSE_CSD_IDACA_POLARITY_SENSE_INV (3uL) + +#define CY_CAPSENSE_CSD_IDACA_BALL_MODE_MSK (CSD_IDACA_BAL_MODE_Msk) +#define CY_CAPSENSE_CSD_IDACA_BALL_MODE_POS (CSD_IDACA_BAL_MODE_Pos) +#define CY_CAPSENSE_CSD_IDACA_BALL_MODE_FULL (0uL) +#define CY_CAPSENSE_CSD_IDACA_BALL_MODE_PHI1 (1uL) +#define CY_CAPSENSE_CSD_IDACA_BALL_MODE_PHI2 (2uL) +#define CY_CAPSENSE_CSD_IDACA_BALL_MODE_PHI1_2 (3uL) + +#define CY_CAPSENSE_CSD_IDACA_LEG1_MODE_MSK (CSD_IDACA_LEG1_MODE_Msk) +#define CY_CAPSENSE_CSD_IDACA_LEG1_MODE_POS (CSD_IDACA_LEG1_MODE_Pos) +#define CY_CAPSENSE_CSD_IDACA_LEG1_MODE_GP_STATIC (0uL) +#define CY_CAPSENSE_CSD_IDACA_LEG1_MODE_GP (1uL) +#define CY_CAPSENSE_CSD_IDACA_LEG1_MODE_CSD_STATIC (2uL) +#define CY_CAPSENSE_CSD_IDACA_LEG1_MODE_CSD (3uL) + +#define CY_CAPSENSE_CSD_IDACA_LEG2_MODE_MSK (CSD_IDACA_LEG2_MODE_Msk) +#define CY_CAPSENSE_CSD_IDACA_LEG2_MODE_POS (CSD_IDACA_LEG2_MODE_Pos) +#define CY_CAPSENSE_CSD_IDACA_LEG2_MODE_GP_STATIC (0uL) +#define CY_CAPSENSE_CSD_IDACA_LEG2_MODE_GP (1uL) +#define CY_CAPSENSE_CSD_IDACA_LEG2_MODE_CSD_STATIC (2uL) +#define CY_CAPSENSE_CSD_IDACA_LEG2_MODE_CSD (3uL) + +#define CY_CAPSENSE_CSD_IDACA_RANGE_MSK (CSD_IDACA_RANGE_Msk) +#define CY_CAPSENSE_CSD_IDACA_RANGE_POS (CSD_IDACA_RANGE_Pos) +#define CY_CAPSENSE_CSD_IDACA_RANGE_IDAC_LO (0uL) +#define CY_CAPSENSE_CSD_IDACA_RANGE_IDAC_MED (1uL) +#define CY_CAPSENSE_CSD_IDACA_RANGE_IDAC_HI (2uL) + +#define CY_CAPSENSE_CSD_IDACA_LEG1_EN_MSK (CSD_IDACA_LEG1_EN_Msk) +#define CY_CAPSENSE_CSD_IDACA_LEG2_EN_MSK (CSD_IDACA_LEG2_EN_Msk) + +/* CSD_IDACB register masks */ +#define CY_CAPSENSE_CSD_IDACB_VAL_MSK (CSD_IDACB_VAL_Msk) +#define CY_CAPSENSE_CSD_IDACB_VAL_POS (CSD_IDACB_VAL_Pos) + +#define CY_CAPSENSE_CSD_IDACB_POL_DYN_MSK (CSD_IDACB_POL_DYN_Msk) +#define CY_CAPSENSE_CSD_IDACB_POL_DYN_POS (CSD_IDACB_POL_DYN_Pos) +#define CY_CAPSENSE_CSD_IDACB_POL_DYN_STATIC (0uL) +#define CY_CAPSENSE_CSD_IDACB_POL_DYN_DYNAMIC (1uL) + +#define CY_CAPSENSE_CSD_IDACB_POLARITY_MSK (CSD_IDACB_POLARITY_Msk) +#define CY_CAPSENSE_CSD_IDACB_POLARITY_POS (CSD_IDACB_POLARITY_Pos) +#define CY_CAPSENSE_CSD_IDACB_POLARITY_VSSA_SRC (0uL) +#define CY_CAPSENSE_CSD_IDACB_POLARITY_VDDA_SNK (1uL) +#define CY_CAPSENSE_CSD_IDACB_POLARITY_SENSE (2uL) +#define CY_CAPSENSE_CSD_IDACB_POLARITY_SENSE_INV (3uL) + +#define CY_CAPSENSE_CSD_IDACB_BALL_MODE_MSK (CSD_IDACB_BAL_MODE_Msk) +#define CY_CAPSENSE_CSD_IDACB_BALL_MODE_POS (CSD_IDACB_BAL_MODE_Pos) +#define CY_CAPSENSE_CSD_IDACB_BALL_MODE_FULL (0uL) +#define CY_CAPSENSE_CSD_IDACB_BALL_MODE_PHI1 (1uL) +#define CY_CAPSENSE_CSD_IDACB_BALL_MODE_PHI2 (2uL) +#define CY_CAPSENSE_CSD_IDACB_BALL_MODE_PHI1_2 (3uL) + +#define CY_CAPSENSE_CSD_IDACB_LEG1_MODE_MSK (CSD_IDACB_LEG1_MODE_Msk) +#define CY_CAPSENSE_CSD_IDACB_LEG1_MODE_POS (CSD_IDACB_LEG1_MODE_Pos) +#define CY_CAPSENSE_CSD_IDACB_LEG1_MODE_GP_STATIC (0uL) +#define CY_CAPSENSE_CSD_IDACB_LEG1_MODE_GP (1uL) +#define CY_CAPSENSE_CSD_IDACB_LEG1_MODE_CSD_STATIC (2uL) +#define CY_CAPSENSE_CSD_IDACB_LEG1_MODE_CSD (3uL) + +#define CY_CAPSENSE_CSD_IDACB_LEG2_MODE_MSK (CSD_IDACB_LEG2_MODE_Msk) +#define CY_CAPSENSE_CSD_IDACB_LEG2_MODE_POS (CSD_IDACB_LEG2_MODE_Pos) +#define CY_CAPSENSE_CSD_IDACB_LEG2_MODE_GP_STATIC (0uL) +#define CY_CAPSENSE_CSD_IDACB_LEG2_MODE_GP (1uL) +#define CY_CAPSENSE_CSD_IDACB_LEG2_MODE_CSD_STATIC (2uL) +#define CY_CAPSENSE_CSD_IDACB_LEG2_MODE_CSD (3uL) + +#define CY_CAPSENSE_CSD_IDACB_RANGE_MSK (CSD_IDACB_RANGE_Msk) +#define CY_CAPSENSE_CSD_IDACB_RANGE_POS (CSD_IDACB_RANGE_Pos) +#define CY_CAPSENSE_CSD_IDACB_RANGE_IDAC_LO (0uL) +#define CY_CAPSENSE_CSD_IDACB_RANGE_IDAC_MED (1uL) +#define CY_CAPSENSE_CSD_IDACB_RANGE_IDAC_HI (2uL) + +#define CY_CAPSENSE_CSD_IDACB_LEG1_EN_MSK (CSD_IDACB_LEG1_EN_Msk) +#define CY_CAPSENSE_CSD_IDACB_LEG2_EN_MSK (CSD_IDACB_LEG2_EN_Msk) +#define CY_CAPSENSE_CSD_IDACB_LEG3_EN_MSK (CSD_IDACB_LEG3_EN_Msk) + +/******************************************************************************* +* PRS & LFSR masks +*******************************************************************************/ +#define CY_CAPSENSE_PRS_LENGTH_8_BITS (0x000000FFuL) +#define CY_CAPSENSE_PRS_LENGTH_12_BITS (0x00000FFFuL) + +#define CY_CAPSENSE_SNSCLK_SSC1_PERIOD (63u) +#define CY_CAPSENSE_SNSCLK_SSC2_PERIOD (127u) +#define CY_CAPSENSE_SNSCLK_SSC3_PERIOD (511u) +#define CY_CAPSENSE_SNSCLK_SSC4_PERIOD (1023u) + +#define CY_CAPSENSE_SNSCLK_LFSR_RANGE (16u) +#define CY_CAPSENSE_LFSR_DITHER_PERCENTAGE (10uL) +#define CY_CAPSENSE_SNSCLK_LFSR_THRESHOLD (CY_CAPSENSE_LFSR_DITHER_PERCENTAGE * CY_CAPSENSE_SNSCLK_LFSR_RANGE) + +/******************************************************************************* +* HSIOM Macros redefinition for readability +*******************************************************************************/ +#define CY_CAPSENSE_HSIOM_SEL_GPIO (HSIOM_SEL_GPIO) +#define CY_CAPSENSE_HSIOM_SEL_CSD_SENSE (HSIOM_SEL_ACT_3) +#define CY_CAPSENSE_HSIOM_SEL_CSD_SHIELD (HSIOM_SEL_ACT_2) +#define CY_CAPSENSE_HSIOM_SEL_AMUXA (HSIOM_SEL_AMUXA) +#define CY_CAPSENSE_HSIOM_SEL_AMUXB (HSIOM_SEL_AMUXB) + +/******************************************************************************* +* Clock Macros +*******************************************************************************/ +#define CY_CAPSENSE_MODCLK_CMD_DIV_SHIFT (0uL) +#define CY_CAPSENSE_MODCLK_CMD_PA_DIV_SHIFT (8uL) +#define CY_CAPSENSE_MODCLK_CMD_DISABLE_SHIFT (30uL) +#define CY_CAPSENSE_MODCLK_CMD_ENABLE_SHIFT (31uL) +#define CY_CAPSENSE_MODCLK_CMD_DISABLE_MASK ((uint32_t)(1uL << CY_CAPSENSE_MODCLK_CMD_DISABLE_SHIFT)) +#define CY_CAPSENSE_MODCLK_CMD_ENABLE_MASK ((uint32_t)(1uL << CY_CAPSENSE_MODCLK_CMD_ENABLE_SHIFT)) + +#define CY_CAPSENSE_MOD_CSD_CLK_12000000_HZ (12000000uL) +#define CY_CAPSENSE_MOD_CSD_CLK_24000000_HZ (24000000uL) +#define CY_CAPSENSE_MOD_CSD_CLK_48000000_HZ (48000000uL) + +#define CY_CAPSENSE_MIN_SNS_CLK_DIVIDER (4000u) + +#define CY_CAPSENSE_PERI_CLK_KHZ (50000000U / 1000U) +#define CY_CAPSENSE_PERI_CLK_MHZ (CY_CAPSENSE_PERI_CLK_KHZ / 1000U) + +#define CY_CAPSENSE_CPU_CLK_KHZ (50000000U / 1000U) +#define CY_CAPSENSE_CPU_CLK_MHZ (CY_CAPSENSE_CPU_CLK_KHZ / 1000U) + +/******************************************************************************* +* Miscellaneous Macros +*******************************************************************************/ +#define CY_CAPSENSE_2000_MV (2000u) + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_SENSING_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_structure.c b/cy_capsense_structure.c new file mode 100644 index 0000000..f76cd15 --- /dev/null +++ b/cy_capsense_structure.c @@ -0,0 +1,308 @@ +/***************************************************************************//** +* \file cy_capsense_structure.c +* \version 1.1 +* +* \brief +* This file defines the data structure global variables and provides the +* implementation for the functions of the Data Structure module. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include +#include +#include "cy_syslib.h" +#include "cy_capsense_common.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_lib.h" +#include "cy_csd.h" + + +/******************************************************************************* +* Function Name: Cy_CapSense_IsAnyWidgetActive +****************************************************************************//** +* +* Reports whether any widget has detected touch. +* +* This function reports whether any widget has detected a touch by extracting +* information from the widget status registers. This function does +* not process widget data but extracts previously processed results +* from the \ref group_capsense_structures. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the touch detection status of all the widgets: +* - Zero - No touch is detected in any of the widgets or sensors. +* - Non-zero - At least one widget or sensor has detected a touch. +* +*******************************************************************************/ +uint32_t Cy_CapSense_IsAnyWidgetActive(const cy_stc_capsense_context_t * context) +{ + uint32_t result = 0u; + uint32_t wdIndex; + + for (wdIndex = context->ptrCommonConfig->numWd; wdIndex-- > 0u;) + { + result |= (uint32_t)context->ptrWdContext[wdIndex].status & CY_CAPSENSE_WD_ACTIVE_MASK; + } + + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_IsWidgetActive +****************************************************************************//** +* +* Reports whether the specified widget detected touch on any of its sensors. +* +* This function reports whether the specified widget has detected a touch by +* extracting information from the widget status register. +* This function does not process widget data but extracts previously processed +* results from the \ref group_capsense_structures. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the touch detection status of the specified widgets: +* - Zero - No touch is detected in the specified widget or a wrong widgetId +* is specified. +* - Non-zero if at least one sensor of the specified widget is active, i.e. +* a touch is detected. +* +*******************************************************************************/ +uint32_t Cy_CapSense_IsWidgetActive( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = 0uL; + + if (widgetId < context->ptrCommonConfig->numWd) + { + result = (uint32_t)context->ptrWdContext[widgetId].status & CY_CAPSENSE_WD_ACTIVE_MASK; + } + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_IsSensorActive +****************************************************************************//** +* +* Reports whether the specified sensor in the widget detected touch. +* +* This function reports whether the specified sensor in the widget has detected a +* touch by extracting information from the widget status register. +* This function does not process widget or sensor data but extracts previously +* processed results from the \ref group_capsense_structures. +* +* For proximity sensors, this function returns the proximity detection status. +* To get the touch status of proximity sensors, use the +* Cy_CapSense_IsProximitySensorActive() function. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the touch detection status of the specified sensor/widget: +* - Zero if no touch is detected in the specified sensor/widget or a wrong +* widget ID/sensor ID is specified. +* - Non-zero if the specified sensor is active, i.e. touch is detected. If the +* specific sensor belongs to a proximity widget, the proximity detection +* status is returned. +* +*******************************************************************************/ +uint32_t Cy_CapSense_IsSensorActive( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = 0uL; + + if (widgetId < context->ptrCommonConfig->numWd) + { + if (sensorId < context->ptrWdConfig[widgetId].numSns) + { + result = context->ptrWdConfig[widgetId].ptrSnsContext[sensorId].status; + } + } + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_IsProximitySensorActive +****************************************************************************//** +* +* Reports the status of the specified proximity widget/sensor. +* +* This function reports whether the specified proximity sensor has detected +* a touch or proximity event by extracting information from the widget +* status register. This function is used only with proximity widgets. +* This function does not process widget data but extracts previously processed +* results from the \ref group_capsense_structures. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param sensorId +* Specifies the ID number of the sensor within the widget. A macro for the +* sensor ID within a specified widget can be found in the cycfg_capsense.h +* file defined as CY_CAPSENSE__SNS_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the status of the specified sensor of the proximity widget. Zero +* indicates that no touch is detected in the specified sensor/widget or a +* wrong widgetId/proxId is specified. +* - Bits [31..2] are reserved. +* - Bit [1] indicates that a touch is detected. +* - Bit [0] indicates that a proximity is detected. +* +*******************************************************************************/ +uint32_t Cy_CapSense_IsProximitySensorActive( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context) +{ + uint32_t result = 0uL; + + if (widgetId < context->ptrCommonConfig->numWd) + { + if ((uint8_t)CY_CAPSENSE_WD_PROXIMITY_E == context->ptrWdConfig[widgetId].wdType) + { + if (sensorId < context->ptrWdConfig[widgetId].numSns) + { + result |= context->ptrWdConfig[widgetId].ptrSnsContext[sensorId].status; + } + } + } + + return result; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_GetTouchInfo +****************************************************************************//** +* +* Reports the details of touch position detected on the specified touchpad, +* matrix buttons or slider widgets. +* +* This function does not process widget data but extracts previously processed +* results from the \ref group_capsense_structures. +* +* \param widgetId +* Specifies the ID number of the widget. A macro for the widget ID can be found +* in the cycfg_capsense.h file defined as CY_CAPSENSE__WDGT_ID. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns the pointer to widget cy_stc_capsense_touch_t structure that +* contains number of positions and data about each position. +* +* +*******************************************************************************/ +cy_stc_capsense_touch_t * Cy_CapSense_GetTouchInfo( + uint32_t widgetId, + const cy_stc_capsense_context_t * context) +{ + cy_stc_capsense_touch_t * ptrTouch = NULL; + + const cy_stc_capsense_widget_config_t * ptrWdCfg; + + if (widgetId < context->ptrCommonConfig->numWd) + { + ptrWdCfg = &context->ptrWdConfig[widgetId]; + switch (ptrWdCfg->wdType) + { + case (uint8_t)CY_CAPSENSE_WD_TOUCHPAD_E: + case (uint8_t)CY_CAPSENSE_WD_MATRIX_BUTTON_E: + case (uint8_t)CY_CAPSENSE_WD_LINEAR_SLIDER_E: + case (uint8_t)CY_CAPSENSE_WD_RADIAL_SLIDER_E: + ptrTouch = &ptrWdCfg->ptrWdContext->wdTouch; + break; + default: + break; + } + } + + return ptrTouch; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CheckConfigIntegrity +****************************************************************************//** +* +* Performs verification of CapSense data structure initialization. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return status +* Returns status of operation: +* - Zero - Indicates successful initialization. +* - Non-zero - One or more errors occurred in the initialization process. +* +*******************************************************************************/ +cy_status Cy_CapSense_CheckConfigIntegrity(const cy_stc_capsense_context_t * context) +{ + cy_status result = CY_RET_SUCCESS; + + const cy_stc_capsense_common_config_t * ptrCommonCfg = context->ptrCommonConfig; + const cy_stc_capsense_common_context_t * ptrCommonCxt = context->ptrCommonContext; + const cy_stc_capsense_internal_context_t * ptrInternalCxt = context->ptrInternalContext; + const cy_stc_capsense_widget_config_t * ptrWdCfg = context->ptrWdConfig; + const cy_stc_capsense_widget_context_t * ptrWdCxt = context->ptrWdContext; + const cy_stc_capsense_pin_config_t * ptrPinCfg = context->ptrPinConfig; + const cy_stc_capsense_pin_config_t * ptrShieldPinCfg = context->ptrShieldPinConfig; + const cy_stc_active_scan_sns_t * ptrActScanSns = context->ptrActiveScanSns; + + if (ptrCommonCfg == NULL) {result |= CY_RET_BAD_DATA;} + if (ptrCommonCxt == NULL) {result |= CY_RET_BAD_DATA;} + if (ptrInternalCxt == NULL) {result |= CY_RET_BAD_DATA;} + if (ptrWdCfg == NULL) {result |= CY_RET_BAD_DATA;} + if (ptrWdCxt == NULL) {result |= CY_RET_BAD_DATA;} + if (ptrPinCfg == NULL) {result |= CY_RET_BAD_DATA;} + if (ptrCommonCfg->csdShieldEn != 0u) + { + if((ptrCommonCfg->csdShieldNumPin > 0u) && (ptrShieldPinCfg == NULL)) + { + result |= CY_RET_BAD_DATA; + } + } + if (ptrActScanSns == NULL) {result |= CY_RET_BAD_DATA;} + + + return (result); +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_structure.h b/cy_capsense_structure.h new file mode 100644 index 0000000..5e302e3 --- /dev/null +++ b/cy_capsense_structure.h @@ -0,0 +1,598 @@ +/***************************************************************************//** +* \file cy_capsense_structure.h +* \version 1.1 +* +* \brief +* This file provides the top-level declarations of the CapSense data +* structure. Also, the file declares the functions for data access. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_STRUCTURE_H) +#define CY_CAPSENSE_STRUCTURE_H + +#include "cy_syslib.h" +#include "cy_device_headers.h" +#include "cy_csd.h" +#include "cy_capsense_lib.h" +#include "cy_capsense_gesture_lib.h" +#include "cy_capsense_common.h" + + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* CapSense Enumerated Types +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_enums *//** \{ */ +/******************************************************************************/ + +/** Defines MW Tuner module states */ +typedef enum +{ + CY_CAPSENSE_TU_FSM_RUNNING = 0x00u, /**< Running state is a state when CapSense middleware is not + * blocked by the CapSense Tuner tool and application program continuously scans */ + CY_CAPSENSE_TU_FSM_SUSPENDED = 0x01u, /**< Scanning is suspended */ + CY_CAPSENSE_TU_FSM_ONE_SCAN = 0x03u, /**< Scanning is suspended after one scan cycle */ +} cy_en_capsense_tuner_state_t; + +/** Defines the Tuner command codes */ +typedef enum +{ + CY_CAPSENSE_TU_CMD_NONE_E = 0u, /**< No command */ + CY_CAPSENSE_TU_CMD_SUSPEND_E = 1u, /**< Suspend command */ + CY_CAPSENSE_TU_CMD_RESUME_E = 2u, /**< Resume command switches state from suspend to running */ + CY_CAPSENSE_TU_CMD_RESTART_E = 3u, /**< Restart command requests to perform CapSense re-initialization */ + CY_CAPSENSE_TU_CMD_RUN_SNR_TEST_E = 4u, /**< Reserved */ + CY_CAPSENSE_TU_CMD_PING_E = 5u, /**< Ping command to check whether application program calls Cy_CapSense_RunTuner() */ + CY_CAPSENSE_TU_CMD_ONE_SCAN_E = 6u, /**< Execute one scan cycle and then switch to suspend state */ + CY_CAPSENSE_TU_CMD_WRITE_E = 7u, /**< Writes specified data with offset into cy_capsense_tuner */ +} cy_en_capsense_tuner_cmd_t; + +/** Defines widget types */ +typedef enum +{ + CY_CAPSENSE_WD_BUTTON_E = 0x01u, /**< Button widget */ + CY_CAPSENSE_WD_LINEAR_SLIDER_E = 0x02u, /**< Linear Slider widget */ + CY_CAPSENSE_WD_RADIAL_SLIDER_E = 0x03u, /**< Radial Slider widget */ + CY_CAPSENSE_WD_MATRIX_BUTTON_E = 0x04u, /**< Matrix Buttons widget */ + CY_CAPSENSE_WD_TOUCHPAD_E = 0x05u, /**< Touchpad widget */ + CY_CAPSENSE_WD_PROXIMITY_E = 0x06u, /**< Proximity widget */ +} cy_en_capsense_widget_type_t; + +/** Defines sensing methods types */ +typedef enum +{ + CY_CAPSENSE_UNDEFINED_E = 0x00u, /**< Undefined method used at initialization or releasing the CSD HW block */ + CY_CAPSENSE_SENSE_METHOD_CSD_E = 0x01u, /**< CSD sensing method */ + CY_CAPSENSE_SENSE_METHOD_CSX_E = 0x02u, /**< CSX sensing method */ +} cy_en_capsense_sensing_method_t; + +/** Defines types of electrode */ +typedef enum +{ + CY_CAPSENSE_ELTD_TYPE_SELF_E = 0x01u, /**< Electrode used as a sensor in CSD sensing method */ + CY_CAPSENSE_ELTD_TYPE_MUT_TX_E = 0x02u, /**< Electrode used as a TX in CSX sensing method */ + CY_CAPSENSE_ELTD_TYPE_MUT_RX_E = 0x03u, /**< Electrode used as a RX in CSX sensing method */ +} cy_en_capsense_eltd_t; + + +/** Defines connections of sensing capacitors */ +typedef enum +{ + CY_CAPSENSE_CMODPAD_E = 0x01u, /**< External capacitor is connected to dedicated CMOD pad */ + CY_CAPSENSE_CTANKPAD_E = 0x02u, /**< External capacitor is connected to dedicated CSH pad */ + CY_CAPSENSE_CSHIELDPAD_E = 0x03u, /**< External capacitor is connected to dedicated SHIELD pad */ + CY_CAPSENSE_VREFEXTPAD_E = 0x04u, /**< External capacitor is connected to dedicated VREF pad */ +} cy_en_capsense_cap_connection_t; + + +/** Defines CapSense middleware execution events + * when the CapSense callback can be executed. */ +typedef enum +{ + CY_CAPSENSE_START_SAMPLE_E = 0x01u, /**< Start Sample Callback. The callback will be executed before each sensor + *scan triggering */ + CY_CAPSENSE_END_OF_SCAN_E = 0x02u, /**< End Of Scan Callback. The callback will be executed when sensor scan + * is finished and there is no other sensors in the queue to be scanned. */ +} cy_en_capsense_callback_event_t; + + +/** \} */ + + +/******************************************************************************* +* CapSense Data Structures +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_structures *//** \{ */ +/******************************************************************************/ + +/** Sensor context structure */ +typedef struct +{ + uint16_t raw; /**< Sensor raw count */ + uint16_t bsln; /**< Sensor baseline */ + uint16_t diff; /**< Sensor difference count */ + uint8_t status; /**< Sensor status */ + uint8_t negBslnRstCnt; /**< Negative baseline reset counter */ + uint8_t idacComp; /**< Compensation IDAC of CSD or IDAC in CSX */ + uint8_t bslnExt; /**< Sensor baseline fractional */ +} cy_stc_capsense_sensor_context_t; + +/** CSX Touchpad touch tracking history */ +typedef struct +{ + uint32_t velocity; /**< The square of the "speed" (maximum distance change per refresh interval) threshold + * distinguishing a fast finger movement from separate finger touches + * (in [pixels/refresh interval]). + * Squared speeds exceeding this value indicate separate finger touches. + * Squared speeds below this value indicate fast single finger movement. */ + cy_stc_capsense_position_t oldPeak[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; + /**< Touch Positions */ + uint8_t oldPeakNumber; /**< Number of detected peaks */ + uint8_t oldActiveIdsMask; /**< Mask of used IDs */ +} cy_stc_capsense_csx_touch_history_t; + +/** Internal CSX Touchpad buffer structure for CSX for Touchpads' processing */ +typedef struct +{ + int32_t distanceMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS * CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; + /**< Buffer for distance map data */ + int32_t colMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; /**< Buffer for column map data */ + int32_t rowMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; /**< Buffer for row map data */ + int32_t minsMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; /**< Buffer for minimums map data */ + cy_stc_capsense_position_t newPeak[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; + /**< Touch Positions */ + int8_t fingerPosIndexMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS + 3u]; + /**< Buffer for index map data */ + int8_t linksMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; /**< Buffer for linked map data */ + int8_t visitedMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; /**< Buffer for visited map data */ + int8_t markIndicesMap[CY_CAPSENSE_CSX_TOUCHPAD_MAX_PEAKS]; /**< Buffer for mark map data */ + uint8_t newPeakNumber; /**< Number of detected peaks */ + uint8_t newActiveIdsMask; /**< Mask of used IDs */ +} cy_stc_capsense_csx_touch_buffer_t; + +/** Widget context structure */ +typedef struct +{ + uint16_t fingerCap; /**< Widget finger capacitance parameter used for the CSD + * widgets only when SmartSense is enabled */ + uint16_t sigPFC; /**< The 75% of signal per user-defined finger capacitance */ + uint16_t resolution; /**< Provides scan resolution for the CSD Widgets. + * Provides number of sub-conversions for the CSX Widgets */ + uint16_t maxRawCount; /**< Calculated maximum raw count of widget */ + uint16_t fingerTh; /**< Widget Finger Threshold */ + uint16_t proxTh; /**< Widget Proximity Threshold */ + uint16_t lowBslnRst; /**< The widget low baseline reset count. Specifies the number + * of samples the sensor signal must be below the Negative + * Noise Threshold \ref nNoiseTh to trigger a baseline reset */ + uint16_t snsClk; /**< Sense Clock Divider. For the Matrix Buttons and Touchpad widgets + * specifies the column sense clock divider */ + uint16_t rowSnsClk; /**< Row Sense Clock Divider for the Matrix Buttons and Touchpad widgets */ + uint16_t gestureDetected; /**< Mask of detected gestures */ + uint16_t gestureDirection; /**< Mask of directions of detected gestures */ + int16_t xDelta; /**< The filtered by Ballistic Multiplier X-displacement */ + int16_t yDelta; /**< The filtered by Ballistic Multiplier Y-displacement */ + uint8_t noiseTh; /**< Widget Noise Threshold */ + uint8_t nNoiseTh; /**< Widget Negative Noise Threshold */ + uint8_t hysteresis; /**< Widget Hysteresis for the signal crossing finger threshold */ + uint8_t onDebounce; /**< Widget Debounce for the signal above the finger threshold 1 to 255. + * * 1 - touch reported immediately as soon as detected + * * 2 - touch reported on the second consecutive detection + * * 3 - touch reported on the third consecutive detection */ + uint8_t snsClkSource; /**< Widget clock source: + * * bit[7] - Indicates auto mode of clock source selection + * * bit[0:6] - Clock source: + * * 0 - Direct (CY_CAPSENSE_CLK_SOURCE_DIRECT) + * * 1 - SSC6 (CY_CAPSENSE_CLK_SOURCE_SSC6) + * * 2 - SSC7 (CY_CAPSENSE_CLK_SOURCE_SSC7) + * * 3 - SSC9 (CY_CAPSENSE_CLK_SOURCE_SSC9) + * * 4 - SSC10 (CY_CAPSENSE_CLK_SOURCE_SSC10) + * * 5 - PRS8 (CY_CAPSENSE_CLK_SOURCE_PRS8) + * * 6 - PRS12 (CY_CAPSENSE_CLK_SOURCE_PRS12) */ + uint8_t idacMod[CY_CAPSENSE_FREQ_CHANNELS_NUM]; /**< Sets the current of the modulation IDAC for the CSD widgets. + * For the CSD Touchpad and Matrix Button widgets sets the current of the + * modulation IDAC for the column sensors. Not used for the CSX widgets. */ + uint8_t idacGainIndex; /**< Index of IDAC gain in table \ref cy_stc_capsense_idac_gain_table_t */ + uint8_t rowIdacMod[CY_CAPSENSE_FREQ_CHANNELS_NUM]; /**< Sets the current of the modulation IDAC for the row sensors + * for the CSD Touchpad and Matrix Button widgets. Not used for the CSX widgets. */ + uint8_t bslnCoeff; /**< Baseline IIR filter coefficient. Lower value leads to higher filtering. */ + uint8_t status; /**< Contains masks: + * * bit[0] - Widget Active (CY_CAPSENSE_WD_ACTIVE_MASK) + * * bit[1] - Widget Disabled (CY_CAPSENSE_WD_DISABLE_MASK) + * * bit[2] - Widget Working (CY_CAPSENSE_WD_WORKING_MASK) - reserved */ + cy_stc_capsense_touch_t wdTouch; /**< Widget touch structure used for Matrix Buttons, Sliders, and Touchpads */ +} cy_stc_capsense_widget_context_t; + +/** Pin configuration structure */ +typedef struct +{ + GPIO_PRT_Type * pcPtr; /**< Pointer to the base port register of the IO */ + uint8_t pinNumber; /**< Position of the IO in the port */ +} cy_stc_capsense_pin_config_t; + +/** Electrode objects configuration structure */ +typedef struct +{ + const cy_stc_capsense_pin_config_t * ptrPin; /**< Pointer to pin configuration structure */ + uint8_t type; /**< Electrode type \ref cy_en_capsense_eltd_t */ + uint8_t numPins; /**< Total number of pins in this sensor */ +} cy_stc_capsense_electrode_config_t; + +/** Configuration structure of advanced touchpad */ +typedef struct +{ + uint16_t penultimateTh; /**< Defines a threshold for determining arrival at edges. This + * value may have to be increased for small diamonds, so that the edge handling is + * initiated sooner. If this number is too high, there is jumping at the edge with + * a smaller finger. If this number is too low, there is jumping at the edge with a + * larger finger. */ + uint16_t virtualSnsTh; /**< Defines a virtual sensor signal. This value should be set + * to the value of any sensor when a medium-sized finger is placed directly over + * it. If this value is too high, a position is reported nearer the edge than ideal + * position. If this value is too low, a position is reported nearer the middle of + * touchpad. */ + uint8_t crossCouplingTh; /**< Defines cross coupling threshold. It is subtracted from + * sensor signals at centroid position calculation to improve the accuracy. + * The threshold should be equal to a sensor signal when your finger is near the + * sensor, but not touching the sensor. This can be determined by slowly dragging + * your finger across the panel and finding the inflection point of the difference + * counts at the base of the curve. The difference value at this point should be + * the Cross-coupling threshold. */ + uint8_t reserved0; /**< Reserved field */ + uint8_t reserved1; /**< Reserved field */ + uint8_t reserved2; /**< Reserved field */ +} cy_stc_capsense_advanced_touchpad_config_t; + +/** Widget configuration structure */ +typedef struct +{ + cy_stc_capsense_widget_context_t * ptrWdContext; /**< Pointer to context structure of this widget */ + cy_stc_capsense_sensor_context_t * ptrSnsContext; /**< Pointer to the first object of sensor context structure that belongs to this widget */ + const cy_stc_capsense_electrode_config_t * ptrEltdConfig; /**< Pointer to the first object of electrode configuration structure that belongs to this widget */ + + cy_stc_capsense_smartsense_csd_noise_envelope_t * ptrNoiseEnvelope; + /**< Pointer to the noise envelope filter used by SmartSense */ + uint16_t * ptrRawFilterHistory; /**< Pointer to the raw count filter history of the widget */ + uint8_t * ptrRawFilterHistoryLow; /**< Pointer to the raw count filter history extended of the widget */ + uint32_t iirCoeff; /**< Raw count IIR filter coefficient. Smaller value leads to higher filtering */ + + uint8_t * ptrDebounceArr; /**< Pointer to the debounce array of the widget */ + + const uint8_t * ptrDiplexTable; /**< Pointer to the diplex table used for Linear slider when Diplex option is enabled */ + uint32_t centroidConfig; /**< Configuration of centroids */ + uint16_t xResolution; /**< Keeps maximum position value. For Touchpads X-axis maximum position */ + uint16_t yResolution; /**< For Touchpads Y-Axis maximum position */ + uint16_t numSns; /**< The total number of sensors: + * For CSD widgets: WD_NUM_ROWS + WD_NUM_COLS. + * For CSX widgets: WD_NUM_ROWS * WD_NUM_COLS. */ + uint8_t numCols; /**< For CSD Button and Proximity Widgets, the number of sensors. + * For CSD Slider Widget, the number of segments. + * For CSD Touchpad and Matrix Button, the number of the column sensors. + * For CSX Button, Touchpad, and Matrix Button, the number of the Rx electrodes. */ + uint8_t numRows; /**< For CSD Touchpad and Matrix Buttons, the number of the row sensors. + * For the CSX Button, the number of the Tx electrodes (constant 1u). + * For CSX Touchpad and Matrix Button, the number of the Tx electrodes. */ + cy_stc_capsense_touch_t * ptrPosFilterHistory; /**< Pointer to the position filter history */ + cy_stc_capsense_csx_touch_history_t * ptrCsxTouchHistory; /**< Pointer to the CSX touchpad history */ + cy_stc_capsense_csx_touch_buffer_t * ptrCsxTouchBuffer; /**< Pointer to the single CSX buffer needed for CSX touchpad processing */ + uint16_t * ptrCsdTouchBuffer; /**< Pointer to the CSD buffer needed for advanced CSD touchpad processing */ + + cy_stc_capsense_gesture_config_t * ptrGestureConfig; /**< Pointer to Gesture configuration structure */ + cy_stc_capsense_gesture_context_t * ptrGestureContext; /**< Pointer to Gesture context structure */ + + cy_stc_capsense_ballistic_config_t ballisticConfig; /**< The configuration data for position ballistic filter. */ + cy_stc_capsense_ballistic_context_t * ptrBallisticContext; /**< Pointer to Ballistic filter context structure */ + + cy_stc_capsense_adaptive_filter_config_t aiirConfig; /**< The configuration of position adaptive filter. */ + cy_stc_capsense_advanced_touchpad_config_t advConfig; /**< The configuration of CSD advanced touchpad */ + + uint32_t posFilterConfig; /**< Position filters configuration */ + uint16_t rawFilterConfig; /**< Raw count filters configuration */ + + uint8_t senseMethod; /**< Specifies the widget sensing method */ + uint8_t wdType; /**< Specifies the widget type */ + +} cy_stc_capsense_widget_config_t; + +/** Declares the IDAC gain table */ +typedef struct +{ + uint32_t gainReg; /**< Register value of IDAC gain */ + uint32_t gainValue; /**< Absolute gain value in pA */ +} cy_stc_capsense_idac_gain_table_t; + +/** Common configuration structure */ +typedef struct +{ + uint32_t cpuClkHz; /**< CPU clock in Hz */ + uint32_t periClkHz; /**< Peripheral clock in Hz */ + uint16_t vdda; /**< VDDA in mV */ + uint16_t numPin; /**< Total number of IOs. */ + uint16_t numSns; /**< The total number of sensors. It is equal to the number of objects with raw count. + * * For CSD widgets: WD_NUM_ROWS + WD_NUM_COLS + * * For CSX widgets: WD_NUM_ROWS * WD_NUM_COLS */ + uint8_t numWd; /**< Total number of widgets */ + + uint8_t csdEn; /**< CSD sensing method enabled, at least one CSD widget is configured */ + uint8_t csxEn; /**< CSX sensing method enabled, at least one CSX widget is configured */ + uint8_t mfsEn; /**< Multi-frequency Scan (MFS) enabled */ + uint8_t positionFilterEn; /**< Position filtering enabled */ + + uint8_t periDividerType; /**< Peripheral clock type (8- or 16-bit type) */ + uint8_t periDividerIndex; /**< Peripheral divider index */ + uint8_t analogWakeupDelay; /**< Time needed to establish correct operation of the CSD HW block after power up or deep sleep. */ + + uint8_t ssIrefSource; /**< Iref source */ + uint8_t ssVrefSource; /**< Vref source */ + + uint16_t proxTouchCoeff; /**< Proximity touch coefficient in percentage used in SmartSense */ + uint8_t swSensorAutoResetEn; /**< Sensor auto reset enabled */ + + uint8_t portCmodPadNum; /**< Number of port of dedicated Cmod pad */ + uint8_t pinCmodPad; /**< Position of the dedicated Cmod pad in the port */ + uint8_t portCshPadNum; /**< Number of port of dedicated Csh pad */ + uint8_t pinCshPad; /**< Position of the dedicated Csh pad in the port */ + uint8_t portShieldPadNum; /**< Number of port of dedicated Shield pad */ + uint8_t pinShieldPad; /**< Position of the dedicated Shield pad in the port */ + uint8_t portVrefExtPadNum; /**< Number of port of dedicated VrefExt pad */ + uint8_t pinVrefExtPad; /**< Position of the dedicated VrefExt pad in the port */ + uint8_t portCmodNum; /**< Number of port of Cmod pin */ + + cy_stc_capsense_idac_gain_table_t idacGainTable[CY_CAPSENSE_IDAC_GAIN_NUMBER]; + /**< Table with the supported IDAC gains and corresponding register values */ + + CSD_Type * ptrCsdBase; /**< Pointer to the CSD HW block register */ + cy_stc_csd_context_t * ptrCsdContext; /**< Pointer to the CSD driver context */ + GPIO_PRT_Type * portCmod; /**< Pointer to the base port register of the Cmod pin */ + GPIO_PRT_Type * portCsh; /**< Pointer to the base port register of the Csh pin */ + GPIO_PRT_Type * portCintA; /**< Pointer to the base port register of the CintA pin */ + GPIO_PRT_Type * portCintB; /**< Pointer to the base port register of the CintB pin */ + + uint8_t pinCmod; /**< Position of the Cmod pin in the port */ + uint8_t portCshNum; /**< Number of port of Csh pin */ + uint8_t pinCsh; /**< Position of the Csh pin in the port */ + uint8_t pinCintA; /**< Position of the CintA pin in the port */ + uint8_t pinCintB; /**< Position of the CintB pin in the port */ + + uint8_t csdShieldEn; /**< Shield enabled */ + uint8_t csdInactiveSnsConnection; /**< Inactive sensor connection state: + * * CY_CAPSENSE_SNS_CONNECTION_HIGHZ + * * CY_CAPSENSE_SNS_CONNECTION_SHIELD + * * CY_CAPSENSE_SNS_CONNECTION_GROUND */ + uint8_t csdShieldDelay; /**< Shield signal delay */ + uint16_t csdVref; /**< Vref for CSD method */ + uint16_t csdRConst; /**< Sensor resistance in series used by SmartSense */ + uint8_t csdCTankShieldEn; /**< Csh enabled */ + uint8_t csdShieldNumPin; /**< Number of shield IOs */ + uint8_t csdShieldSwRes; /**< Shield switch resistance */ + uint8_t csdInitSwRes; /**< Switch resistance at coarse initialization */ + uint8_t csdChargeTransfer; /**< IDAC sensing configuration */ + uint8_t csdRawTarget; /**< Raw count target in percentage for CSD calibration */ + uint8_t csdAutotuneEn; /**< SmartSense enabled */ + uint8_t csdIdacAutocalEn; /**< CSD IDAC calibration enabled */ + uint8_t csdIdacGainInit; /**< IDAC gain index per \ref idacGainTable */ + uint8_t csdIdacAutoGainEn; /**< IDAC gain autocalibration enabled */ + uint8_t csdCalibrationError; /**< Acceptable calibration error */ + uint8_t csdIdacGainIndexDefault; /**< The highest IDAC gain index in CSD calibration per \ref idacGainTable */ + uint8_t csdIdacMin; /**< Min acceptable IDAC value in CSD calibration */ + uint8_t csdIdacCompEn; /**< Compensation IDAC enabled */ + uint8_t csdFineInitTime; /**< Number of dummy SnsClk periods at fine initialization */ + uint8_t csdIdacRowColAlignEn; /**< Row-Column alignment enabled. It adjusts modulator IDAC for rows + * and for columns to achieve the similar sensitivity */ + uint8_t csdMfsDividerOffsetF1; /**< Frequency divider offset for channel 1. This value is added to + * base (channel 0) SnsClk divider to form channel 1 frequency */ + uint8_t csdMfsDividerOffsetF2; /**< Frequency divider offset for channel 2. This value is added to + * base (channel 0) SnsClk divider to form channel 2 frequency */ + uint8_t csxRawTarget; /**< Raw count target in percentage for CSX calibration */ + uint8_t csxIdacGainInit; /**< IDAC gain for CSX method */ + uint8_t csxRefGain; /**< Refgen gain for CSX method */ + uint8_t csxIdacAutocalEn; /**< CSX IDAC calibration enabled */ + uint8_t csxCalibrationError; /**< Acceptable calibration error */ + uint8_t csxFineInitTime; /**< Number of dummy TX periods at fine initialization */ + uint8_t csxInitSwRes; /**< Switch resistance at fine initialization */ + uint8_t csxScanSwRes; /**< Switch resistance at scanning */ + uint8_t csxInitShieldSwRes; /**< Switch resistance at fine initialization */ + uint8_t csxScanShieldSwRes; /**< Switch resistance at scanning */ + uint8_t csxMfsDividerOffsetF1; /**< Frequency divider offset for channel 1. This value is added to + * base (channel 0) Tx divider to form channel 1 frequency */ + uint8_t csxMfsDividerOffsetF2; /**< Frequency divider offset for channel 2. This value is added to + * base (channel 0) Tx divider to form channel 2 frequency */ +} cy_stc_capsense_common_config_t; + +/** Declares active sensor details */ +typedef struct +{ + void (* ptrISRCallback)(void * context); /**< Pointer to the interrupt handler of the active sensor */ + + const cy_stc_capsense_widget_config_t * ptrWdConfig; /**< Pointer to the widget configuration structure of the active sensor */ + cy_stc_capsense_widget_context_t * ptrWdContext; /**< Pointer to the widget context structure of the active sensor */ + + const cy_stc_capsense_electrode_config_t * ptrEltdConfig; /**< Pointer to the electrode configuration structure of the active sensor */ + const cy_stc_capsense_electrode_config_t * ptrRxConfig; /**< Pointer to the Rx electrode configuration structure of the active sensor */ + const cy_stc_capsense_electrode_config_t * ptrTxConfig; /**< Pointer to the Tx electrode configuration structure of the active sensor */ + + cy_stc_capsense_sensor_context_t * ptrSnsContext; /**< Pointer to the sensor context structure */ + + volatile uint16_t sensorIndex; /**< Current sensor ID */ + volatile uint8_t widgetIndex; /**< Current widget ID */ + volatile uint8_t rxIndex; /**< Current Rx ID */ + volatile uint8_t txIndex; /**< Current Tx ID */ + volatile uint8_t connectedSnsState; /**< Shows if the current sensor is connected to analog bus */ + volatile uint8_t scanScopeAll; /**< Request of scanning all widgets */ + volatile uint8_t scanScopeSns; /**< Request of scanning a single sensor */ + volatile uint8_t mfsChannelIndex; /**< MFS channel index */ + volatile uint8_t currentSenseMethod; /**< Current sensing method */ +} cy_stc_active_scan_sns_t; + + +/** Declares internal Context Data Structure */ +typedef struct +{ + uint32_t csdInactiveSnsDm; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegConfig; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwHsPSelScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwHsPSelInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwBypSel; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwResScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwResInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegAmuxbufInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwAmuxbufSel; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwShieldSelScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwShieldSelInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegHscmpInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegHscmpScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csdIdacAConfig; /**< Internal pre-calculated data for faster operation */ + uint32_t csdIdacBConfig; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwFwTankSelScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwFwTankSelInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegSwCmpPSel; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegIoSel; /**< Internal pre-calculated data for faster operation */ + uint32_t csdRegRefgen; /**< Internal pre-calculated data for faster operation */ + uint32_t csxRegConfigInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csxRegConfigScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csxRegSwResInit; /**< Internal pre-calculated data for faster operation */ + uint32_t csxRegSwResPrech; /**< Internal pre-calculated data for faster operation */ + uint32_t csxRegSwResScan; /**< Internal pre-calculated data for faster operation */ + uint32_t csxRegRefgen; /**< Internal pre-calculated data for faster operation */ + uint32_t regSwRefGenSel; /**< Internal pre-calculated data for faster operation */ + + uint8_t csdCmodConnection; /**< Internal pre-calculated data for faster operation */ + uint8_t csdCshConnection; /**< Internal pre-calculated data for faster operation */ + en_hsiom_sel_t csdInactiveSnsHsiom; /**< Internal pre-calculated data for faster operation */ + uint8_t csdVrefGain; /**< Internal pre-calculated data for faster operation */ + uint16_t csdVrefVoltageMv; /**< Internal pre-calculated data for faster operation */ +}cy_stc_capsense_internal_context_t; + +/** +* Provides the typedef for the callback function that is intended to be called when +* the \ref cy_en_capsense_callback_event_t events occurs. +*/ +typedef void (*cy_capsense_callback_t)(cy_stc_active_scan_sns_t * ptrActiveScan); + +/** +* Provides the typedef for the callback function that is called by the +* Cy_CapSense_RunTuner() function to establish communication with +* the CapSense Tuner tool to monitor CapSense operation. +* Refer to \ref group_capsense_callbacks section. +*/ +typedef void (*cy_capsense_tuner_send_callback_t)(void * context); + +/** +* Provides the typedef for the callback function that is called by the +* Cy_CapSense_RunTuner() function to establish communication with +* the CapSense Tuner tool to support life-time tunning. +* Refer to \ref group_capsense_callbacks section. +*/ +typedef void (*cy_capsense_tuner_receive_callback_t)(uint8_t ** commandPacket, uint8_t ** tunerPacket, void * context); + +/** \} */ + + + +/******************************************************************************/ +/** \addtogroup group_capsense_structures *//** \{ */ +/******************************************************************************/ + +/** Declares top-level Context Data Structure */ +typedef struct +{ + uint16_t configId; /**< 16-bit CRC calculated by the CapSense Configurator tool for the CapSense configuration. + * Used by the CapSense Tuner tool to identify if the FW corresponds to the specific user configuration. */ + uint16_t tunerCmd; /**< Tuner Command Register \ref cy_en_capsense_tuner_cmd_t. + * Used for the communication between the CapSense Tuner tool and the middleware */ + uint16_t scanCounter; /**< This counter increments after each scan. */ + uint8_t tunerSt; /**< State of CapSense middleware tuner module. \ref cy_en_capsense_tuner_state_t */ + uint8_t initDone; /**< Keep information whether initialization was done or not */ + cy_capsense_callback_t ptrSSCallback; /**< Pointer to a user's Start Sample callback function. Refer to \ref group_capsense_callbacks section */ + cy_capsense_callback_t ptrEOSCallback; /**< Pointer to a user's End Of Scan callback function. Refer to \ref group_capsense_callbacks section */ + + cy_capsense_tuner_send_callback_t ptrTunerSendCallback; /**< Pointer to a user's tuner callback function. Refer to \ref group_capsense_callbacks section */ + cy_capsense_tuner_receive_callback_t ptrTunerReceiveCallback; /**< Pointer to a user's tuner callback function. Refer to \ref group_capsense_callbacks section */ + + volatile uint32_t status; /**< Middleware status information, scan in progress or not */ + uint32_t timestampInterval; /**< Timestamp interval used at increasing the timestamp by Cy_CapSense_IncrementGestureTimestamp() */ + uint32_t timestamp; /**< Current timestamp should be kept updated and operational, which is vital for the + * operation of Gesture and Ballistic multiplier features */ + uint8_t modCsdClk; /**< The modulator clock divider for the CSD widgets */ + uint8_t modCsxClk; /**< The modulator clock divider for the CSX widgets */ + uint8_t tunerCnt; /**< Command counter of CapSense middleware tuner module */ +} cy_stc_capsense_common_context_t; + + + +/** Declares top-level CapSense context data structure */ +typedef struct +{ + const cy_stc_capsense_common_config_t * ptrCommonConfig; /**< Pointer to the common configuration structure */ + cy_stc_capsense_common_context_t * ptrCommonContext; /**< Pointer to the common context structure */ + cy_stc_capsense_internal_context_t * ptrInternalContext; /**< Pointer to the internal context structure */ + const cy_stc_capsense_widget_config_t * ptrWdConfig; /**< Pointer to the widget configuration structure */ + cy_stc_capsense_widget_context_t * ptrWdContext; /**< Pointer to the widget context structure */ + const cy_stc_capsense_pin_config_t * ptrPinConfig; /**< Pointer to the pin configuration structure */ + const cy_stc_capsense_pin_config_t * ptrShieldPinConfig; /**< Pointer to the shield pin configuration structure */ + cy_stc_active_scan_sns_t * ptrActiveScanSns; /**< Pointer to the current active sensor structure */ +} cy_stc_capsense_context_t; + +/** \} */ + + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_high_level *//** \{ */ +/******************************************************************************/ + +uint32_t Cy_CapSense_IsAnyWidgetActive(const cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_IsWidgetActive( + uint32_t widgetId, + const cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_IsSensorActive( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_IsProximitySensorActive( + uint32_t widgetId, + uint32_t sensorId, + const cy_stc_capsense_context_t * context); +cy_stc_capsense_touch_t * Cy_CapSense_GetTouchInfo( + uint32_t widgetId, + const cy_stc_capsense_context_t * context); + + +/** \} */ + + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +cy_status Cy_CapSense_CheckConfigIntegrity(const cy_stc_capsense_context_t * context); + +/** \} \endcond */ + + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_STRUCTURE_H */ + + +/* [] END OF FILE */ diff --git a/cy_capsense_tuner.c b/cy_capsense_tuner.c new file mode 100644 index 0000000..2801276 --- /dev/null +++ b/cy_capsense_tuner.c @@ -0,0 +1,394 @@ +/***************************************************************************//** +* \file cy_capsense_tuner.c +* \version 1.1 +* +* \brief +* This file provides the source code for the Tuner module functions. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#include "cy_syslib.h" +#include "cy_capsense_structure.h" +#include "cy_capsense_tuner.h" +#include "cy_capsense_control.h" +#include "cy_capsense_common.h" + + +/******************************************************************************* +* Function Name: Cy_CapSense_TuInitialize +****************************************************************************//** +* +* Initializes the communication interface with the CapSense Tuner tool. +* +*******************************************************************************/ +void Cy_CapSense_TuInitialize(cy_stc_capsense_context_t * context) +{ + volatile cy_stc_capsense_common_context_t * ptrCommonCxt = context->ptrCommonContext; + ptrCommonCxt->tunerCmd = (uint16_t)CY_CAPSENSE_TU_CMD_NONE_E; + ptrCommonCxt->tunerSt = (uint8_t)CY_CAPSENSE_TU_FSM_RUNNING; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_RunTuner +****************************************************************************//** +* +* Establishes synchronized operation between the CapSense middleware and +* the CapSense Tuner tool. +* +* This function should be called periodically in the application program to +* serve the CapSense Tuner tool requests and commands to synchronize the +* operation, however there is no specific timing requirement for this function. +* In most cases, the best place to call this function is after processing +* and before next scanning. +* +* If a user changes some parameters in the Tuner tool, a re-initialization +* of the middleware is required. In such cases, the tuner issues a re-initialize +* command and which is executed by this function. +* +* If this function is not called by the application program, the middleware +* operation is asynchronous to the Tuner tool and the following disadvantages +* are applicable: +* +* * The raw counts displayed in the CapSense Tuner tool may be filtered +* and/or non-filtered. As a result, noise and SNR measurements will +* not be accurate. +* * The CapSense Tuner tool may read the sensor data such as raw counts +* from a scan multiple times. As a result, noise and SNR measurement +* will not be accurate. +* * The CapSense Tuner tool and Host controller should not change +* the parameters via the tuner interface. Changing the parameters via +* the Tuner interface in the async mode will result in abnormal behavior. +* * Displaying detected gestures may be missed. +* +* \note +* Calling this function is not mandatory and required only +* synchronizing the communication with the CapSense Tuner tool when the Tuner +* is used. +* +* \warning +* This function executes received commands. Two commands +* CY_CAPSENSE_TU_CMD_ONE_SCAN_E and CY_CAPSENSE_TU_CMD_SUSPEND_E change the +* FW tuner module state to suspend. In this state, the function waits until +* CY_CAPSENSE_TU_CMD_RESUME_E is received. A callback mechanism of command +* receiving should be used to avoid FW hang. +* +* \param context +* The pointer to the CapSense context structure \ref cy_stc_capsense_context_t. +* +* \return +* Returns a status of whether a re-initialization of the middleware was +* executed by this function or not: +* - CY_CAPSENSE_STATUS_RESTART_DONE - Based on a received command, the +* CapSense was re-initialized. +* - CY_CAPSENSE_STATUS_RESTART_NONE - No re-initialization was executed by this +* function. +* +* \funcusage +* +* An example of synchronization with the Tuner tool using EzI2C: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Tuner_EzI2C +* +* An example of synchronization with the Tuner tool using UART.
+* Tuner Send callback implementation: Transmitting data through UART interface: +* \snippet capsense\1.1\snippet\main.c snippet_TunerSend +* +* Tuner Receive callback implementation: Receiving data from UART interface: +* \snippet capsense\1.1\snippet\main.c snippet_TunerReceive +* +* A part of the main.c FW flow with registering callbacks: +* \snippet capsense\1.1\snippet\main.c snippet_Cy_CapSense_Tuner_UART +* +* Refer to the \ref group_capsense_callbacks section for details. +* +*******************************************************************************/ +uint32_t Cy_CapSense_RunTuner(cy_stc_capsense_context_t * context) +{ + uint32_t interruptState; + uint32_t updateFlag = 0uL; + uint32_t tunerStatus = CY_CAPSENSE_STATUS_RESTART_NONE; + uint16_t tunerCommand; + uint32_t cmdOffset; + uint32_t cmdSize; + uint8_t cmdCounter; + + uint8_t * tunerStructure = NULL; + uint8_t * commandPacket = NULL; + volatile cy_stc_capsense_common_context_t * ptrCommonCxt = context->ptrCommonContext; + uint8_t tunerState = ptrCommonCxt->tunerSt; + + cy_capsense_tuner_send_callback_t sendCallback = context->ptrCommonContext->ptrTunerSendCallback; + cy_capsense_tuner_receive_callback_t receiveCallback = context->ptrCommonContext->ptrTunerReceiveCallback; + + do + { + /* + * ONE_SCAN command could be interpreted as two commands: + * RESUME till next call of this function and then + * SUSPEND till next command receiving. + * So, after one scan cycle tuner state is changed to suspend. + */ + if ((uint8_t)CY_CAPSENSE_TU_FSM_ONE_SCAN == tunerState) + { + interruptState = Cy_SysLib_EnterCriticalSection(); + context->ptrCommonContext->tunerCmd = (uint16_t)CY_CAPSENSE_TU_CMD_SUSPEND_E; + Cy_SysLib_ExitCriticalSection(interruptState); + } + + /* Send Data to the CapSense Tuner tool */ + if(NULL != sendCallback) + { + sendCallback((void *)context); + } + + /* Command can come from EzI2C by direct writing into data structure */ + tunerCommand = context->ptrCommonContext->tunerCmd; + cmdCounter = context->ptrCommonContext->tunerCnt + 1u; + + /* Call user's callback function if it is registered */ + if (NULL != receiveCallback) + { + commandPacket = NULL; + tunerStructure = NULL; + receiveCallback(&commandPacket, &tunerStructure, context); + + /* If command exists and is correct then read command */ + if ((NULL != commandPacket) || (NULL != tunerStructure)) + { + if (CY_CAPSENSE_COMMAND_OK == Cy_CapSense_CheckCommandIntegrity(commandPacket)) + { + tunerCommand = commandPacket[CY_CAPSENSE_COMMAND_CODE_0_IDX]; + ptrCommonCxt->tunerCmd = tunerCommand; + cmdCounter = commandPacket[CY_CAPSENSE_COMMAND_CNTR_0_IDX]; + } + } + } + + /* Check command register */ + switch (tunerCommand) + { + case (uint16_t)CY_CAPSENSE_TU_CMD_SUSPEND_E: + tunerState = (uint8_t)CY_CAPSENSE_TU_FSM_SUSPENDED; + updateFlag = 1u; + break; + + case (uint16_t)CY_CAPSENSE_TU_CMD_RESUME_E: + tunerState = (uint8_t)CY_CAPSENSE_TU_FSM_RUNNING; + updateFlag = 1u; + break; + + case (uint16_t)CY_CAPSENSE_TU_CMD_RESTART_E: + (void)Cy_CapSense_Enable(context); + tunerStatus = CY_CAPSENSE_STATUS_RESTART_DONE; + tunerState = (uint8_t)CY_CAPSENSE_TU_FSM_RUNNING; + updateFlag = 1u; + break; + + case (uint16_t)CY_CAPSENSE_TU_CMD_PING_E: + tunerState = (uint8_t)CY_CAPSENSE_TU_FSM_RUNNING; + updateFlag = 1u; + break; + + case (uint16_t)CY_CAPSENSE_TU_CMD_ONE_SCAN_E: + tunerState = (uint8_t)CY_CAPSENSE_TU_FSM_ONE_SCAN; + updateFlag = 0u; + break; + + case (uint16_t)CY_CAPSENSE_TU_CMD_WRITE_E: + /* Tuner state is not changed */ + cmdOffset = (uint32_t)((uint32_t)commandPacket[CY_CAPSENSE_COMMAND_OFFS_0_IDX] << CY_CAPSENSE_MSB_SHIFT) | + (uint32_t)commandPacket[CY_CAPSENSE_COMMAND_OFFS_1_IDX]; + cmdSize = commandPacket[CY_CAPSENSE_COMMAND_SIZE_0_IDX]; + + if (1u == cmdSize) + { + tunerStructure[cmdOffset] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 3u]; + } + else if (2u == cmdSize) + { + tunerStructure[cmdOffset + 1u] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 2u]; + tunerStructure[cmdOffset + 0u] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 3u]; + } + else + { + tunerStructure[cmdOffset + 3u] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 0u]; + tunerStructure[cmdOffset + 2u] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 1u]; + tunerStructure[cmdOffset + 1u] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 2u]; + tunerStructure[cmdOffset + 0u] = commandPacket[CY_CAPSENSE_COMMAND_DATA_0_IDX + 3u]; + } + + updateFlag = 1u; + break; + + default: + break; + } + + ptrCommonCxt->tunerSt = tunerState; + + /* Set Complete flag in command register if needed */ + if (0uL != updateFlag) + { + interruptState = Cy_SysLib_EnterCriticalSection(); + /* Check that command wasn't overwritten with new command */ + if (tunerCommand == ptrCommonCxt->tunerCmd) + { + ptrCommonCxt->tunerCmd |= CY_CAPSENSE_TU_CMD_COMPLETE_BIT; + ptrCommonCxt->tunerCnt = cmdCounter; + } + Cy_SysLib_ExitCriticalSection(interruptState); + updateFlag = 0uL; + } + + } while ((uint8_t)CY_CAPSENSE_TU_FSM_SUSPENDED == tunerState); + + return tunerStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CheckCommandIntegrity +****************************************************************************//** +* +* Checks command format, header, tail, CRC, etc. +* +* This function checks whether the specified packet with the size +* CY_CAPSENSE_COMMAND_PACKET_SIZE could be represented as a +* command received from the CapSense Tuner tool. +* The verification includes the following items: +* * Header +* * Tail +* * CRC +* * Command code +* +* Command format is the following: +* * Byte 0: Header 0 = 0x0D +* * Byte 1: Header 1 = 0x0A +* * Byte 2: Command code MSB = cy_en_capsense_tuner_cmd_t +* * Byte 3: Command code LSB = cy_en_capsense_tuner_cmd_t +* * Byte 4: Command counter +* * Byte 5: Size = either 1, 2 or 4 +* * Byte 6: Offset MSB +* * Byte 7: Offset LSB +* * Byte 8: Data MSB +* * Byte 9: Data +* * Byte 10: Data +* * Byte 11: Data LSB +* * Byte 12: 8-bit CRC +* * Byte 13: Tail 0 = 0x00 +* * Byte 14: Tail 1 = 0xFF +* * Byte 15: Tail 2 = 0xFF +* +* \param commandPacket +* The pointer to the data packet that should be verified. +* +* \return +* Returns the result of the command verification: +* - CY_CAPSENSE_COMMAND_OK - Command is correct. +* - CY_CAPSENSE_WRONG_HEADER - Wrong header. +* - CY_CAPSENSE_WRONG_TAIL - Wrong tail. +* - CY_CAPSENSE_WRONG_CRC - Wrong CRC. +* - CY_CAPSENSE_WRONG_CODE - Wrong Command code. +* +*******************************************************************************/ +uint32_t Cy_CapSense_CheckCommandIntegrity(const uint8_t * commandPacket) +{ + uint32_t cmdCheckStatus = CY_CAPSENSE_COMMAND_OK; + uint16_t crcValue; + + if (CY_CAPSENSE_COMMAND_HEAD_0 != commandPacket[CY_CAPSENSE_COMMAND_HEAD_0_IDX]) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_HEADER; + } + else if (CY_CAPSENSE_COMMAND_HEAD_1 != commandPacket[CY_CAPSENSE_COMMAND_HEAD_1_IDX]) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_HEADER; + } + else if (CY_CAPSENSE_COMMAND_TAIL_0 != commandPacket[CY_CAPSENSE_COMMAND_TAIL_0_IDX]) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_TAIL; + } + else if (CY_CAPSENSE_COMMAND_TAIL_1 != commandPacket[CY_CAPSENSE_COMMAND_TAIL_1_IDX]) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_TAIL; + } + else if (CY_CAPSENSE_COMMAND_TAIL_2 != commandPacket[CY_CAPSENSE_COMMAND_TAIL_2_IDX]) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_TAIL; + } + else if (((uint8_t)CY_CAPSENSE_TU_CMD_WRITE_E) < commandPacket[CY_CAPSENSE_COMMAND_CODE_0_IDX]) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_CODE; + } + else + { + crcValue = (uint16_t)((uint16_t)commandPacket[CY_CAPSENSE_COMMAND_CRC_0_IDX] << CY_CAPSENSE_MSB_SHIFT); + crcValue |= (uint16_t)commandPacket[CY_CAPSENSE_COMMAND_CRC_1_IDX]; + if (crcValue != Cy_CapSense_CalculateCrc16(&commandPacket[0u], CY_CAPSENSE_COMMAND_CRC_DATA_SIZE)) + { + cmdCheckStatus = CY_CAPSENSE_WRONG_CRC; + } + } + + return cmdCheckStatus; +} + + +/******************************************************************************* +* Function Name: Cy_CapSense_CalculateCrc16 +****************************************************************************//** +* +* Calculates CRC for the specified buffer and length. CRC Poly: 0xAC9A +* +* This API is used for the CRC protection of a packet received from +* the CapSense Tuner tool. CRC polynomial is 0xAC9A. It has a Hamming +* distance 5 for data words up to 241 bits. +* +* Reference: "P. Koopman, T. Chakravarthy, +* "Cyclic Redundancy Code (CRC) Polynomial Selection for Embedded Networks", +* The International Conference on Dependable Systems and Networks, DSN-2004" +* +* \param ptrData +* The pointer to the data. +* +* \param len +* The length of the data in bytes. +* +* \return +* Returns a calculated CRC-16 value. +* +*******************************************************************************/ +uint16 Cy_CapSense_CalculateCrc16(const uint8_t *ptrData, uint32_t len) +{ + uint32_t idx; + uint32_t actualCrc = 0u; + const uint16_t crcTable[] = + { + 0x0000u, 0xAC9Au, 0xF5AEu, 0x5934u, 0x47C6u, 0xEB5Cu, 0xB268u, 0x1EF2u, + 0x8F8Cu, 0x2316u, 0x7A22u, 0xD6B8u, 0xC84Au, 0x64D0u, 0x3DE4u, 0x917Eu + }; + + for (;len-- > 0u;) + { + /* Process HI Nibble */ + idx = ((actualCrc >> 12u) ^ (((uint32)*ptrData) >> 4u)) & 0xFLu; + actualCrc = crcTable[idx] ^ (actualCrc << 4u); + + /* Process LO Nibble */ + idx = ((actualCrc >> 12u) ^ (uint32)*ptrData) & 0xFLu; + actualCrc = crcTable[idx] ^ (actualCrc << 4u); + + ptrData++; + } + + return (uint16_t)actualCrc; +} + + +/* [] END OF FILE */ diff --git a/cy_capsense_tuner.h b/cy_capsense_tuner.h new file mode 100644 index 0000000..dab8574 --- /dev/null +++ b/cy_capsense_tuner.h @@ -0,0 +1,94 @@ +/***************************************************************************//** +* \file cy_capsense_tuner.h +* \version 1.1 +* +* \brief +* This file provides CapSense MW Tuner module function prototypes. +* +******************************************************************************** +* \copyright +* Copyright 2018-2019, Cypress Semiconductor Corporation. All rights reserved. +* You may use this file only in accordance with the license, terms, conditions, +* disclaimers, and limitations in the end user license agreement accompanying +* the software package with which this file was provided. +*******************************************************************************/ + +#if !defined(CY_CAPSENSE_TUNER_H) +#define CY_CAPSENSE_TUNER_H + +#include "cy_syslib.h" +#include "cy_capsense_structure.h" + +#if defined(__cplusplus) +extern "C" { +#endif + + +/******************************************************************************* +* Macros Definitions +*******************************************************************************/ +#define CY_CAPSENSE_COMMAND_PACKET_SIZE (16u) +#define CY_CAPSENSE_COMMAND_CRC_DATA_SIZE (11u) + +#define CY_CAPSENSE_COMMAND_HEAD_0_IDX (0u) +#define CY_CAPSENSE_COMMAND_HEAD_1_IDX (1u) +#define CY_CAPSENSE_COMMAND_CODE_0_IDX (2u) +#define CY_CAPSENSE_COMMAND_CNTR_0_IDX (3u) +#define CY_CAPSENSE_COMMAND_SIZE_0_IDX (4u) +#define CY_CAPSENSE_COMMAND_OFFS_0_IDX (5u) +#define CY_CAPSENSE_COMMAND_OFFS_1_IDX (6u) +#define CY_CAPSENSE_COMMAND_DATA_0_IDX (7u) +#define CY_CAPSENSE_COMMAND_DATA_1_IDX (8u) +#define CY_CAPSENSE_COMMAND_DATA_2_IDX (9u) +#define CY_CAPSENSE_COMMAND_DATA_3_IDX (10u) +#define CY_CAPSENSE_COMMAND_CRC_0_IDX (11u) +#define CY_CAPSENSE_COMMAND_CRC_1_IDX (12u) +#define CY_CAPSENSE_COMMAND_TAIL_0_IDX (13u) +#define CY_CAPSENSE_COMMAND_TAIL_1_IDX (14u) +#define CY_CAPSENSE_COMMAND_TAIL_2_IDX (15u) + +#define CY_CAPSENSE_COMMAND_HEAD_0 (0x0Du) +#define CY_CAPSENSE_COMMAND_HEAD_1 (0x0Au) +#define CY_CAPSENSE_COMMAND_TAIL_0 (0x00u) +#define CY_CAPSENSE_COMMAND_TAIL_1 (0xFFu) +#define CY_CAPSENSE_COMMAND_TAIL_2 (0xFFu) + +#define CY_CAPSENSE_COMMAND_OK (0u) +#define CY_CAPSENSE_WRONG_HEADER (1u) +#define CY_CAPSENSE_WRONG_CRC (2u) +#define CY_CAPSENSE_WRONG_TAIL (3u) +#define CY_CAPSENSE_WRONG_CODE (4u) + +#define CY_CAPSENSE_MSB_SHIFT (8u) + +/******************************************************************************* +* Function Prototypes +*******************************************************************************/ + +/******************************************************************************/ +/** \addtogroup group_capsense_high_level *//** \{ */ +/******************************************************************************/ + +uint32_t Cy_CapSense_RunTuner(cy_stc_capsense_context_t * context); +uint32_t Cy_CapSense_CheckCommandIntegrity(const uint8_t * commandPacket); + +/** \} */ + +/******************************************************************************/ +/** \cond SECTION_CAPSENSE_INTERNAL */ +/** \addtogroup group_capsense_internal *//** \{ */ +/******************************************************************************/ + +void Cy_CapSense_TuInitialize(cy_stc_capsense_context_t * context); +uint16 Cy_CapSense_CalculateCrc16(const uint8_t *ptrData, uint32_t len); + +/** \} \endcond */ + +#if defined(__cplusplus) +} +#endif + +#endif /* CY_CAPSENSE_TUNER_H */ + + +/* [] END OF FILE */ diff --git a/lib/TOOLCHAIN_ARM/libcy_capsense.ar b/lib/TOOLCHAIN_ARM/libcy_capsense.ar new file mode 100644 index 0000000..ee79357 Binary files /dev/null and b/lib/TOOLCHAIN_ARM/libcy_capsense.ar differ diff --git a/lib/TOOLCHAIN_GCC_ARM/libcy_capsense.a b/lib/TOOLCHAIN_GCC_ARM/libcy_capsense.a new file mode 100644 index 0000000..2184898 Binary files /dev/null and b/lib/TOOLCHAIN_GCC_ARM/libcy_capsense.a differ diff --git a/lib/TOOLCHAIN_IAR/libcy_capsense.a b/lib/TOOLCHAIN_IAR/libcy_capsense.a new file mode 100644 index 0000000..d8c47e0 Binary files /dev/null and b/lib/TOOLCHAIN_IAR/libcy_capsense.a differ