summaryrefslogtreecommitdiff
path: root/Libraries/TouchSense/STMTouch_Driver/src
diff options
context:
space:
mode:
authorAlexander <trotsenkoa@gmail.com>2022-06-29 11:03:02 +0300
committerAlexander <trotsenkoa@gmail.com>2022-06-29 11:03:02 +0300
commit1702ce6ce430a66bb7af51644b91b7c196e719d9 (patch)
tree6039acbdf047873d32aaf55969286c5f0d55958f /Libraries/TouchSense/STMTouch_Driver/src
Создаю новый репозиторий. Программа для версии NixieClock_v2. Работает, часы тикают. Есть проблема, что скачет вторая сеносрная кнопка (она в другом канале). Поэтому на нее собираюсь сделать антидребезг.
Diffstat (limited to 'Libraries/TouchSense/STMTouch_Driver/src')
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl.c61
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq.c372
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f0xx.c1008
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f3xx.c1148
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_hw.c862
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_sw.c996
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_hw.c888
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_sw.c1426
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8tl5x.c906
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_dxs.c181
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_ecs.c331
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_filter.c137
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_globals.c33
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c2103
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_object.c258
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_time.c174
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f0xx.c104
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f3xx.c55
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32l1xx.c55
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8l.c108
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8tl5x.c104
-rw-r--r--Libraries/TouchSense/STMTouch_Driver/src/tsl_touchkey.c1089
22 files changed, 12399 insertions, 0 deletions
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl.c
new file mode 100644
index 0000000..45ab841
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl.c
@@ -0,0 +1,61 @@
+/**
+ ******************************************************************************
+ * @file tsl.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains the STMTouch Driver main functions.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Initializes the TS interface.
+ * @param bank Array holding all the banks
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_Init(CONST TSL_Bank_T *bank)
+{
+ TSL_Status_enum_T retval;
+
+ // Get banks array
+ TSL_Globals.Bank_Array = bank;
+
+ // Initialization of the timing module
+ retval = TSL_tim_Init();
+
+ if (retval == TSL_STATUS_OK)
+ {
+ // Initialization of the acquisition module
+ retval = TSL_acq_Init();
+ }
+
+ return retval;
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq.c
new file mode 100644
index 0000000..45a9a10
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq.c
@@ -0,0 +1,372 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the acquisition in general.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
+
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Read all channels measurement of a Bank, calculate Delta
+ * @param[in] idx_bk Index of the Bank to access
+ * @param[in] mfilter Pointer to the Measure filter function
+ * @param[in] dfilter Pointer to the Delta filter function
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankGetResult(TSL_tIndex_T idx_bk, TSL_pFuncMeasFilter_T mfilter, TSL_pFuncDeltaFilter_T dfilter)
+{
+ TSL_Status_enum_T retval = TSL_STATUS_OK;
+ TSL_tIndex_T idx_ch;
+ TSL_tIndexDest_T idx_dest;
+ TSL_tMeas_T old_meas, new_meas;
+ TSL_tDelta_T new_delta;
+ CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
+ CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ // For all channels in the bank copy the measure + calculate delta and store them.
+ for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
+ {
+
+ // Get the Destination Index of the current channel
+ idx_dest = pchDest->IdxDest;
+
+ if (bank->p_chData[idx_dest].Flags.ObjStatus == TSL_OBJ_STATUS_ON)
+ {
+
+ // Initialize flag to inform the Object of that a new data is ready
+ bank->p_chData[idx_dest].Flags.DataReady = TSL_DATA_READY;
+
+ // Get the new measure (the access is different between acquisitions)
+ new_meas = TSL_acq_GetMeas(pchSrc->IdxSrc);
+
+ // Store last measure for the filter below
+#if TSLPRM_USE_MEAS > 0
+ old_meas = bank->p_chData[idx_dest].Meas;
+#else
+ old_meas = new_meas;
+#endif
+
+ // Store the new measure
+#if TSLPRM_USE_MEAS > 0
+ bank->p_chData[idx_dest].Meas = new_meas;
+#endif
+
+ // Check acquisition value min/max and set acquisition status flag
+ if (new_meas < TSL_Params.AcqMin)
+ {
+ bank->p_chData[idx_dest].Flags.AcqStatus = TSL_ACQ_STATUS_ERROR_MIN;
+ bank->p_chData[idx_dest].Delta = 0;
+ retval = TSL_STATUS_ERROR;
+ }
+ else
+ {
+ if (new_meas > TSL_Params.AcqMax)
+ {
+ bank->p_chData[idx_dest].Flags.AcqStatus = TSL_ACQ_STATUS_ERROR_MAX;
+ bank->p_chData[idx_dest].Delta = 0;
+ retval = TSL_STATUS_ERROR;
+ }
+ else // The measure is OK
+ {
+ if (TSL_acq_UseFilter(&bank->p_chData[idx_dest]))
+ {
+ // Apply Measure filter if it exists
+ if (mfilter)
+ {
+ new_meas = mfilter(old_meas, new_meas);
+ // Store the measure (optional - used for debug purpose)
+#if TSLPRM_USE_MEAS > 0
+ bank->p_chData[idx_dest].Meas = new_meas;
+#endif
+ }
+
+ // Calculate the new Delta
+ new_delta = TSL_acq_ComputeDelta(bank->p_chData[idx_dest].Ref, new_meas);
+
+ // Check Noise (TSL_ACQ_STATUS_OK if no Noise or if Noise detection is not supported)
+ bank->p_chData[idx_dest].Flags.AcqStatus = TSL_acq_CheckNoise();
+
+ // Apply Delta filter if it exists
+ if (dfilter)
+ {
+ bank->p_chData[idx_dest].Delta = dfilter(new_delta);
+ }
+ else
+ {
+ bank->p_chData[idx_dest].Delta = new_delta;
+ }
+ }
+ else
+ {
+ // Calculate the new Delta
+ bank->p_chData[idx_dest].Delta = TSL_acq_ComputeDelta(bank->p_chData[idx_dest].Ref, new_meas);
+
+ // Check Noise (TSL_ACQ_STATUS_OK if no Noise or if Noise detection is not supported)
+ bank->p_chData[idx_dest].Flags.AcqStatus = TSL_acq_CheckNoise();
+ }
+ }
+ }
+ }
+
+ // Next channel
+ pchDest++;
+ pchSrc++;
+
+ }
+
+ return retval;
+}
+
+
+/**
+ * @brief Calibrate a Bank
+ * @param[in] idx_bk Index of the Bank to access
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankCalibrate(TSL_tIndex_T idx_bk)
+{
+ TSL_Status_enum_T retval;
+ TSL_Status_enum_T acq_status;
+ TSL_tIndex_T idx_ch;
+ TSL_tIndexDest_T idx_dest;
+ TSL_tMeas_T new_meas;
+ static TSL_tIndex_T calibration_ongoing = 0;
+ static TSL_tNb_T calibration_done = 0;
+ static TSL_tNb_T div;
+ CONST TSL_Bank_T *bank;
+ CONST TSL_ChannelDest_T *pchDest; // Pointer to the current channel
+ CONST TSL_ChannelSrc_T *pchSrc; // Pointer to the current channel
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ bank = &(TSL_Globals.Bank_Array[idx_bk]);
+
+ if (calibration_ongoing == 0)
+ {
+ switch (TSL_Params.NbCalibSamples)
+ {
+ case 4:
+ div = 2;
+ break;
+ case 16:
+ div = 4;
+ break;
+ default:
+ TSL_Params.NbCalibSamples = 8;
+ div = 3;
+ break;
+ }
+ // Clear data for all channels of the bank
+ TSL_acq_BankClearData(idx_bk);
+ // Configure bank
+ if (TSL_acq_BankConfig(idx_bk) == TSL_STATUS_OK)
+ {
+ // Start acquisition
+ TSL_acq_BankStartAcq();
+ calibration_ongoing = 1; // Calibration started
+ calibration_done = TSL_Params.NbCalibSamples;
+ retval = TSL_STATUS_BUSY;
+ }
+ else
+ {
+ // Stop calibration
+ // Clear data for all channels of the bank
+ TSL_acq_BankClearData(idx_bk);
+ calibration_ongoing = 0;
+ retval = TSL_STATUS_ERROR;
+ }
+
+ }
+ else // Calibration is on-going
+ {
+ // Check End of Acquisition
+ acq_status = TSL_acq_BankWaitEOC();
+ if (acq_status == TSL_STATUS_OK)
+ {
+
+ // Get the first channel of the bank
+ pchDest = bank->p_chDest;
+ pchSrc = bank->p_chSrc;
+
+ // Get new measurement for all channels of the bank
+ for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
+ {
+
+ // Get index of the current channel
+ idx_dest = pchDest->IdxDest;
+
+ // Get the new measure (the access is different between acquisitions)
+ new_meas = TSL_acq_GetMeas(pchSrc->IdxSrc);
+
+ // Check min/max and set status flag
+ if ((new_meas < TSL_Params.AcqMin) || (new_meas > TSL_Params.AcqMax))
+ {
+ // Stop calibration
+ // Clear data for all channels of the bank
+ TSL_acq_BankClearData(idx_bk);
+ calibration_ongoing = 0;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ // Add the measure
+ bank->p_chData[idx_dest].Ref += new_meas;
+ }
+
+ // Next channel
+ pchDest++;
+ pchSrc++;
+ }
+
+ // Check that we have all the needed measurements
+ calibration_done--;
+ if (calibration_done == 0)
+ {
+
+ // Get the first channel of the bank
+ pchDest = bank->p_chDest;
+
+ // Calculate the Reference for all channels of the bank
+ for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
+ {
+ // Get index of the current channel
+ idx_dest = pchDest->IdxDest;
+ // Divide the Reference by the number of samples
+ bank->p_chData[idx_dest].Ref >>= div;
+ // Next channel
+ pchDest++;
+ }
+
+ // End
+ calibration_ongoing = 0;
+ retval = TSL_STATUS_OK;
+ }
+ else // Restart a new measurement on the bank
+ {
+ TSL_acq_BankStartAcq();
+ retval = TSL_STATUS_BUSY;
+ }
+ }
+ else
+ if (acq_status == TSL_STATUS_ERROR)
+ {
+ // Stop calibration
+ // Clear data for all channels of the bank
+ TSL_acq_BankClearData(idx_bk);
+ calibration_ongoing = 0;
+ retval = TSL_STATUS_ERROR;
+ }
+ else
+ {
+ retval = TSL_STATUS_BUSY;
+ }
+ }
+
+ return retval;
+}
+
+
+/**
+ * @brief Clear Reference and Delta on all channels of a Bank
+ * @param[in] idx_bk Index of the Bank to access
+ * @retval None
+ */
+void TSL_acq_BankClearData(TSL_tIndex_T idx_bk)
+{
+ TSL_tIndex_T idx_ch;
+ TSL_tIndexDest_T idx_Dest;
+ CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ // For all channels of the bank
+ for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
+ {
+ idx_Dest = pchDest->IdxDest;
+ bank->p_chData[idx_Dest].Ref = 0;
+ bank->p_chData[idx_Dest].Delta = 0;
+ pchDest++; // Next channel
+ }
+}
+
+
+#if TSLPRM_USE_ZONE > 0
+
+/**
+ * @brief Configures a Zone.
+ * @param[in] zone Zone to configure
+ * @param[in] idx_bk Bank index in the zone to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_ZoneConfig(CONST TSL_Zone_T *zone, TSL_tIndex_T idx_bk)
+{
+ TSL_Status_enum_T retval;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ TSL_Globals.This_Zone = zone;
+
+ do
+ {
+ retval = TSL_acq_BankConfig(zone->BankIndex[idx_bk]);
+ TSL_Globals.This_Bank = zone->BankIndex[idx_bk];
+ idx_bk++;
+ }
+ while ((idx_bk < zone->NbBanks) && (retval == TSL_STATUS_ERROR));
+
+ TSL_Globals.Index_In_This_Zone = idx_bk;
+
+#if TSLPRM_PXS_LOW_POWER_MODE > 0
+ if (idx_bk < zone->NbBanks)
+ {
+ resetPXSLowPower();
+ }
+#endif
+
+ return(retval);
+
+}
+
+#endif
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f0xx.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f0xx.c
new file mode 100644
index 0000000..a0967a9
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f0xx.c
@@ -0,0 +1,1008 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm32f0xx.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the TSC acquisition
+ * on STM32F0xx products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm32f0xx.h"
+#include "tsl_globals.h"
+#include "stm32f0xx_it.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+#define NU (0) // Not Used IO
+#define CHANNEL (1) // Channel IO
+#define SHIELD (2) // Shield IO (= Channel IO but not acquired)
+#define SAMPCAP (3) // Sampling Capacitor IO
+
+/* Private macros ------------------------------------------------------------*/
+
+// Used by assert
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
+#define IS_SRC_INDEX_0_5_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < 6)))
+#define IS_SRC_INDEX_0_7_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < 8)))
+
+/* Private variables ---------------------------------------------------------*/
+uint32_t DelayDischarge;
+
+/* Private functions prototype -----------------------------------------------*/
+void SoftDelay(uint32_t val);
+
+/**
+ * @brief Initializes the TouchSensing GPIOs.
+ * @param None
+ * @retval None
+ */
+void TSL_acq_InitGPIOs(void)
+{
+
+ GPIO_InitTypeDef GPIO_InitStructure;
+ uint32_t tmp_value_0;
+ uint32_t tmp_value_1;
+
+ //====================
+ // GPIOs configuration
+ //====================
+
+ // Enable GPIOs clocks
+ RCC->AHBENR |= (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN
+#if (TSC_GROUP7_ENABLED > 0) || (TSC_GROUP8_ENABLED > 0)
+ | RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOEEN
+#endif
+ );
+
+ // Alternate function Output Open-Drain for Sampling Capacitor IOs
+ //----------------------------------------------------------------
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+
+ // GPIOA
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP1_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_9;
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_10;
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_11;
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ // GPIOB
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP3_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_11;
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+ // GPIOC
+#if TSLPRM_TSC_GROUP3_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
+#endif
+
+#if (TSC_GROUP8_ENABLED > 0)
+ // GPIOD
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP8_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_15;
+#endif
+ GPIO_Init(GPIOD, &GPIO_InitStructure);
+#endif // TSC_GROUP8_ENABLED
+
+#if (TSC_GROUP7_ENABLED > 0)
+// GPIOE
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP7_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+ GPIO_Init(GPIOE, &GPIO_InitStructure);
+#endif // TSC_GROUP7_ENABLED
+
+ // Alternate function Output Push-Pull for Channel and Shield IOs
+ //---------------------------------------------------------------
+
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+
+ // GPIOA
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP1_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if (TSLPRM_TSC_GROUP1_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if (TSLPRM_TSC_GROUP1_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if (TSLPRM_TSC_GROUP1_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_9;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_10;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_11;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ // GPIOB
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP3_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if (TSLPRM_TSC_GROUP3_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if (TSLPRM_TSC_GROUP3_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_11;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+ // GPIOC
+#if (TSLPRM_TSC_GROUP3_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
+#endif
+
+#if (TSC_GROUP8_ENABLED > 0)
+ // GPIOD
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP8_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if (TSLPRM_TSC_GROUP8_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if (TSLPRM_TSC_GROUP8_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#if (TSLPRM_TSC_GROUP8_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_15;
+#endif
+ GPIO_Init(GPIOD, &GPIO_InitStructure);
+#endif // TSC_GROUP8_ENABLED
+
+#if (TSC_GROUP7_ENABLED > 0)
+ // GPIOE
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP7_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if (TSLPRM_TSC_GROUP7_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP7_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP7_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+ GPIO_Init(GPIOE, &GPIO_InitStructure);
+#endif // TSC_GROUP7_ENABLED
+
+ // Set Alternate-Function AF3 for GPIOA and GPIOB
+ //-----------------------------------------------
+
+ // GPIOA
+ tmp_value_0 = 0;
+ tmp_value_1 = 0;
+#if TSLPRM_TSC_GROUP1_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (0 * 4));
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+ GPIOA->AFR[0] |= tmp_value_0;
+ GPIOA->AFR[1] |= tmp_value_1;
+
+ // GPIOB
+ tmp_value_0 = 0;
+ tmp_value_1 = 0;
+#if TSLPRM_TSC_GROUP3_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (0 * 4));
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+ GPIOB->AFR[0] |= tmp_value_0;
+ GPIOB->AFR[1] |= tmp_value_1;
+
+ // Set Alternate-Function AF1 for GPIOD and GPIOE
+ //-----------------------------------------------
+
+#if (TSC_GROUP8_ENABLED > 0)
+ // GPIOD
+ tmp_value_1 = 0;
+#if TSLPRM_TSC_GROUP8_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)1 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)1 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)1 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)1 << (7 * 4));
+#endif
+ GPIOD->AFR[1] |= tmp_value_1;
+#endif // TSC_GROUP8_ENABLED
+
+#if (TSC_GROUP7_ENABLED > 0)
+ // GPIOE
+ tmp_value_0 = 0;
+#if TSLPRM_TSC_GROUP7_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << (5 * 4));
+#endif
+ GPIOE->AFR[0] |= tmp_value_0;
+#endif // TSC_GROUP7_ENABLED
+
+ //==================
+ // TSC configuration
+ //==================
+
+ // Enable TSC clock
+ RCC->AHBENR |= RCC_AHBENR_TSEN;
+
+ // Disable Schmitt trigger hysteresis on all used TS IOs (Channel, Shield and Sampling IOs)
+ //-----------------------------------------------------------------------------------------
+
+ tmp_value_0 = 0xFFFFFFFF;
+#if TSLPRM_TSC_GROUP1_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 0);
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 1);
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 2);
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 3);
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 4);
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 5);
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 6);
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 7);
+#endif
+#if TSLPRM_TSC_GROUP3_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 8);
+#endif
+#if TSLPRM_TSC_GROUP3_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 9);
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 10);
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 11);
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 12);
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 13);
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 14);
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 15);
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 16);
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 17);
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 18);
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 19);
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 20);
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 21);
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 22);
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 23);
+#endif
+
+#if (TSC_GROUP7_ENABLED > 0)
+#if TSLPRM_TSC_GROUP7_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 24);
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 25);
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 26);
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 27);
+#endif
+#endif // TSC_GROUP7_ENABLED
+
+#if (TSC_GROUP8_ENABLED > 0)
+#if TSLPRM_TSC_GROUP8_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 28);
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 29);
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 30);
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 31);
+#endif
+#endif // TSC_GROUP8_ENABLED
+
+ TSC->IOHCR &= tmp_value_0;
+
+ // Set Sampling Capacitor IOs
+ //---------------------------
+
+ tmp_value_0 = 0;
+#if TSLPRM_TSC_GROUP1_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 0);
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 1);
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 2);
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 3);
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 4);
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 5);
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 6);
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 7);
+#endif
+#if TSLPRM_TSC_GROUP3_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 8);
+#endif
+#if TSLPRM_TSC_GROUP3_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 9);
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 10);
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 11);
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 12);
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 13);
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 14);
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 15);
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 16);
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 17);
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 18);
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 19);
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 20);
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 21);
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 22);
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 23);
+#endif
+
+#if (TSC_GROUP7_ENABLED > 0)
+#if TSLPRM_TSC_GROUP7_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 24);
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 25);
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 26);
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 27);
+#endif
+#endif // TSC_GROUP7_ENABLED
+
+#if (TSC_GROUP8_ENABLED > 0)
+#if TSLPRM_TSC_GROUP8_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 28);
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 29);
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 30);
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 31);
+#endif
+#endif // TSC_GROUP8_ENABLED
+
+ TSC->IOSCR |= tmp_value_0;
+
+}
+
+
+/**
+ * @brief Initializes the acquisition module.
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+
+#if TSLPRM_TSC_GPIO_CONFIG > 0
+ TSL_acq_InitGPIOs();
+#endif
+
+ // Enable TSC clock
+ RCC->AHBENR |= RCC_AHBENR_TSEN;
+
+ // TSC enabled
+ TSC->CR = 0x01;
+
+ // Set CTPH
+#if TSLPRM_TSC_CTPH > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_CTPH << 28) & 0xF0000000;
+#endif
+
+ // Set CTPL
+#if TSLPRM_TSC_CTPL > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_CTPL << 24) & 0x0F000000;
+#endif
+
+ // Set SpreadSpectrum
+#if TSLPRM_TSC_USE_SS > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_USE_SS << 16) & 0x00010000;
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_SSD << 17) & 0x00FE0000;
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_SSPSC << 15) & 0x00008000;
+#endif
+
+ // Set Prescaler
+#if TSLPRM_TSC_PGPSC > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_PGPSC << 12) & 0x00007000;
+#endif
+
+ // Set Max Count
+#if TSLPRM_TSC_MCV > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_MCV << 5) & 0x000000E0;
+#endif
+
+ // Set IO default in Output PP Low to discharge all capacitors
+ TSC->CR &= (uint32_t)(~(1 << 4));
+
+ // Set Synchronization Mode
+#if TSLPRM_TSC_AM > 0
+
+ // Set Synchronization Pin in Alternate-Function mode
+ RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Set GPIOB clock
+
+#if TSLPRM_TSC_SYNC_PIN == 0 // PB08
+ GPIOB->MODER &= 0xFFFCFFFF;
+ GPIOB->MODER |= 0x00020000;
+ GPIOB->AFR[1] |= 0x00000003;
+#else // PB10
+ GPIOB->MODER &= 0xFFCFFFFF;
+ GPIOB->MODER |= 0x00200000;
+ GPIOB->AFR[1] |= 0x00000300;
+#endif
+
+ // Set Synchronization Polarity
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_SYNC_POL << 3) & 0x00000008;
+
+ // Set acquisition mode
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_AM << 2) & 0x00000004;
+
+#endif
+
+#if TSLPRM_USE_ACQ_INTERRUPT > 0
+
+ // Set both EOA and MCE interrupts
+ TSC->IER |= 0x03;
+
+ // Configure NVIC
+ NVIC_SetPriority(TSC_IRQn, 0);
+ NVIC_EnableIRQ(TSC_IRQn);
+
+#endif
+
+ // Initialize the delay that will be used to discharge the capacitors
+ DelayDischarge = (uint32_t)((TSLPRM_DELAY_DISCHARGE_ALL * (uint32_t)(SystemCoreClock/1000000)) / 48);
+
+ return TSL_STATUS_OK;
+
+}
+
+
+/**
+ * @brief Configures a Bank.
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ uint32_t idx_ch;
+ uint32_t objs; /* bit field of TSL_ObjStatus_enum_T type */
+ uint32_t gx;
+ uint32_t ioy;
+ CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;
+ CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ // Mark the current bank processed
+ TSL_Globals.This_Bank = idx_bk;
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // Enable the Gx_IOy used as channels (channels + shield)
+ TSC->IOCCR = bank->msk_IOCCR_channels;
+ // Enable acquisition on selected Groups
+ TSC->IOGCSR = bank->msk_IOGCSR_groups;
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ // For all channels of the bank check if they are OFF or BURST_ONLY
+ // and set acquisition status flag
+ for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
+ {
+
+ // Check Object status flag
+ objs = bank->p_chData[pchDest->IdxDest].Flags.ObjStatus;
+
+ if (objs != TSL_OBJ_STATUS_ON)
+ {
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // Get the Channel Group mask
+ gx = pchSrc->msk_IOGCSR_group;
+ // Stop acquisition of the Group
+ TSC->IOGCSR &= (uint32_t)~gx;
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ if (objs == TSL_OBJ_STATUS_OFF)
+ {
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // Get the Channel IO mask
+ ioy = pchSrc->msk_IOCCR_channel;
+ // Stop Burst of the Channel
+ TSC->IOCCR &= (uint32_t)~ioy;
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ }
+ }
+
+ // Next channel
+ pchSrc++;
+ pchDest++;
+ }
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Start acquisition on a previously configured bank
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+ // Clear both EOAIC and MCEIC flags
+ TSC->ICR |= 0x03;
+
+ // Wait capacitors discharge
+ SoftDelay(DelayDischarge);
+
+#if TSLPRM_TSC_IODEF > 0 // Default = Input Floating
+ // Set IO default in Input Floating
+ TSC->CR |= (1 << 4);
+#endif
+
+ // Start acquisition
+ TSC->CR |= 0x02;
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ TSL_Status_enum_T retval = TSL_STATUS_BUSY;
+
+ // Check EOAF flag
+ if (TSC->ISR & 0x01)
+ {
+
+#if TSLPRM_TSC_IODEF > 0 // Default = Input Floating
+ // Set IO default in Output PP Low to discharge all capacitors
+ TSC->CR &= (uint32_t)(~(1 << 4));
+#endif
+
+ // Check MCEF flag
+ if (TSC->ISR & 0x02)
+ {
+ retval = TSL_STATUS_ERROR;
+ }
+ else
+ {
+ retval = TSL_STATUS_OK;
+ }
+ }
+
+ return retval;
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndex_T index)
+{
+ // Check parameters (if USE_FULL_ASSERT is defined)
+#if (TSC_GROUP7_ENABLED > 0) || (TSC_GROUP8_ENABLED > 0)
+ assert_param(IS_SRC_INDEX_0_7_OK(idx_bk));
+#else
+ assert_param(IS_SRC_INDEX_0_5_OK(idx_bk));
+#endif
+ return((TSL_tMeas_T)(TSC->IOGXCR[index]));
+}
+
+
+/**
+ * @brief Compute the Delta value
+ * @param[in] ref Reference value
+ * @param[in] meas Last Measurement value
+ * @retval Delta value
+ */
+TSL_tDelta_T TSL_acq_ComputeDelta(TSL_tRef_T ref, TSL_tMeas_T meas)
+{
+ return((TSL_tDelta_T)(ref - meas));
+}
+
+
+/**
+ * @brief Compute the Measurement value
+ * @param[in] ref Reference value
+ * @param[in] delta Delta value
+ * @retval Measurement value
+ */
+TSL_tMeas_T TSL_acq_ComputeMeas(TSL_tRef_T ref, TSL_tDelta_T delta)
+{
+ return((TSL_tMeas_T)(ref - delta));
+}
+
+
+/**
+ * @brief Check noise (not used)
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ return TSL_ACQ_STATUS_OK;
+}
+
+
+/**
+ * @brief Check if a filter must be used on the current channel (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if a filter can be applied
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ return TSL_TRUE;
+}
+
+
+/**
+ * @brief Test if the Reference is incorrect (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if the Reference is out of range
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ return TSL_FALSE;
+}
+
+
+/**
+ * @brief Test if the measure has crossed the reference target (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result TRUE if the Reference is valid
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ return TSL_TRUE;
+}
+
+
+#if defined(__IAR_SYSTEMS_ICC__) // IAR/EWARM
+#pragma optimize=low
+#elif defined(__CC_ARM) // Keil/MDK-ARM
+#pragma O1
+#pragma Ospace
+#elif defined(__TASKING__) // Altium/Tasking
+#pragma optimize O0
+#elif defined(__GNUC__) // Atollic/True Studio + Raisonance/RKit
+#pragma GCC push_options
+#pragma GCC optimize ("O0")
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * @retval None
+ * @note Measurements done with HCLK=48MHz and Keil/MDK-ARM compiler
+ * val = 500: ~ 53s
+ * val = 1000: ~106s
+ * val = 2000: ~210s
+ */
+void SoftDelay(uint32_t val)
+{
+ uint32_t idx;
+ for (idx = val; idx > 0; idx--)
+ {}
+}
+#if defined(__TASKING__)
+#pragma endoptimize
+#endif
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f3xx.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f3xx.c
new file mode 100644
index 0000000..c75a791
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32f3xx.c
@@ -0,0 +1,1148 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm32f3xx.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the TSC acquisition
+ * on STM32F3xx products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm32f3xx.h"
+#include "tsl_globals.h"
+#if defined(STM32F30X)
+#include "stm32f30x_it.h"
+#endif
+#if defined(STM32F37X)
+#include "stm32f37x_it.h"
+#endif
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+#define NU (0) // Not Used IO
+#define CHANNEL (1) // Channel IO
+#define SHIELD (2) // Shield IO (= Channel IO but not acquired)
+#define SAMPCAP (3) // Sampling Capacitor IO
+
+/* Private macros ------------------------------------------------------------*/
+
+// Used by assert
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
+#define IS_SRC_INDEX_0_7_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < 8)))
+
+/* Private variables ---------------------------------------------------------*/
+uint32_t DelayDischarge;
+
+/* Private functions prototype -----------------------------------------------*/
+void SoftDelay(uint32_t val);
+
+/**
+ * @brief Initializes the TouchSensing GPIOs.
+ * @param None
+ * @retval None
+ */
+void TSL_acq_InitGPIOs(void)
+{
+
+ GPIO_InitTypeDef GPIO_InitStructure;
+ uint32_t tmp_value_0;
+ uint32_t tmp_value_1;
+
+ //====================
+ // GPIOs configuration
+ //====================
+
+ // Enable GPIOs clocks
+ RCC->AHBENR |= (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN |
+ RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOEEN);
+
+ // Alternate function Output Open-Drain for Sampling Capacitor IOs
+ //----------------------------------------------------------------
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+
+ // GPIOA
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP1_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_9;
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_10;
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ // GPIOB
+ GPIO_InitStructure.GPIO_Pin = 0;
+
+#if defined(STM32F30X)
+#if TSLPRM_TSC_GROUP3_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_11;
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#endif // STM32F30X
+
+#if defined(STM32F37X)
+#if TSLPRM_TSC_GROUP3_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_15;
+#endif
+#endif // STM32F37X
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+ // GPIOC
+#if defined(STM32F30X)
+#if TSLPRM_TSC_GROUP3_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
+#endif
+#endif // STM32F30X
+
+#if defined(STM32F37X)
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP3_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP3_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
+#endif // STM32F37X
+
+ // GPIOD
+ GPIO_InitStructure.GPIO_Pin = 0;
+
+#if defined(STM32F37X)
+#if TSLPRM_TSC_GROUP6_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
+#endif
+#endif // STM32F37X
+
+#if TSLPRM_TSC_GROUP8_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
+#endif
+ GPIO_Init(GPIOD, &GPIO_InitStructure);
+
+ // GPIOE
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if TSLPRM_TSC_GROUP7_IO1 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 == SAMPCAP
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+#endif
+ GPIO_Init(GPIOE, &GPIO_InitStructure);
+
+ // Alternate function Output Push-Pull for Channel and Shield IOs
+ //---------------------------------------------------------------
+
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+
+ // GPIOA
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP1_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if (TSLPRM_TSC_GROUP1_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if (TSLPRM_TSC_GROUP1_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if (TSLPRM_TSC_GROUP1_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP1_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if (TSLPRM_TSC_GROUP2_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP2_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_9;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_10;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if (TSLPRM_TSC_GROUP4_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP4_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ // GPIOB
+ GPIO_InitStructure.GPIO_Pin = 0;
+
+#if defined(STM32F30X)
+#if (TSLPRM_TSC_GROUP3_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if (TSLPRM_TSC_GROUP3_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if (TSLPRM_TSC_GROUP3_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_11;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#endif // STM32F30X
+
+#if defined(STM32F37X)
+#if (TSLPRM_TSC_GROUP3_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_0;
+#endif
+#if (TSLPRM_TSC_GROUP3_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_1;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_6;
+#endif
+#if (TSLPRM_TSC_GROUP5_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP5_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_7;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_15;
+#endif
+#endif // STM32F37X
+
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
+
+ // GPIOC
+
+#if defined(STM32F30X)
+#if (TSLPRM_TSC_GROUP3_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
+#endif
+#endif // STM32F30X
+
+#if defined(STM32F37X)
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP3_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP3_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP3_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+ GPIO_Init(GPIOC, &GPIO_InitStructure);
+#endif // STM32F37X
+
+ // GPIOD
+ GPIO_InitStructure.GPIO_Pin = 0;
+
+#if defined(STM32F37X)
+#if (TSLPRM_TSC_GROUP6_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_8;
+#endif
+#if (TSLPRM_TSC_GROUP6_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP6_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_9;
+#endif
+#endif // STM32F37X
+
+#if (TSLPRM_TSC_GROUP8_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_12;
+#endif
+#if (TSLPRM_TSC_GROUP8_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_13;
+#endif
+#if (TSLPRM_TSC_GROUP8_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_14;
+#endif
+#if (TSLPRM_TSC_GROUP8_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP8_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_15;
+#endif
+ GPIO_Init(GPIOD, &GPIO_InitStructure);
+
+ // GPIOE
+ GPIO_InitStructure.GPIO_Pin = 0;
+#if (TSLPRM_TSC_GROUP7_IO1 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO1 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_2;
+#endif
+#if (TSLPRM_TSC_GROUP7_IO2 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO2 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_3;
+#endif
+#if (TSLPRM_TSC_GROUP7_IO3 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO3 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_4;
+#endif
+#if (TSLPRM_TSC_GROUP7_IO4 == CHANNEL) || (TSLPRM_TSC_GROUP7_IO4 == SHIELD)
+ GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_5;
+#endif
+ GPIO_Init(GPIOE, &GPIO_InitStructure);
+
+ // Set Alternate-Function AF3 on used TSC IOs
+ //-------------------------------------------
+
+ // GPIOA
+ tmp_value_0 = 0;
+ tmp_value_1 = 0;
+#if TSLPRM_TSC_GROUP1_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (0 * 4));
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+ GPIOA->AFR[0] |= tmp_value_0;
+ GPIOA->AFR[1] |= tmp_value_1;
+
+ // GPIOB
+ tmp_value_0 = 0;
+ tmp_value_1 = 0;
+
+#if defined(STM32F30X)
+#if TSLPRM_TSC_GROUP3_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (0 * 4));
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#endif // STM32F30X
+
+#if defined(STM32F37X)
+#if TSLPRM_TSC_GROUP3_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (0 * 4));
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+#endif // STM32F37X
+
+ GPIOB->AFR[0] |= tmp_value_0;
+ GPIOB->AFR[1] |= tmp_value_1;
+
+ // GPIOC
+#if defined(STM32F30X)
+#if TSLPRM_TSC_GROUP3_IO1 != NU
+ GPIOC->AFR[0] |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#endif // STM32F30X
+
+#if defined(STM32F37X)
+#if TSLPRM_TSC_GROUP3_IO1 != NU
+ GPIOC->AFR[0] |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP3_IO2 != NU
+ GPIOC->AFR[0] |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#endif // STM32F37X
+
+ // GPIOD
+ tmp_value_1 = 0;
+
+#if defined(STM32F37X)
+#if TSLPRM_TSC_GROUP6_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (0 * 4));
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (1 * 4));
+#endif
+#endif // STM32F37X
+
+#if TSLPRM_TSC_GROUP8_IO1 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (6 * 4));
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 != NU
+ tmp_value_1 |= (uint32_t)((uint32_t)3 << (7 * 4));
+#endif
+ GPIOD->AFR[1] |= tmp_value_1;
+
+ // GPIOE
+ tmp_value_0 = 0;
+#if TSLPRM_TSC_GROUP7_IO1 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (2 * 4));
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (3 * 4));
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (4 * 4));
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 != NU
+ tmp_value_0 |= (uint32_t)((uint32_t)3 << (5 * 4));
+#endif
+ GPIOE->AFR[0] |= tmp_value_0;
+
+ //==================
+ // TSC configuration
+ //==================
+
+ // Enable TSC clock
+ RCC->AHBENR |= RCC_AHBENR_TSEN;
+
+ // Disable Schmitt trigger hysteresis on all used TS IOs (Channel, Shield and Sampling IOs)
+ //-----------------------------------------------------------------------------------------
+
+ tmp_value_0 = 0xFFFFFFFF;
+#if TSLPRM_TSC_GROUP1_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 0);
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 1);
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 2);
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 3);
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 4);
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 5);
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 6);
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 7);
+#endif
+#if TSLPRM_TSC_GROUP3_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 8);
+#endif
+#if TSLPRM_TSC_GROUP3_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 9);
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 10);
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 11);
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 12);
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 13);
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 14);
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 15);
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 16);
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 17);
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 18);
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 19);
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 20);
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 21);
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 22);
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 23);
+#endif
+#if TSLPRM_TSC_GROUP7_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 24);
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 25);
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 26);
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 27);
+#endif
+#if TSLPRM_TSC_GROUP8_IO1 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 28);
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 29);
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 30);
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 != NU
+ tmp_value_0 &= (uint32_t)~((uint32_t)1 << 31);
+#endif
+ TSC->IOHCR &= tmp_value_0;
+
+ // Set Sampling Capacitor IOs
+ //---------------------------
+
+ tmp_value_0 = 0;
+#if TSLPRM_TSC_GROUP1_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 0);
+#endif
+#if TSLPRM_TSC_GROUP1_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 1);
+#endif
+#if TSLPRM_TSC_GROUP1_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 2);
+#endif
+#if TSLPRM_TSC_GROUP1_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 3);
+#endif
+#if TSLPRM_TSC_GROUP2_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 4);
+#endif
+#if TSLPRM_TSC_GROUP2_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 5);
+#endif
+#if TSLPRM_TSC_GROUP2_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 6);
+#endif
+#if TSLPRM_TSC_GROUP2_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 7);
+#endif
+#if TSLPRM_TSC_GROUP3_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 8);
+#endif
+#if TSLPRM_TSC_GROUP3_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 9);
+#endif
+#if TSLPRM_TSC_GROUP3_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 10);
+#endif
+#if TSLPRM_TSC_GROUP3_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 11);
+#endif
+#if TSLPRM_TSC_GROUP4_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 12);
+#endif
+#if TSLPRM_TSC_GROUP4_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 13);
+#endif
+#if TSLPRM_TSC_GROUP4_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 14);
+#endif
+#if TSLPRM_TSC_GROUP4_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 15);
+#endif
+#if TSLPRM_TSC_GROUP5_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 16);
+#endif
+#if TSLPRM_TSC_GROUP5_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 17);
+#endif
+#if TSLPRM_TSC_GROUP5_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 18);
+#endif
+#if TSLPRM_TSC_GROUP5_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 19);
+#endif
+#if TSLPRM_TSC_GROUP6_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 20);
+#endif
+#if TSLPRM_TSC_GROUP6_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 21);
+#endif
+#if TSLPRM_TSC_GROUP6_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 22);
+#endif
+#if TSLPRM_TSC_GROUP6_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 23);
+#endif
+#if TSLPRM_TSC_GROUP7_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 24);
+#endif
+#if TSLPRM_TSC_GROUP7_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 25);
+#endif
+#if TSLPRM_TSC_GROUP7_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 26);
+#endif
+#if TSLPRM_TSC_GROUP7_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 27);
+#endif
+#if TSLPRM_TSC_GROUP8_IO1 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 28);
+#endif
+#if TSLPRM_TSC_GROUP8_IO2 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 29);
+#endif
+#if TSLPRM_TSC_GROUP8_IO3 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 30);
+#endif
+#if TSLPRM_TSC_GROUP8_IO4 == SAMPCAP
+ tmp_value_0 |= (uint32_t)((uint32_t)1 << 31);
+#endif
+ TSC->IOSCR |= tmp_value_0;
+
+}
+
+
+/**
+ * @brief Initializes the acquisition module.
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+
+#if TSLPRM_TSC_GPIO_CONFIG > 0
+ TSL_acq_InitGPIOs();
+#endif
+
+ // Enable TSC clock
+ RCC->AHBENR |= RCC_AHBENR_TSEN;
+
+ // TSC enabled
+ TSC->CR = 0x01;
+
+ // Set CTPH
+#if TSLPRM_TSC_CTPH > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_CTPH << 28) & 0xF0000000;
+#endif
+
+ // Set CTPL
+#if TSLPRM_TSC_CTPL > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_CTPL << 24) & 0x0F000000;
+#endif
+
+ // Set SpreadSpectrum
+#if TSLPRM_TSC_USE_SS > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_USE_SS << 16) & 0x00010000;
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_SSD << 17) & 0x00FE0000;
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_SSPSC << 15) & 0x00008000;
+#endif
+
+ // Set Prescaler
+#if TSLPRM_TSC_PGPSC > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_PGPSC << 12) & 0x00007000;
+#endif
+
+ // Set Max Count
+#if TSLPRM_TSC_MCV > 0
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_MCV << 5) & 0x000000E0;
+#endif
+
+ // Set IO default in Output PP Low to discharge all capacitors
+ TSC->CR &= (uint32_t)(~(1 << 4));
+
+ // Set Synchronization Mode
+#if TSLPRM_TSC_AM > 0
+
+ // Set Synchronization Pin in Alternate-Function mode
+#if TSLPRM_TSC_SYNC_PIN == 0 // PB08
+ RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Set GPIOB clock
+ GPIOB->MODER &= 0xFFFCFFFF;
+ GPIOB->MODER |= 0x00020000;
+ GPIOB->AFR[1] |= 0x00000003;
+#endif
+#if TSLPRM_TSC_SYNC_PIN == 1 // PB10
+ RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // Set GPIOB clock
+ GPIOB->MODER &= 0xFFCFFFFF;
+ GPIOB->MODER |= 0x00200000;
+ GPIOB->AFR[1] |= 0x00000300;
+#endif
+#if TSLPRM_TSC_SYNC_PIN == 2 // PA15
+ RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // Set GPIOA clock
+ GPIOA->MODER &= 0x3FFFFFFF;
+ GPIOA->MODER |= 0x80000000;
+ GPIOA->AFR[1] |= 0x30000000;
+#endif
+
+ // Set Synchronization Polarity
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_SYNC_POL << 3) & 0x00000008;
+
+ // Set acquisition mode
+ TSC->CR |= (uint32_t)((uint32_t)TSLPRM_TSC_AM << 2) & 0x00000004;
+
+#endif
+
+#if TSLPRM_USE_ACQ_INTERRUPT > 0
+
+ // Set both EOA and MCE interrupts
+ TSC->IER |= 0x03;
+
+ // Configure NVIC
+ NVIC_SetPriority(EXTI2_TS_IRQn, 0);
+ NVIC_EnableIRQ(EXTI2_TS_IRQn);
+
+#endif
+
+ // Initialize the delay that will be used to discharge the capacitors
+ DelayDischarge = (uint32_t)((TSLPRM_DELAY_DISCHARGE_ALL * (uint32_t)(SystemCoreClock/1000000)) / 72);
+
+ return TSL_STATUS_OK;
+
+}
+
+
+/**
+ * @brief Configures a Bank.
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ uint32_t idx_ch;
+ uint32_t objs; /* bit field of TSL_ObjStatus_enum_T type */
+ uint32_t gx;
+ uint32_t ioy;
+ CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;
+ CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ // Mark the current bank processed
+ TSL_Globals.This_Bank = idx_bk;
+
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // Enable the Gx_IOy used as channels (channels + shield)
+ TSC->IOCCR = bank->msk_IOCCR_channels;
+ // Enable acquisition on selected Groups
+ TSC->IOGCSR = bank->msk_IOGCSR_groups;
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ // For all channels of the bank check if they are OFF or BURST_ONLY
+ // and set acquisition status flag
+ for (idx_ch = 0; idx_ch < bank->NbChannels; idx_ch++)
+ {
+
+ // Check Object status flag
+ objs = bank->p_chData[pchDest->IdxDest].Flags.ObjStatus;
+
+ if (objs != TSL_OBJ_STATUS_ON)
+ {
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // Get the Channel Group mask
+ gx = pchSrc->msk_IOGCSR_group;
+ // Stop acquisition of the Group
+ TSC->IOGCSR &= (uint32_t)~gx;
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ if (objs == TSL_OBJ_STATUS_OFF)
+ {
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ // Get the Channel IO mask
+ ioy = pchSrc->msk_IOCCR_channel;
+ // Stop Burst of the Channel
+ TSC->IOCCR &= (uint32_t)~ioy;
+ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ }
+ }
+
+ // Next channel
+ pchSrc++;
+ pchDest++;
+ }
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Start acquisition on a previously configured bank
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+ // Clear both EOAIC and MCEIC flags
+ TSC->ICR |= 0x03;
+
+ // Wait capacitors discharge
+ SoftDelay(DelayDischarge);
+
+#if TSLPRM_TSC_IODEF > 0 // Default = Input Floating
+ // Set IO default in Input Floating
+ TSC->CR |= (1 << 4);
+#endif
+
+ // Start acquisition
+ TSC->CR |= 0x02;
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ TSL_Status_enum_T retval = TSL_STATUS_BUSY;
+
+ // Check EOAF flag
+ if (TSC->ISR & 0x01)
+ {
+
+#if TSLPRM_TSC_IODEF > 0 // Default = Input Floating
+ // Set IO default in Output PP Low to discharge all capacitors
+ TSC->CR &= (uint32_t)(~(1 << 4));
+#endif
+
+ // Check MCEF flag
+ if (TSC->ISR & 0x02)
+ {
+ retval = TSL_STATUS_ERROR;
+ }
+ else
+ {
+ retval = TSL_STATUS_OK;
+ }
+ }
+
+ return retval;
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndex_T index)
+{
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_SRC_INDEX_0_7_OK(idx_bk));
+ return((TSL_tMeas_T)(TSC->IOGXCR[index]));
+}
+
+
+/**
+ * @brief Compute the Delta value
+ * @param[in] ref Reference value
+ * @param[in] meas Last Measurement value
+ * @retval Delta value
+ */
+TSL_tDelta_T TSL_acq_ComputeDelta(TSL_tRef_T ref, TSL_tMeas_T meas)
+{
+ return((TSL_tDelta_T)(ref - meas));
+}
+
+
+/**
+ * @brief Compute the Measurement value
+ * @param[in] ref Reference value
+ * @param[in] delta Delta value
+ * @retval Measurement value
+ */
+TSL_tMeas_T TSL_acq_ComputeMeas(TSL_tRef_T ref, TSL_tDelta_T delta)
+{
+ return((TSL_tMeas_T)(ref - delta));
+}
+
+
+/**
+ * @brief Check noise (not used)
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ return TSL_ACQ_STATUS_OK;
+}
+
+
+/**
+ * @brief Check if a filter must be used on the current channel (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if a filter can be applied
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ return TSL_TRUE;
+}
+
+
+/**
+ * @brief Test if the Reference is incorrect (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if the Reference is out of range
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ return TSL_FALSE;
+}
+
+
+/**
+ * @brief Test if the measure has crossed the reference target (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result TRUE if the Reference is valid
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ return TSL_TRUE;
+}
+
+
+#if defined(__IAR_SYSTEMS_ICC__) // IAR/EWARM
+#pragma optimize=low
+#elif defined(__CC_ARM) // Keil/MDK-ARM
+#pragma O1
+#pragma Ospace
+#elif defined(__TASKING__) // Altium/Tasking
+#pragma optimize O0
+#elif defined(__GNUC__) // Atollic/True Studio + Raisonance/RKit
+#pragma GCC push_options
+#pragma GCC optimize ("O0")
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * @retval None
+ * @note Measurements done with HCLK=72MHz and Keil/MDK-ARM compiler
+ * val = 500: ~ 63s
+ * val = 1000: ~126s
+ * val = 2000: ~251s
+ */
+void SoftDelay(uint32_t val)
+{
+ uint32_t idx;
+ for (idx = val; idx > 0; idx--)
+ {}
+}
+#if defined(__TASKING__)
+#pragma endoptimize
+#endif
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_hw.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_hw.c
new file mode 100644
index 0000000..dd7048f
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_hw.c
@@ -0,0 +1,862 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm32l1xx_hw.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the acquisition
+ * on STM32l1xx products using the Hardware mode (with Timers).
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm32l1xx_hw.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+
+// Register configuration
+typedef struct
+{
+ unsigned int RI_ASCR : 3;
+ unsigned int RI_ASCR_bit : 5;
+} TSL_RIConf_t;
+
+/* Private defines -----------------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
+
+// Acquisition pulses period
+/** Master timer reload value for HW acquisition only (range=4..65534, even number)
+ --> Period for Charge/Transfer cycle = ((TSLPRM_TIM_RELOAD*2)/FTimer)
+*/
+#define TIM_RELOAD ((TSLPRM_CT_PERIOD * TSLPRM_TIMER_FREQ) / 2)
+#define TIM9_PWM_CH1_WIDTH ((TIM_RELOAD >> 1) + 1) // Configure channel 1 Pulse Width
+#define TIM9_PWM_CH2_WIDTH ((TIM_RELOAD >> 1) - 1) // Configure channel 2 Pulse Width
+
+#define TSL_CHANNEL_PORT(channel) (channel >> 4)
+#define TSL_CHANNEL_IO(channel) (channel & 0x0F)
+
+#define TSL_GPIO_AFR(channel) ((TSL_CHANNEL_IO(channel) < 8) ? 0 : 1)
+#define TSL_GPIO_AFR_Shift(channel) ((TSL_CHANNEL_IO(channel) < 8) ? (4 * TSL_CHANNEL_IO(channel)) : (4 * (TSL_CHANNEL_IO(channel) - 8)))
+
+#define TSL_RI_HYSCR_MASK(channel) (1 << TSL_CHANNEL_IO(channel))
+#define TSL_RI_ASMR_MASK(channel) (1 << TSL_CHANNEL_IO(channel))
+#define TSL_RI_CMR_MASK(channel) (1 << TSL_CHANNEL_IO(channel))
+#define TSL_RI_CICR_MASK(channel) (1 << TSL_CHANNEL_IO(channel))
+
+#define TSL_RCC_AHBENR_Config(channel) (RCC->AHBENR |= TSL_GPIO_Clock_LookUpTable[TSL_CHANNEL_PORT(channel)])
+
+#define TSL_RI_ASCR_Config(channel) (*TSL_RI_ASCR_LookUpTable[TSL_RI_Conf_LookUpTable[channel].RI_ASCR] |= (1 << (TSL_RI_Conf_LookUpTable[channel].RI_ASCR_bit)))
+#define TSL_RI_HYSCR_Config(channel) (*TSL_RI_HYSCR_LookUpTable[TSL_CHANNEL_PORT(channel)] |= TSL_RI_HYSCR_MASK(channel))
+#define TSL_RI_ASMR_Config(channel) (*TSL_RI_ASMR_LookUpTable[TSL_CHANNEL_PORT(channel)] |= TSL_RI_ASMR_MASK(channel))
+#define TSL_RI_ASMR_Config_Clear(channel) (*TSL_RI_ASMR_LookUpTable[TSL_CHANNEL_PORT(channel)] &= (uint32_t)(~TSL_RI_ASMR_MASK(channel)))
+#define TSL_RI_CMR_Config(channel) (*TSL_RI_CMR_LookUpTable[TSL_CHANNEL_PORT(channel)] |= TSL_RI_CMR_MASK(channel))
+#define TSL_RI_CMR_Config_Clear(channel) (*TSL_RI_CMR_LookUpTable[TSL_CHANNEL_PORT(channel)] &= (uint32_t)(~TSL_RI_CMR_MASK(channel)))
+#define TSL_RI_CICR_Config(channel) (*TSL_RI_CICR_LookUpTable[TSL_CHANNEL_PORT(channel)] |= TSL_RI_CICR_MASK(channel))
+#define TSL_RI_CICR_Config_Clear(channel) (*TSL_RI_CICR_LookUpTable[TSL_CHANNEL_PORT(channel)] &= (uint32_t)(~TSL_RI_CICR_MASK(channel)))
+
+#define TSL_GPIO_MODER_IN_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER &= (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel)))))
+#define TSL_GPIO_MODER_AF_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER = (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER & (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel))))) | (2 << (2 * TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_MODER_OUT_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER = (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER & (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel))))) | (1 << (2 * TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_PUPDR_NO_PUPD_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->PUPDR &= (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel)))))
+#define TSL_GPIO_OTYPER_PP_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->OTYPER &= (uint32_t)(~(1 << TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_OSPEEDR_VL_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->OSPEEDR &= (uint32_t)~(3 << (2 * TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_AFR_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->AFR[TSL_GPIO_AFR(channel)] |= (0x0E << (TSL_GPIO_AFR_Shift(channel))))
+#define TSL_GPIO_BS_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->BSRRL = (uint16_t)(1 << (TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_BR_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->BSRRH = (uint16_t)(1 << (TSL_CHANNEL_IO(channel))))
+
+#define TSL_GPIO_AFR_NOAF_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->AFR[TSL_GPIO_AFR(channel)] &= (uint32_t)(~(0x0F << (TSL_GPIO_AFR_Shift(channel)))))
+
+#define TSL_GPIO_IDR_XOR_RI_CMR(channel) ((TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->IDR)^(*TSL_RI_CMR_LookUpTable[TSL_CHANNEL_PORT(channel)]))
+#define TSL_GPIO_IDR_AND_RI_CMR(channel) ((TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->IDR)&(*TSL_RI_CMR_LookUpTable[TSL_CHANNEL_PORT(channel)]))
+
+/* Private variables ---------------------------------------------------------*/
+CONST TSL_Bank_T *bank;
+TSL_tIndex_T NumberOfChannelOn = 0;
+TSL_tNb_T NumberOfChannels = 0;
+uint32_t tab_MeasurementCounter[11];
+TSL_Status_enum_T TSL_Acq_Status = TSL_STATUS_BUSY;
+static uint16_t GroupToCheck = 0;
+static TSL_tIndex_T NumberOfChannelChecked = 0;
+
+uint32_t TSL_GPIO_Clock_LookUpTable[] = {RCC_AHBPeriph_GPIOA, RCC_AHBPeriph_GPIOB, RCC_AHBPeriph_GPIOC, RCC_AHBPeriph_GPIOD, RCC_AHBPeriph_GPIOE, RCC_AHBPeriph_GPIOF, RCC_AHBPeriph_GPIOG, RCC_AHBPeriph_GPIOH};
+GPIO_TypeDef *TSL_GPIO_LookUpTable[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH};
+
+uint32_t *TSL_RI_ASCR_LookUpTable[] = {(uint32_t *)&RI->ASCR1, (uint32_t *)&RI->ASCR2};
+
+uint16_t *TSL_RI_HYSCR_LookUpTable[] =
+{
+ (uint16_t *)&RI->HYSCR1, (uint16_t *)&RI->HYSCR1 + 1,
+ (uint16_t *)&RI->HYSCR2, (uint16_t *)&RI->HYSCR2 + 1,
+ (uint16_t *)&RI->HYSCR3, (uint16_t *)&RI->HYSCR3 + 1,
+ (uint16_t *)&RI->HYSCR4, (uint16_t *)&RI->HYSCR4 + 1
+};
+
+uint32_t *TSL_RI_ASMR_LookUpTable[] = {(uint32_t *)&RI->ASMR1, (uint32_t *)&RI->ASMR2, (uint32_t *)&RI->ASMR3, 0, 0, (uint32_t *)&RI->ASMR4, (uint32_t *)&RI->ASMR5};
+uint32_t *TSL_RI_CMR_LookUpTable[] = {(uint32_t *)&RI->CMR1, (uint32_t *)&RI->CMR2, (uint32_t *)&RI->CMR3, 0, 0, (uint32_t *)&RI->CMR4, (uint32_t *)&RI->CMR5};
+uint32_t *TSL_RI_CICR_LookUpTable[] = {(uint32_t *)&RI->CICR1, (uint32_t *)&RI->CICR2, (uint32_t *)&RI->CICR3, 0, 0, (uint32_t *)&RI->CICR4, (uint32_t *)&RI->CICR5};
+
+CONST TSL_RIConf_t TSL_RI_Conf_LookUpTable[101] =
+{
+ {0, 0},
+ {0, 1},
+ {0, 2},
+ {0, 3},
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 6},
+ {0, 7},
+ {1, 9},
+ {1, 10},
+ {1, 11},
+ {1, 15},
+ {0, 0},//padding
+ {1, 6},
+ {1, 7},
+ {1, 8},
+
+ {0, 8},
+ {0, 9},
+ {1, 16},
+ {0, 0},//padding
+ {1, 4},
+ {1, 5},
+ {1, 27},
+ {1, 28},
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 18},
+ {0, 19},
+ {0, 20},
+ {0, 21},
+
+ {0, 10},
+ {0, 11},
+ {0, 12},
+ {0, 13},
+ {0, 14},
+ {0, 15},
+ {1, 0},
+ {1, 1},
+ {1, 2},
+ {1, 3},
+ {1, 29},
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 27},
+ {0, 28},
+ {0, 29},
+ {0, 30},
+ {0, 16},
+ {1, 17},
+ {1, 18},
+ {1, 19},
+ {1, 20},
+ {1, 21},
+
+ {1, 22},
+ {1, 23},
+ {1, 24},
+ {1, 25},
+ {1, 26}
+};
+
+/* Private functions prototype -----------------------------------------------*/
+void TSL_Init_GPIOs(void);
+void TSL_Init_TIMs(void);
+void TSL_Init_RI(void);
+uint8_t TSL_Check_GPIO_IDR(uint8_t sample);
+void SoftDelay(uint16_t val);
+
+
+/**
+ * @brief Initializes the TouchSensing GPIOs.
+ * @param None
+ * @retval None
+ */
+void TSL_Init_GPIOs(void)
+{
+ CONST TSL_Bank_T *LocalBank = &(TSL_Globals.Bank_Array[0]);
+ TSL_tNb_T NumberOfBanks = TSLPRM_TOTAL_BANKS;
+ TSL_tNb_T LocalNumberOfChannels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+ CONST TSL_ChannelSrc_T *p_chSrc = LocalBank->p_chSrc; // Pointer to the current channel
+
+ for (idx_bk = 0; idx_bk < NumberOfBanks; idx_bk++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = LocalBank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Enables GPIOs clock
+ TSL_RCC_AHBENR_Config(LocalBank->shield_sample);
+
+ // Bank shield configuration
+ TSL_GPIO_OTYPER_PP_Config(LocalBank->shield_channel);
+ TSL_GPIO_OSPEEDR_VL_Config(LocalBank->shield_channel);
+ TSL_GPIO_PUPDR_NO_PUPD_Config(LocalBank->shield_channel);
+ TSL_GPIO_AFR_Config(LocalBank->shield_channel);
+
+ TSL_GPIO_OSPEEDR_VL_Config(LocalBank->shield_sample);
+ TSL_GPIO_BR_Config(LocalBank->shield_sample);
+ TSL_GPIO_OTYPER_PP_Config(LocalBank->shield_sample);
+ TSL_GPIO_PUPDR_NO_PUPD_Config(LocalBank->shield_sample);
+
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_sample);
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_channel);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < LocalNumberOfChannels;
+ idx_ch++)
+ {
+ TSL_RCC_AHBENR_Config(p_chSrc->t_sample);
+ TSL_RCC_AHBENR_Config(p_chSrc->t_channel);
+
+ TSL_GPIO_OTYPER_PP_Config(p_chSrc->t_channel);
+ TSL_GPIO_OSPEEDR_VL_Config(p_chSrc->t_channel);
+ TSL_GPIO_PUPDR_NO_PUPD_Config(p_chSrc->t_channel);
+ TSL_GPIO_AFR_Config(p_chSrc->t_channel);
+
+ TSL_GPIO_OSPEEDR_VL_Config(p_chSrc->t_sample);
+ TSL_GPIO_BR_Config(p_chSrc->t_sample);
+ TSL_GPIO_OTYPER_PP_Config(p_chSrc->t_sample);
+ TSL_GPIO_PUPDR_NO_PUPD_Config(p_chSrc->t_sample);
+
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_channel);
+
+ p_chSrc++;
+ }
+ }
+}
+
+/**
+ * @brief Initializes the TouchSensing timers.
+ * @param None
+ * @retval None
+ */
+// Acquisition pulses period
+/** Master timer reload value for HW acquisition only (range=4..65534, even number)
+ --> Period for Charge/Transfer cycle = ((TSLPRM_TIM_RELOAD*2)/FTimer)
+*/
+void TSL_Init_TIMs(void)
+{
+ // Enable Timers clocks
+ RCC->APB2ENR |= ((1 << 4) | (1 << 2)); // TIM11, TIM9
+
+ //==============================
+ // TIMER 9 configuration: Master
+ //==============================
+ // Set the option register to redirect RI_tim9_itr_O to TIM9_itr
+ TIM9->OR |= 4;
+ // Set the Autoreload value (signal frequency)
+ //TIM9->ARR = 64; // freq = (64*2)*31.25ns = 1us
+ TIM9->ARR = TIM_RELOAD; // freq = (64*2)*31.25ns = 1us
+ // Set the Prescaler value
+ //TIM9->PSC = 0; // fCK_CNT = 32MHz/(0+1) = 32MHz --> T=31.25ns
+ //TIM9->PSC = TSLPRM_TIM_PRESCALER; // fCK_CNT = 32MHz/(1+1) = 32MHz --> T=31.25ns
+ TIM9->PSC = 0; // fCK_CNT = 32MHz/(1+1) = 32MHz --> T=31.25ns
+ // Set UP counter, Center-Aligned mode 1
+ TIM9->CR1 = 0x20;
+ // OC1REF used as TRGO
+ TIM9->CR2 |= 0x40; // MMS=100
+ // Select Master mode
+ TIM9->SMCR = 0x95;
+ // Set Update generation
+ TIM9->EGR |= 0x01;
+
+ // Channel 1 PWM configuration
+ // Set the Output Compare Mode, PWM2
+ TIM9->CCMR1 |= 0x0070;
+ // Set the Pulse value
+ //TIM9->CCR1 = 34; // duty cycle
+ TIM9->CCR1 = TIM9_PWM_CH1_WIDTH; // duty cycle
+ // Compare output enable, active high
+ TIM9->CCER |= 0x01;
+
+ // Channel 2 PWM configuration
+ // Set the Output Compare Mode, PWM2
+ TIM9->CCMR1 |= 0x6000;
+ // Set the Pulse value
+ //TIM9->CCR2 = 30;
+ TIM9->CCR2 = TIM9_PWM_CH2_WIDTH;
+ // Compare output enable, active high
+ TIM9->CCER |= 0x10;
+
+ //==============================
+ // TIMER 11 configuration: slave
+ //==============================
+ // Set the option register to redirect TIM11_ic_o to TIM11_ti
+ TIM11->OR |= 8;
+ // Set the option register to redirect TIM9_tgo_cktim to TIM11_etri
+ TIM11->OR |= 4;
+ // Set the Prescaler value
+ TIM11->PSC = 0;
+ // Set UP counter, edge-aligned mode
+ TIM11->CR1 = 0;
+ // Select Slave mode, Internal Trigger 2 (ITR2 = TIM9), External clock mode 1
+ TIM11->SMCR = 0x4000; // ECE bit
+ // Channel 1 configured in Input capture mode
+ TIM11->CCMR1 = 0x01; // No prescaler, no filter
+ // Channel 1 capture enable (CCE1 = 1)
+ TIM11->CCER = 0x01;
+ // Set auto reload regarding the max count
+#if (TSLPRM_ACQ_MAX < 16534)
+ TIM11->ARR = TSLPRM_ACQ_MAX+1;
+#endif
+ // Interrupt Enable, active high, Enable interrupt when counter reaches max count (ARR)
+ TIM11->DIER |= 0x03;
+ // Start slave timer
+ TIM11->CR1 |= 0x01;
+}
+
+
+/**
+ * @brief Init TS routing interface.
+ * @param None
+ * @retval None
+ */
+void TSL_Init_RI(void)
+{
+ CONST TSL_Bank_T *LocalBank;
+ TSL_tNb_T NumberOfBanks = TSLPRM_TOTAL_BANKS;
+ TSL_tNb_T LocalNumberOfChannels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+ CONST TSL_ChannelSrc_T *p_chSrc; // Pointer to the current channel
+
+ RCC->APB1ENR |= (uint32_t)((uint32_t)1 << 31); // COMP enable
+
+ for (idx_bk = 0; idx_bk < NumberOfBanks; idx_bk++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[idx_bk]);
+
+#if (TSLPRM_USE_SHIELD > 0)
+ TSL_RI_HYSCR_Config(LocalBank->shield_sample);
+ TSL_RI_CICR_Config(LocalBank->shield_sample);
+ TSL_RI_CICR_Config_Clear(LocalBank->shield_channel);
+
+ TSL_RI_ASCR_Config(LocalBank->shield_sample);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ p_chSrc = LocalBank->p_chSrc;
+ for (idx_ch = 0; idx_ch < LocalNumberOfChannels; idx_ch++)
+ {
+ TSL_RI_HYSCR_Config(p_chSrc->t_sample);
+ TSL_RI_CICR_Config(p_chSrc->t_sample);
+ TSL_RI_CICR_Config_Clear(p_chSrc->t_channel);
+ TSL_RI_ASCR_Config(p_chSrc->t_sample);
+ p_chSrc++;
+ }
+ }
+
+ // Reset TSUSP bit, TIM9 ITR enabled to suspend OC TIM9 generation
+ COMP->CSR &= (uint32_t)(~0x80000000);
+
+}
+
+
+/**
+ * @brief Initializes the acquisition module.
+ * @param None
+ * @retval retval
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+ NVIC_InitTypeDef NVIC_InitStructure;
+
+ NVIC_InitStructure.NVIC_IRQChannel = TIM11_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure);
+
+ TSL_Init_GPIOs();
+ TSL_Init_TIMs();
+ TSL_Init_RI();
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Configures a Bank.
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ TSL_tIndex_T idx_dest;
+ TSL_tIndex_T idx_ch;
+ CONST TSL_ChannelDest_T *p_chDest; // Pointer to the current channel
+ CONST TSL_ChannelSrc_T *p_chSrc; // Pointer to the current channel
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ bank = &(TSL_Globals.Bank_Array[idx_bk]);
+
+ NumberOfChannels = bank->NbChannels;
+
+ GroupToCheck = 0;//init group to check
+ NumberOfChannelOn = 0;//init number of channel on
+
+ // init RI ASMR
+ RI->ASMR1 = 0;
+ RI->ASMR2 = 0;
+ RI->ASMR3 = 0;
+ RI->ASMR4 = 0;
+ RI->ASMR5 = 0;
+
+ p_chDest = bank->p_chDest;
+ p_chSrc = bank->p_chSrc;
+ for (idx_ch = 0; idx_ch < NumberOfChannels; idx_ch++)
+ {
+ // Get index in the result array associated to the current channel
+ idx_dest = p_chDest->IdxDest;
+ if (bank->p_chData[idx_dest].Flags.ObjStatus != TSL_OBJ_STATUS_OFF)
+ {
+ TSL_RI_CMR_Config(p_chSrc->t_sample);
+ TSL_RI_ASMR_Config(p_chSrc->t_channel);
+ GroupToCheck |= (1 << (p_chSrc->IdxSrc));
+ NumberOfChannelOn++;
+ }
+ p_chDest++;
+ p_chSrc++;
+ }
+
+ return TSL_STATUS_OK;
+
+}
+
+
+/**
+ * @brief Start acquisition on a previously configured bank
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+#if (TSLPRM_IODEF > 0)
+ CONST TSL_Bank_T *LocalBank = &(TSL_Globals.Bank_Array[0]);
+ TSL_tNb_T NumberOfBanks = TSLPRM_TOTAL_BANKS;
+ TSL_tNb_T LocalNumberOfChannels = 0;
+ TSL_tIndex_T BankIndex;
+#endif
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ CONST TSL_ChannelDest_T *p_chDest;
+ TSL_tIndex_T idx_dest;
+ TSL_tIndex_T idx_ch;
+
+ if (NumberOfChannelOn)
+ {
+#if (TSLPRM_IODEF > 0)
+ //============================
+ // All GPIOs in Input floating
+ //============================
+ for (BankIndex = 0; BankIndex < NumberOfBanks; BankIndex++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[BankIndex]);
+ p_chSrc = LocalBank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ TSL_GPIO_MODER_IN_Config(LocalBank->shield_sample);
+ TSL_GPIO_MODER_IN_Config(LocalBank->shield_channel);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < LocalNumberOfChannels;
+ idx_ch++)
+ {
+ TSL_GPIO_MODER_IN_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_IN_Config(p_chSrc->t_channel);
+
+ p_chSrc++;
+ }
+ }
+#endif
+
+
+ // Reset count
+ TIM11->CNT = 0;
+
+ // Discharge sample capacitors
+ p_chDest = bank->p_chDest;
+ p_chSrc = bank->p_chSrc;
+ for (idx_ch = 0; idx_ch < NumberOfChannels; idx_ch++)
+ {
+ // Get index in the result array associated to the current channel
+ idx_dest = p_chDest->IdxDest;
+ if (bank->p_chData[idx_dest].Flags.ObjStatus != TSL_OBJ_STATUS_OFF)
+ {
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_sample);
+ }
+ p_chDest++;
+ p_chSrc++;
+ }
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Discharge shield sample capacitor
+ TSL_GPIO_MODER_OUT_Config(bank->shield_sample);
+#endif
+
+ // Wait for capa discharge
+ SoftDelay(0x80);
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Init sample shield in floating input
+ TSL_GPIO_MODER_IN_Config(bank->shield_sample);
+ TSL_GPIO_MODER_AF_Config(bank->shield_channel);
+
+ TSL_RI_ASMR_Config(bank->shield_channel);
+#endif
+
+ // Init samples in floating input and channels in alternate
+ p_chDest = bank->p_chDest;
+ p_chSrc = bank->p_chSrc;
+ for (idx_ch = 0; idx_ch < NumberOfChannels; idx_ch++)
+ {
+ // Get index in the result array associated to the current channel
+ idx_dest = p_chDest->IdxDest;
+
+ if (bank->p_chData[idx_dest].Flags.ObjStatus != TSL_OBJ_STATUS_OFF)
+ {
+ TSL_GPIO_MODER_IN_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_AF_Config(p_chSrc->t_channel);
+ }
+
+ p_chDest++;
+ p_chSrc++;
+ }
+
+ /* Start acquisition */
+ TSL_Acq_Status = TSL_STATUS_BUSY;
+ TIM9 ->CR1 |= 0x01; // Master
+ }
+ else
+ {
+ TSL_Acq_Status = TSL_STATUS_OK;
+ }
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ return TSL_Acq_Status;
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndex_T index)
+{
+ return(tab_MeasurementCounter[index]);
+}
+
+
+/**
+ * @brief Check noise (not used)
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ return TSL_ACQ_STATUS_OK;
+}
+
+
+/**
+ * @brief Check GPIO IDR for the sample
+ * @param[in] sample
+ * @retval Status
+ */
+uint8_t TSL_Check_GPIO_IDR(uint8_t sample)
+{
+ GPIO_TypeDef *GPIO;
+ uint32_t GPIO_IDR_Mask = 0;
+
+ GPIO = TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(sample)];
+
+ GPIO_IDR_Mask = (1 << (sample & 0x0F));
+
+ if (((GPIO->IDR) & GPIO_IDR_Mask) == GPIO_IDR_Mask)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+/**
+ * @brief Process the TS Interrupt routine
+ * @param None
+ * @retval None
+ */
+void TSL_acq_ProcessIT(void)
+{
+ CONST TSL_Bank_T *LocalBank = &(TSL_Globals.Bank_Array[0]);
+ TSL_tNb_T NumberOfBanks = TSLPRM_TOTAL_BANKS;
+ TSL_tNb_T LocalNumberOfChannels = 0;
+ TSL_tIndex_T BankIndex;
+
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ CONST TSL_ChannelDest_T *p_chDest;
+ TSL_tIndex_T idx_dest;
+ TSL_tIndex_T idx_ch;
+ TSL_tNb_T CounterOverflowFlag = 0;
+
+ CounterOverflowFlag = TIM11->SR & TIM_SR_UIF;
+
+ // Reset flags
+ TIM11->SR = 0;
+ idx_ch = 0;
+
+ p_chDest = bank->p_chDest;
+ p_chSrc = bank->p_chSrc;
+ do
+ {
+ // Get index in the result array associated to the current channel
+ idx_dest = p_chDest->IdxDest;
+
+ if (bank->p_chData[idx_dest].Flags.ObjStatus != TSL_OBJ_STATUS_OFF)
+ {
+ if ((TSL_Check_GPIO_IDR(p_chSrc->t_sample)) &&
+ ((GroupToCheck & (1 << (p_chSrc->IdxSrc))) == (1 << (p_chSrc->IdxSrc))))
+ {
+ tab_MeasurementCounter[p_chSrc->IdxSrc] = TIM11->CCR1;
+ NumberOfChannelChecked++;
+ GroupToCheck &= (uint32_t)(~(1 << (p_chSrc->IdxSrc)));
+
+ // Reset CMR register to restart the timer
+ TSL_RI_CMR_Config_Clear(p_chSrc->t_sample);
+ }
+ // Manage Overflow
+ else if((CounterOverflowFlag) &&
+ ((GroupToCheck & (1 << (p_chSrc->IdxSrc))) == (1 << (p_chSrc->IdxSrc))))
+ {
+ tab_MeasurementCounter[p_chSrc->IdxSrc] = TSLPRM_ACQ_MAX + 1;
+ GroupToCheck &= (uint32_t)(~(1 << (p_chSrc->IdxSrc)));
+
+ // Reset CMR register to restart the timer
+ TSL_RI_CMR_Config_Clear(p_chSrc->t_sample);
+ }
+ }
+ p_chDest++;
+ p_chSrc++;
+ idx_ch++;
+ }
+ while (idx_ch < NumberOfChannels);
+
+ if (NumberOfChannelChecked >= NumberOfChannelOn)
+ {
+ NumberOfChannelOn = 0;
+ NumberOfChannelChecked = 0;
+
+ // Disable master counter
+ TIM9->CR1 &= (uint16_t)(~0x01);
+
+ //====================
+ // All GPIOs in PP Low
+ //====================
+ for (BankIndex = 0; BankIndex < NumberOfBanks; BankIndex++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[BankIndex]);
+ p_chSrc = LocalBank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ TSL_GPIO_BR_Config(LocalBank->shield_sample);
+ TSL_GPIO_BR_Config(LocalBank->shield_channel);
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_sample);
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_channel);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < LocalNumberOfChannels;
+ idx_ch++)
+ {
+ TSL_GPIO_BR_Config(p_chSrc->t_sample);
+ TSL_GPIO_BR_Config(p_chSrc->t_channel);
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_channel);
+
+ p_chSrc++;
+ }
+ }
+ TSL_Acq_Status = TSL_STATUS_OK;
+ }
+}
+
+
+/**
+ * @brief Check if a filter must be used on the current channel (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if a filter can be applied
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ return TSL_TRUE;
+}
+
+
+/**
+ * @brief Compute the Delta value
+ * @param[in] ref Reference value
+ * @param[in] meas Last Measurement value
+ * @retval Delta value
+ */
+TSL_tDelta_T TSL_acq_ComputeDelta(TSL_tRef_T ref, TSL_tMeas_T meas)
+{
+ return((TSL_tDelta_T)(ref - meas));
+}
+
+
+/**
+ * @brief Compute the Measurement value
+ * @param[in] ref Reference value
+ * @param[in] delta Delta value
+ * @retval Measurement value
+ */
+TSL_tMeas_T TSL_acq_ComputeMeas(TSL_tRef_T ref, TSL_tDelta_T delta)
+{
+ return((TSL_tMeas_T)(ref - delta));
+}
+
+
+/**
+ * @brief Test if the Reference is incorrect (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if the Reference is out of range
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ return TSL_FALSE;
+}
+
+
+/**
+ * @brief Test if the measure has crossed the reference target (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result TRUE if the Reference is valid
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ return TSL_TRUE;
+}
+
+
+#if defined(__IAR_SYSTEMS_ICC__) // IAR/EWARM
+#pragma optimize=medium
+#elif defined(__CC_ARM) // Keil/MDK-ARM
+#pragma O1
+#pragma Ospace
+#elif defined(__TASKING__) // Altium/Tasking
+#pragma optimize O0
+#elif defined(__GNUC__) // Atollic/True Studio + Raisonance/RKit
+#pragma GCC push_options
+#pragma GCC optimize ("O0")
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * With fHCLK = 32MHz: 1 = ~1s, 50 = ~14s, 100 = ~25s, 200 = ~50s
+ * @retval None
+ */
+void SoftDelay(uint16_t val)
+{
+ __IO uint16_t idx;
+ for (idx = val; idx > 0; idx--)
+ {}
+}
+#if defined(__TASKING__)
+#pragma endoptimize
+#endif
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_sw.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_sw.c
new file mode 100644
index 0000000..98e6792
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm32l1xx_sw.c
@@ -0,0 +1,996 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm32l1xx_sw.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the acquisition
+ * on STM32l1xx products using the software mode.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm32l1xx_sw.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+
+// Register configuration
+typedef struct
+{
+ unsigned int RI_ASCR : 3;
+ unsigned int RI_ASCR_bit : 5;
+} TSL_RIConf_t;
+
+/* Private defines -----------------------------------------------------------*/
+#define SIZEOFBANKCONF (17) //2 mask RIRs + 5 ports x 3 mask registers(MODER input, output, ODR) => 17 registers
+
+/* Private macros ------------------------------------------------------------*/
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
+
+#define TSL_CHANNEL_PORT(channel) (channel >> 4)
+#define TSL_CHANNEL_IO(channel) (channel & 0x0F)
+
+
+#define TSL_RI_HYSCR_MASK(channel) (1 << TSL_CHANNEL_IO(channel))
+
+#define TSL_RCC_AHBENR_Config(channel) (RCC->AHBENR |= TSL_GPIO_Clock_LookUpTable[TSL_CHANNEL_PORT(channel)])
+
+#define TSL_RI_HYSCR_Config(channel) (*TSL_RI_HYSCR_LookUpTable[TSL_CHANNEL_PORT(channel)] |= TSL_RI_HYSCR_MASK(channel))
+
+#define TSL_GPIO_MODER_IN_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER &= (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel)))))
+#define TSL_GPIO_MODER_OUT_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER = (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->MODER & (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel))))) | (1 << (2 * TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_PUPDR_NO_PUPD_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->PUPDR &= (uint32_t)(~(3 << (2 * TSL_CHANNEL_IO(channel)))))
+#define TSL_GPIO_OTYPER_PP_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->OTYPER &= (uint32_t)(~(1 << TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_OSPEEDR_VL_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->OSPEEDR &= (uint32_t)~(3 << (2 * TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_BS_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->BSRRL = (uint16_t)(1 << (TSL_CHANNEL_IO(channel))))
+#define TSL_GPIO_BR_Config(channel) (TSL_GPIO_LookUpTable[TSL_CHANNEL_PORT(channel)]->BSRRH = (uint16_t)(1 << (TSL_CHANNEL_IO(channel))))
+
+
+/* Private variables ---------------------------------------------------------*/
+uint32_t TSL_BankSampleConf[SIZEOFBANKCONF];
+uint32_t TSL_BankChannelConf[SIZEOFBANKCONF];
+uint32_t tab_MeasurementCounter[11];
+extern TSL_Params_T TSL_Params;
+
+CONST TSL_Bank_T *bank;
+TSL_tIndex_T NumberOfChannelOn = 0;
+TSL_tNb_T NumberOfChannels = 0;
+TSL_Status_enum_T TSL_Acq_Status = TSL_STATUS_BUSY;
+uint16_t GroupToCheck = 0;
+
+uint32_t TSL_GPIO_Clock_LookUpTable[] = {RCC_AHBPeriph_GPIOA, RCC_AHBPeriph_GPIOB, RCC_AHBPeriph_GPIOC, RCC_AHBPeriph_GPIOD, RCC_AHBPeriph_GPIOE, RCC_AHBPeriph_GPIOF, RCC_AHBPeriph_GPIOG, RCC_AHBPeriph_GPIOH};
+GPIO_TypeDef *TSL_GPIO_LookUpTable[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH};
+
+uint16_t *TSL_RI_HYSCR_LookUpTable[] =
+{
+ (uint16_t *)&RI->HYSCR1, (uint16_t *)&RI->HYSCR1 + 1,
+ (uint16_t *)&RI->HYSCR2, (uint16_t *)&RI->HYSCR2 + 1,
+ (uint16_t *)&RI->HYSCR3, (uint16_t *)&RI->HYSCR3 + 1,
+ (uint16_t *)&RI->HYSCR4, (uint16_t *)&RI->HYSCR4 + 1
+};
+
+CONST TSL_RIConf_t TSL_RI_Conf_LookUpTable[101] =
+{
+ {0, 0},
+ {0, 1},
+ {0, 2},
+ {0, 3},
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 6},
+ {0, 7},
+ {1, 9},
+ {1, 10},
+ {1, 11},
+ {1, 15},
+ {0, 0},//padding
+ {1, 6},
+ {1, 7},
+ {1, 8},
+
+ {0, 8},
+ {0, 9},
+ {1, 16},
+ {0, 0},//padding
+ {1, 4},
+ {1, 5},
+ {1, 27},
+ {1, 28},
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 18},
+ {0, 19},
+ {0, 20},
+ {0, 21},
+
+ {0, 10},
+ {0, 11},
+ {0, 12},
+ {0, 13},
+ {0, 14},
+ {0, 15},
+ {1, 0},
+ {1, 1},
+ {1, 2},
+ {1, 3},
+ {1, 29},
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 0},//padding
+ {0, 27},
+ {0, 28},
+ {0, 29},
+ {0, 30},
+ {0, 16},
+ {1, 17},
+ {1, 18},
+ {1, 19},
+ {1, 20},
+ {1, 21},
+
+ {1, 22},
+ {1, 23},
+ {1, 24},
+ {1, 25},
+ {1, 26}
+};
+
+#if (TSLPRM_USE_GPIOA)
+uint32_t GPIOA_IDR_Mask = 0;
+#endif
+#if (TSLPRM_USE_GPIOB)
+uint32_t GPIOB_IDR_Mask = 0;
+#endif
+#if (TSLPRM_USE_GPIOC)
+uint32_t GPIOC_IDR_Mask = 0;
+#endif
+#if (TSLPRM_USE_GPIOF)
+uint32_t GPIOF_IDR_Mask = 0;
+#endif
+#if (TSLPRM_USE_GPIOG)
+uint32_t GPIOG_IDR_Mask = 0;
+#endif
+
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+uint8_t SpreadCounter = TSLPRM_SPREAD_MIN;
+#endif
+
+/* Private functions prototype -----------------------------------------------*/
+void SoftDelay(uint16_t val);
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+__INLINE void SwSpreadSpectrum(void);
+#endif
+void TSL_BankConf(uint32_t * BankConf, TSL_Conf_t Conf);
+void TSL_acq_GroupDone(uint16_t EndedGroup);
+
+/**
+ * @brief Configures the acquisition module.
+ * @param[in] BankConf Pointer to the bank to configure
+ * @param[in] Conf Configuration
+ * @retval None
+ */
+void TSL_BankConf(uint32_t *BankConf, TSL_Conf_t Conf)
+{
+ BankConf[TSL_RI_Conf_LookUpTable[Conf].RI_ASCR] |= (1 << (TSL_RI_Conf_LookUpTable[Conf].RI_ASCR_bit));
+
+ switch (TSL_CHANNEL_PORT(Conf))
+ {
+ case TSL_BANK_GPIOA: BankConf[2] |= (3 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER input
+ BankConf[3] |= (1 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER output
+ BankConf[4] |= (1 << (TSL_CHANNEL_IO(Conf))); //ODR
+ break;
+ case TSL_BANK_GPIOB: BankConf[5] |= (3 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER input
+ BankConf[6] |= (1 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER output
+ BankConf[7] |= (1 << (TSL_CHANNEL_IO(Conf))); //ODR
+ break;
+ case TSL_BANK_GPIOC: BankConf[8] |= (3 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER input
+ BankConf[9] |= (1 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER output
+ BankConf[10] |= (1 << (TSL_CHANNEL_IO(Conf))); //ODR
+ break;
+ case TSL_BANK_GPIOF: BankConf[11] |= (3 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER input
+ BankConf[12] |= (1 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER output
+ BankConf[13] |= (1 << (TSL_CHANNEL_IO(Conf))); //ODR
+ break;
+ case TSL_BANK_GPIOG: BankConf[14] |= (3 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER input
+ BankConf[15] |= (1 << (2 * (TSL_CHANNEL_IO(Conf)))); //MODER output
+ BankConf[16] |= (1 << (TSL_CHANNEL_IO(Conf))); //ODR
+ break;
+ default: break;
+ }
+}
+
+
+/**
+ * @brief Initializes the acquisition module.
+ * @param None
+ * @retval None
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+ CONST TSL_Bank_T *LocalBank = &(TSL_Globals.Bank_Array[0]);
+ TSL_tNb_T NumberOfBanks = TSLPRM_TOTAL_BANKS;
+ TSL_tNb_T LocalNumberOfChannels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+ CONST TSL_ChannelSrc_T *p_chSrc = LocalBank->p_chSrc; // Pointer to the current channel
+
+ /* Enables the comparator interface clock */
+ RCC->APB1ENR |= RCC_APB1Periph_COMP;
+
+ //====================
+ // GPIOs configuration
+ //====================
+ for (idx_bk = 0; idx_bk < NumberOfBanks; idx_bk++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = LocalBank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Enables GPIOs clock
+ TSL_RCC_AHBENR_Config(LocalBank->shield_sample);
+
+ // Bank shield configuration
+ /* Disables Hysteresis Register */
+ TSL_RI_HYSCR_Config(LocalBank->shield_sample);
+
+ /* Output PP config */
+ TSL_GPIO_OTYPER_PP_Config(p_chSrc->t_sample);
+ TSL_GPIO_OTYPER_PP_Config(p_chSrc->t_channel);
+ /* 400kHz config */
+ TSL_GPIO_OSPEEDR_VL_Config(p_chSrc->t_sample);
+ TSL_GPIO_OSPEEDR_VL_Config(p_chSrc->t_channel);
+ /* No pull up/pull down config */
+ TSL_GPIO_PUPDR_NO_PUPD_Config(LocalBank->shield_sample);
+ TSL_GPIO_PUPDR_NO_PUPD_Config(LocalBank->shield_channel);
+ /* Set ODR */
+ TSL_GPIO_BR_Config(LocalBank->shield_sample);
+ TSL_GPIO_BR_Config(LocalBank->shield_channel);
+ /* Output mode */
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_sample);
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_channel);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < LocalNumberOfChannels;
+ idx_ch++)
+ {
+ /* Enables GPIOs clock */
+ TSL_RCC_AHBENR_Config(p_chSrc->t_sample);
+ TSL_RCC_AHBENR_Config(p_chSrc->t_channel);
+
+ // Bank/channel configuration
+ /* Disables Hysteresis Register */
+ TSL_RI_HYSCR_Config(p_chSrc->t_sample);
+ /* Output PP config */
+ TSL_GPIO_OTYPER_PP_Config(p_chSrc->t_sample);
+ TSL_GPIO_OTYPER_PP_Config(p_chSrc->t_channel);
+ /* 400kHz config */
+ TSL_GPIO_OSPEEDR_VL_Config(p_chSrc->t_sample);
+ TSL_GPIO_OSPEEDR_VL_Config(p_chSrc->t_channel);
+ /* No pull up/pull down config */
+ TSL_GPIO_PUPDR_NO_PUPD_Config(p_chSrc->t_sample);
+ TSL_GPIO_PUPDR_NO_PUPD_Config(p_chSrc->t_channel);
+ /* Set ODR */
+ TSL_GPIO_BR_Config(p_chSrc->t_sample);
+ TSL_GPIO_BR_Config(p_chSrc->t_channel);
+ /* Output mode */
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_channel);
+
+ p_chSrc++;
+ }
+ }
+
+ /* Enable RI Switch */
+ RI->ASCR1 &= (uint32_t)(~0x80000000); // ADC analog switches open !!!
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Configures a Bank.
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ TSL_tIndex_T index;
+ TSL_tIndex_T idx_dest;
+ TSL_tIndex_T idx_ch;
+ CONST TSL_ChannelDest_T *p_chDest; // Pointer to the current channel
+ CONST TSL_ChannelSrc_T *p_chSrc; // Pointer to the current channel
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ bank = &(TSL_Globals.Bank_Array[idx_bk]);
+
+ for (index = 0;index < SIZEOFBANKCONF;index++)
+ {
+ TSL_BankSampleConf[index] = 0x00000000;
+ TSL_BankChannelConf[index] = 0x00000000;
+ }
+
+ NumberOfChannels = bank->NbChannels;
+ NumberOfChannelOn = 0;
+ GroupToCheck = 0;//init group to check
+
+ p_chDest = bank->p_chDest;
+ p_chSrc = bank->p_chSrc;
+ for (idx_ch = 0; idx_ch < NumberOfChannels; idx_ch++)
+ {
+ // Get index in the result array associated to the current channel
+ idx_dest = p_chDest->IdxDest;
+
+ if (bank->p_chData[idx_dest].Flags.ObjStatus != TSL_OBJ_STATUS_OFF)
+ {
+ TSL_BankConf(TSL_BankSampleConf, p_chSrc->t_sample);
+ TSL_BankConf(TSL_BankChannelConf, p_chSrc->t_channel);
+ GroupToCheck |= (1 << (p_chSrc->IdxSrc));
+ NumberOfChannelOn++;
+ }
+
+ p_chSrc++;
+ p_chDest++;
+ }
+
+#if (TSLPRM_USE_GPIOA)
+ GPIOA_IDR_Mask = TSL_BankSampleConf[4];
+#endif
+
+#if (TSLPRM_USE_GPIOB)
+ GPIOB_IDR_Mask = TSL_BankSampleConf[7];
+#endif
+
+#if (TSLPRM_USE_GPIOC)
+ GPIOC_IDR_Mask = TSL_BankSampleConf[10];
+#endif
+
+#if (TSLPRM_USE_GPIOF)
+ GPIOF_IDR_Mask = TSL_BankSampleConf[13];
+#endif
+
+#if (TSLPRM_USE_GPIOG)
+ GPIOG_IDR_Mask = TSL_BankSampleConf[16];
+#endif
+
+
+#if (TSLPRM_USE_SHIELD > 0)
+ if (NumberOfChannelOn != 0)
+ {
+ TSL_BankConf(TSL_BankSampleConf, bank->shield_sample);
+ TSL_BankConf(TSL_BankChannelConf, bank->shield_channel);
+ }
+#endif
+
+ return TSL_STATUS_OK;
+
+}
+
+
+/**
+ * @brief Check which group is not over
+ * @param[in] EndedGroup
+ * @retval None
+ */
+void TSL_acq_GroupDone(uint16_t EndedGroup)
+{
+ uint16_t i;
+
+ for (i = 0;i < 11;i++)
+ {
+ if ((EndedGroup & (1 << i)) != (1 << i))
+ {
+ tab_MeasurementCounter[i] = TSL_Params.AcqMax + 1;
+ }
+ }
+
+}
+
+
+/**
+ * @brief Start acquisition on a previously configured bank
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+ CONST TSL_Bank_T *LocalBank = &(TSL_Globals.Bank_Array[0]);
+ TSL_tNb_T NumberOfBanks = TSLPRM_TOTAL_BANKS;
+ TSL_tNb_T LocalNumberOfChannels = 0;
+ TSL_tIndex_T BankIndex;
+
+ uint16_t MeasurementCounter = 0;
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ TSL_tIndex_T idx_ch;
+ uint16_t GroupToCheckMask = 0;
+ uint32_t GPIO_IDR_Mask = 0;
+ uint8_t Check_Input = 0;
+
+#if (TSLPRM_USE_GPIOA)
+ uint16_t TSL_GPIOA_IDR = 0;
+#endif
+#if (TSLPRM_USE_GPIOB)
+ uint16_t TSL_GPIOB_IDR = 0;
+#endif
+#if (TSLPRM_USE_GPIOC)
+ uint16_t TSL_GPIOC_IDR = 0;
+#endif
+#if (TSLPRM_USE_GPIOF)
+ uint16_t TSL_GPIOF_IDR = 0;
+#endif
+#if (TSLPRM_USE_GPIOG)
+ uint16_t TSL_GPIOG_IDR = 0;
+#endif
+ uint16_t GPIO_IDR = 0;
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __disable_irq();
+#endif
+#if (TSLPRM_IODEF > 0)
+ //============================
+ // All GPIOs in Input floating
+ //============================
+ for (BankIndex = 0; BankIndex < NumberOfBanks; BankIndex++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[BankIndex]);
+ p_chSrc = LocalBank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ TSL_GPIO_MODER_IN_Config(LocalBank->shield_sample);
+ TSL_GPIO_MODER_IN_Config(LocalBank->shield_channel);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < LocalNumberOfChannels;
+ idx_ch++)
+ {
+ TSL_GPIO_MODER_IN_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_IN_Config(p_chSrc->t_channel);
+
+ p_chSrc++;
+ }
+ }
+#endif
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __enable_irq();
+#endif
+
+ /* Open the analog switches */
+ RI->ASCR1 &= (uint32_t)(~(TSL_BankSampleConf[0] | TSL_BankChannelConf[0]));
+ RI->ASCR2 &= (uint32_t)(~(TSL_BankSampleConf[1] | TSL_BankChannelConf[1]));
+
+ /* All IO to pushpull LOW for discharging all capacitors (Ctouch and Csense) */
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __disable_irq();
+#endif
+ /* Discharging sampling capacitor and CTouch */
+#if (TSLPRM_USE_GPIOA)
+ GPIOA->ODR &= (uint32_t)(~(TSL_BankSampleConf[4] | TSL_BankChannelConf[4]));
+ GPIOA->MODER = (GPIOA->MODER & (uint32_t)(~(TSL_BankSampleConf[2] | TSL_BankChannelConf[2]))) | (TSL_BankSampleConf[3] | TSL_BankChannelConf[3]);
+#endif
+#if (TSLPRM_USE_GPIOB)
+ GPIOB->ODR &= (uint32_t)(~(TSL_BankSampleConf[7] | TSL_BankChannelConf[7]));
+ GPIOB->MODER = (GPIOB->MODER & (uint32_t)(~(TSL_BankSampleConf[5] | TSL_BankChannelConf[5]))) | (TSL_BankSampleConf[6] | TSL_BankChannelConf[6]);
+#endif
+#if (TSLPRM_USE_GPIOC)
+ GPIOC->ODR &= (uint32_t)(~(TSL_BankSampleConf[10] | TSL_BankChannelConf[10]));
+ GPIOC->MODER = (GPIOC->MODER & (uint32_t)(~(TSL_BankSampleConf[8] | TSL_BankChannelConf[8]))) | (TSL_BankSampleConf[9] | TSL_BankChannelConf[9]);
+#endif
+#if (TSLPRM_USE_GPIOF)
+ GPIOF->ODR &= (uint32_t)(~(TSL_BankSampleConf[13] | TSL_BankChannelConf[13]));
+ GPIOF->MODER = (GPIOF->MODER & (uint32_t)(~(TSL_BankSampleConf[11] | TSL_BankChannelConf[11]))) | (TSL_BankSampleConf[12] | TSL_BankChannelConf[12]);
+#endif
+#if (TSLPRM_USE_GPIOG)
+ GPIOG->ODR &= (uint32_t)(~(TSL_BankSampleConf[16] | TSL_BankChannelConf[16]));
+ GPIOG->MODER = (GPIOG->MODER & (uint32_t)(~(TSL_BankSampleConf[14] | TSL_BankChannelConf[14]))) | (TSL_BankSampleConf[15] | TSL_BankChannelConf[15]);
+#endif
+
+
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __enable_irq();
+#endif
+
+ /* Wait a while for a good discharging of all capacitors */
+ SoftDelay(50); // ~14s with fHCLK = 32MHz
+ //this time depends of the size of the sampling capacitor
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __disable_irq();
+#endif
+ /* All IO in input floating */
+#if (TSLPRM_USE_GPIOA)
+ GPIOA->MODER &= (uint32_t)(~(TSL_BankSampleConf[2] | TSL_BankChannelConf[2]));
+#endif
+#if (TSLPRM_USE_GPIOB)
+ GPIOB->MODER &= (uint32_t)(~(TSL_BankSampleConf[5] | TSL_BankChannelConf[5]));
+#endif
+#if (TSLPRM_USE_GPIOC)
+ GPIOC->MODER &= (uint32_t)(~(TSL_BankSampleConf[8] | TSL_BankChannelConf[8]));
+#endif
+#if (TSLPRM_USE_GPIOF)
+ GPIOF->MODER &= (uint32_t)(~(TSL_BankSampleConf[11] | TSL_BankChannelConf[11]));
+#endif
+#if (TSLPRM_USE_GPIOG)
+ GPIOG->MODER &= (uint32_t)(~(TSL_BankSampleConf[14] | TSL_BankChannelConf[14]));
+#endif
+
+ /* set the IO to Vdd (io in push-pull HIGH when in output mode) */
+#if (TSLPRM_USE_GPIOA)
+ GPIOA->ODR |= (TSL_BankSampleConf[4] | TSL_BankChannelConf[4]); /* HIGH level */
+#endif
+#if (TSLPRM_USE_GPIOB)
+ GPIOB->ODR |= (TSL_BankSampleConf[7] | TSL_BankChannelConf[7]); /* HIGH level */
+#endif
+#if (TSLPRM_USE_GPIOC)
+ GPIOC->ODR |= (TSL_BankSampleConf[10] | TSL_BankChannelConf[10]); /* HIGH level */
+#endif
+#if (TSLPRM_USE_GPIOF)
+ GPIOF->ODR |= (TSL_BankSampleConf[13] | TSL_BankChannelConf[13]); /* HIGH level */
+#endif
+#if (TSLPRM_USE_GPIOG)
+ GPIOG->ODR |= (TSL_BankSampleConf[16] | TSL_BankChannelConf[16]); /* HIGH level */
+#endif
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __enable_irq();
+#endif
+
+ /* Close the sampling capacitor analog switch */
+ RI->ASCR1 |= (TSL_BankSampleConf[0]);
+ RI->ASCR2 |= (TSL_BankSampleConf[1]);
+
+
+ /* Loop while all the 1st channel of each group have not reach the VIH level */
+ do
+ {
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __disable_irq();
+#endif
+ /* Charging Ctouch by connecting the IO to Vdd (io in push-pull HIGH) */
+#if (TSLPRM_USE_GPIOA)
+ GPIOA->MODER |= (TSL_BankChannelConf[3]); /* Output push pull config */
+#endif
+#if (TSLPRM_USE_GPIOB)
+ GPIOB->MODER |= (TSL_BankChannelConf[6]); /* Output push pull config */
+#endif
+#if (TSLPRM_USE_GPIOC)
+ GPIOC->MODER |= (TSL_BankChannelConf[9]); /* Output push pull config */
+#endif
+#if (TSLPRM_USE_GPIOF)
+ GPIOF->MODER |= (TSL_BankChannelConf[12]); /* Output push pull config */
+#endif
+#if (TSLPRM_USE_GPIOG)
+ GPIOG->MODER |= (TSL_BankChannelConf[15]); /* Output push pull config */
+#endif
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __enable_irq();
+#endif
+
+ /* Wait a while for a good charging (programmable delay) */
+#if ( TSLPRM_DELAY_TRANSFER > 0 )
+ SoftDelay(TSLPRM_DELAY_TRANSFER);
+#endif
+
+ /* Spread Spectrum */
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+ SwSpreadSpectrum();
+#endif
+
+ /* test GPIOx->IDR bit + group configuration for each channel */
+
+#if (TSLPRM_USE_GPIOA)
+ TSL_GPIOA_IDR = GPIOA->IDR;
+ if ((TSL_GPIOA_IDR & GPIOA_IDR_Mask) != 0)
+ {
+ Check_Input = 1;
+ GPIOA_IDR_Mask &= (uint32_t)(~TSL_GPIOA_IDR);
+ }
+#endif
+
+#if (TSLPRM_USE_GPIOB)
+ TSL_GPIOB_IDR = GPIOB->IDR;
+ if ((TSL_GPIOB_IDR & GPIOB_IDR_Mask) != 0)
+ {
+ Check_Input = (1 << 1);
+ GPIOB_IDR_Mask &= (uint32_t)(~TSL_GPIOB_IDR);
+ }
+#endif
+
+#if (TSLPRM_USE_GPIOC)
+ TSL_GPIOC_IDR = GPIOC->IDR;
+ if ((TSL_GPIOC_IDR & GPIOC_IDR_Mask) != 0)
+ {
+ Check_Input = (1 << 2);
+ GPIOC_IDR_Mask &= (uint32_t)(~TSL_GPIOC_IDR);
+ }
+#endif
+
+#if (TSLPRM_USE_GPIOF)
+ TSL_GPIOF_IDR = GPIOF->IDR;
+ if ((TSL_GPIOF_IDR & GPIOF_IDR_Mask) != 0)
+ {
+ Check_Input = (1 << 5);
+ GPIOF_IDR_Mask &= (uint32_t)(~TSL_GPIOF_IDR);
+ }
+#endif
+
+#if (TSLPRM_USE_GPIOG)
+ TSL_GPIOG_IDR = GPIOG->IDR;
+ if ((TSL_GPIOG_IDR & GPIOG_IDR_Mask) != 0)
+ {
+ Check_Input = (1 << 6);
+ GPIOG_IDR_Mask &= (uint32_t)(~TSL_GPIOG_IDR);
+ }
+#endif
+
+
+ if (Check_Input)
+ {
+ p_chSrc = bank->p_chSrc;
+ for (idx_ch = 0; idx_ch < NumberOfChannels; idx_ch++)
+ {
+ GroupToCheckMask = (1 << (p_chSrc->IdxSrc));
+ if ((GroupToCheck & GroupToCheckMask) == (GroupToCheckMask))
+ {
+ GPIO_IDR_Mask = (1 << TSL_CHANNEL_IO(p_chSrc->t_sample));
+
+ switch (TSL_CHANNEL_PORT(p_chSrc->t_sample))
+ {
+#if (TSLPRM_USE_GPIOA)
+ case 0: GPIO_IDR = TSL_GPIOA_IDR; break;
+#endif
+#if (TSLPRM_USE_GPIOB)
+ case 1: GPIO_IDR = TSL_GPIOB_IDR; break;
+#endif
+#if (TSLPRM_USE_GPIOC)
+ case 2: GPIO_IDR = TSL_GPIOC_IDR; break;
+#endif
+#if (TSLPRM_USE_GPIOF)
+ case 5: GPIO_IDR = TSL_GPIOF_IDR; break;
+#endif
+#if (TSLPRM_USE_GPIOG)
+ case 6: GPIO_IDR = TSL_GPIOG_IDR; break;
+#endif
+ default: break;
+ }
+
+ if ((GPIO_IDR & GPIO_IDR_Mask) == GPIO_IDR_Mask)
+ {
+ tab_MeasurementCounter[p_chSrc->IdxSrc] = MeasurementCounter;
+ GroupToCheck &= (uint32_t)(~(1 << (p_chSrc->IdxSrc)));
+ Check_Input &= (uint32_t)(~(1 << TSL_CHANNEL_PORT(p_chSrc->t_sample)));
+ }
+ }
+ p_chSrc++;
+ }
+ }
+
+ MeasurementCounter++;
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __disable_irq();
+#endif
+ /* Configure All channels in input floating */
+#if (TSLPRM_USE_GPIOA)
+ GPIOA->MODER &= (uint32_t)(~(TSL_BankChannelConf[2]));
+#endif
+#if (TSLPRM_USE_GPIOB)
+ GPIOB->MODER &= (uint32_t)(~(TSL_BankChannelConf[5]));
+#endif
+#if (TSLPRM_USE_GPIOC)
+ GPIOC->MODER &= (uint32_t)(~(TSL_BankChannelConf[8]));
+#endif
+#if (TSLPRM_USE_GPIOF)
+ GPIOF->MODER &= (uint32_t)(~(TSL_BankChannelConf[11]));
+#endif
+#if (TSLPRM_USE_GPIOG)
+ GPIOG->MODER &= (uint32_t)(~(TSL_BankChannelConf[14]));
+#endif
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __enable_irq();
+#endif
+
+ /* Charging the Csense cap with connecting it to Ctouch by closing the analog switch */
+ RI->ASCR1 |= (TSL_BankChannelConf[0]);
+ RI->ASCR2 |= (TSL_BankChannelConf[1]);
+
+ /* Wait a while for a good charge transfering (programmable delay) */
+#if ( TSLPRM_DELAY_TRANSFER > 0 )
+ SoftDelay(TSLPRM_DELAY_TRANSFER);
+#endif
+
+ RI->ASCR1 &= (uint32_t)(~(TSL_BankChannelConf[0]));
+ RI->ASCR2 &= (uint32_t)(~(TSL_BankChannelConf[1]));
+
+ /*it's better to implement this like that because it's much more faster than to put this test in the "while test" below */
+ if (MeasurementCounter > TSL_Params.AcqMax)
+ {
+ TSL_acq_GroupDone(GroupToCheck);
+ __NOP();
+ break;
+ }
+
+ }
+ while (GroupToCheck != 0);
+
+
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __disable_irq();
+#endif
+ //====================
+ // All GPIOs in PP Low
+ //====================
+ for (BankIndex = 0; BankIndex < NumberOfBanks; BankIndex++)
+ {
+ LocalBank = &(TSL_Globals.Bank_Array[BankIndex]);
+ p_chSrc = LocalBank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ TSL_GPIO_BR_Config(LocalBank->shield_sample);
+ TSL_GPIO_BR_Config(LocalBank->shield_channel);
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_sample);
+ TSL_GPIO_MODER_OUT_Config(LocalBank->shield_channel);
+#endif
+
+ LocalNumberOfChannels = LocalBank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < LocalNumberOfChannels;
+ idx_ch++)
+ {
+ TSL_GPIO_BR_Config(p_chSrc->t_sample);
+ TSL_GPIO_BR_Config(p_chSrc->t_channel);
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_sample);
+ TSL_GPIO_MODER_OUT_Config(p_chSrc->t_channel);
+
+ p_chSrc++;
+ }
+ }
+#if (TSLPRM_PROTECT_IO_ACCESS > 0)
+ __enable_irq();
+#endif
+
+
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ TSL_Status_enum_T retval = TSL_STATUS_BUSY;
+ retval = TSL_STATUS_OK;
+ return retval;
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndex_T index)
+{
+ return(tab_MeasurementCounter[index]);
+}
+
+
+/**
+ * @brief Check noise (not used)
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ return TSL_ACQ_STATUS_OK;
+}
+
+
+/**
+ * @brief Process the TS Interrupt routine
+ * @param None
+ * @retval None
+ */
+void TSL_acq_ProcessIT(void)
+{
+}
+
+/**
+ * @brief Check if a filter must be used on the current channel (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if a filter can be applied
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ return TSL_TRUE;
+}
+
+
+/**
+ * @brief Compute the Delta value
+ * @param[in] ref Reference value
+ * @param[in] meas Last Measurement value
+ * @retval Delta value
+ */
+TSL_tDelta_T TSL_acq_ComputeDelta(TSL_tRef_T ref, TSL_tMeas_T meas)
+{
+ return((TSL_tDelta_T)(ref - meas));
+}
+
+
+/**
+ * @brief Compute the Measurement value
+ * @param[in] ref Reference value
+ * @param[in] delta Delta value
+ * @retval Measurement value
+ */
+TSL_tMeas_T TSL_acq_ComputeMeas(TSL_tRef_T ref, TSL_tDelta_T delta)
+{
+ return((TSL_tMeas_T)(ref - delta));
+}
+
+
+/**
+ * @brief Test if the Reference is incorrect (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if the Reference is out of range
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ return TSL_FALSE;
+}
+
+
+/**
+ * @brief Test if the measure has crossed the reference target (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result TRUE if the Reference is valid
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ return TSL_TRUE;
+}
+
+
+#if defined(__IAR_SYSTEMS_ICC__) // IAR/EWARM
+#pragma optimize=medium
+#elif defined(__CC_ARM) // Keil/MDK-ARM
+#pragma O1
+#pragma Ospace
+#elif defined(__TASKING__) // Altium/Tasking
+#pragma optimize O0
+#elif defined(__GNUC__) // Atollic/True Studio + Raisonance/RKit
+#pragma GCC push_options
+#pragma GCC optimize ("O0")
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * With fHCLK = 32MHz: 1 = ~1s, 50 = ~14s, 100 = ~25s, 200 = ~50s
+ * @retval None
+ */
+void SoftDelay(uint16_t val)
+{
+ __IO uint16_t idx;
+ for (idx = val; idx > 0; idx--)
+ {}
+}
+#if defined(__TASKING__)
+#pragma endoptimize
+#endif
+
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+#if defined(__IAR_SYSTEMS_ICC__) // IAR/EWARM
+#pragma optimize=medium
+#elif defined(__CC_ARM) // Keil/MDK-ARM
+#pragma O1
+#pragma Ospace
+#elif defined(__TASKING__) // Altium/Tasking
+#pragma optimize O0
+#elif defined(__GNUC__) // Atollic/True Studio + Raisonance/RKit
+#pragma GCC push_options
+#pragma GCC optimize ("O0")
+#endif
+/**
+ * @brief Spread Spectrum using a variable software delay.
+ * @param None
+ * @retval None
+ */
+__INLINE void SwSpreadSpectrum(void)
+{
+ uint8_t idx;
+
+ SpreadCounter++;
+
+ if (SpreadCounter == TSLPRM_SPREAD_MAX)
+ {
+ SpreadCounter = TSLPRM_SPREAD_MIN;
+ }
+
+ idx = SpreadCounter;
+
+ while (--idx) {}
+}
+#if defined(__TASKING__)
+#pragma endoptimize
+#endif
+#endif
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_hw.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_hw.c
new file mode 100644
index 0000000..007efa2
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_hw.c
@@ -0,0 +1,888 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm8l_hw.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the acquisition
+ * on STM8L products using the hardware acquisition mode (with Timers).
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm8l_hw.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+
+/** Structure containing RI IO informations according to GPIO.
+ */
+typedef struct
+{
+ unsigned int IO_Channel : 4; /**< Channel number from 1 to 4 in the Routing interface group */
+ unsigned int IO_Group : 4; /**< Group number in the Routing interface */
+} TSL_IOConf_T;
+
+/* Private defines -----------------------------------------------------------*/
+
+#define MAX_CHANNEL_NUMBER_BY_GROUP (4)
+
+/* Private macros ------------------------------------------------------------*/
+
+#define GPIO_PORT(GPIO) (GPIO >> 3) /**< Get the GPIO port*/
+#define GPIO_BIT(GPIO) (GPIO & 0x07) /**< Get the GPIO pin number*/
+
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS))) /**< Check if the index have a good range*/
+
+#define GPIO_ODR_HIGH(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->ODR |= (uint8_t)(1 << GPIO_BIT(GPIO)))
+#define GPIO_ODR_LOW(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->ODR &= (uint8_t)(~(1 << GPIO_BIT(GPIO))))
+#define GPIO_DDR_IN(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->DDR &= (uint8_t)(~(1 << GPIO_BIT(GPIO))))
+#define GPIO_DDR_OUT(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->DDR |= (uint8_t)(1 << GPIO_BIT(GPIO)))
+#define GPIO_CR1_PP(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->CR1 |= (uint8_t)(1 << GPIO_BIT(GPIO)))
+#define GPIO_CR1_FLOATING(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->CR1 &= (uint8_t)(~(1 << GPIO_BIT(GPIO))))
+
+#define DISABLE_MASK(GPIO) (DisableMask[(GPIO_to_SW_Conf[GPIO].IO_Channel)-1] |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group)) /**< Create disable mask array to modify initial bank mask before acquisition (only for STATUS_OFF)*/
+#define DISABLE_SAMPLING(GPIO) (DisableSampling |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group)) /**< Create disable sampling mask to don't take sampling measurement of corresponding channels(for STATUS_BURST_ONLY and shield) */
+
+/* Private variables ---------------------------------------------------------*/
+
+__IO uint8_t *p_IOIRx; // Pointer to the IOIRx register (x from 1 to 4)
+__IO uint8_t *p_IOMRx; // Pointer to the IOMRx register (x from 1 to 4)
+uint8_t OldStatus; // Mask used to memorize the IOIRx bits processed during the acquisition
+uint8_t BankDone; // Control if all activate sampling reach the VIH level
+uint8_t CurrentSampling; // Mask to control IOGCR register
+uint8_t CurrentChannel; // Mask to control IOGCR register
+uint8_t ChannelSampling; // Contain the channel number where all sampling are connected
+uint8_t DisableSampling; // Disable sampling mask when the Burst Only mode is activated for one channel of the current bank(not get the measure)
+
+TSL_Bank_Config_Mask_T BankMask[TSLPRM_TOTAL_BANKS]; // Complete masks (channel and sampling) to configure IOCMRx and IOSRx registers for all banks
+uint8_t SamplingMask[TSLPRM_TOTAL_BANKS]; // Sampling mask to configure IOGCR register for all banks
+uint8_t ChannelMask[TSLPRM_TOTAL_BANKS]; // Channel mask to configure IOGCR register for all banks
+uint8_t DisableMask[MAX_CHANNEL_NUMBER_BY_GROUP]; // Complete disable mask(channel and sampling) when the Channel OFF mode is activated for one channel of the current bank(to modifie the Current_Bank)
+uint8_t CurrentBank[MAX_CHANNEL_NUMBER_BY_GROUP]; // Complete mask for the current bank
+uint16_t tab_MeasurementCounter[8] = {0}; // Measurement of each sampling of the current bank
+
+TSL_Status_enum_T TSL_Acq_Status = TSL_STATUS_BUSY;
+
+GPIO_TypeDef *p_GPIOx[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF};
+
+__IO uint8_t *RI_IOIRx_Register[MAX_CHANNEL_NUMBER_BY_GROUP] = {&(RI->IOIR1), &(RI->IOIR2), &(RI->IOIR3), &(RI->IOIR4)};
+__IO uint8_t *RI_IOMRx_Register[MAX_CHANNEL_NUMBER_BY_GROUP] = {&(RI->IOMR1), &(RI->IOMR2), &(RI->IOMR3), &(RI->IOMR4)};
+
+
+/* Table which do the link between GPIO and switch configuation:{x,y}
+ x = channel number
+ y = group number - 1
+ Note: {0,0} = not connect to IO switch
+*/
+CONST TSL_IOConf_T GPIO_to_SW_Conf[40] =
+{
+ // Port A definitions
+ {0, 0}, // PA0
+ {0, 0}, // PA1
+ {0, 0}, // PA2
+ {0, 0}, // PA3
+ {3, 0}, // PA4 is channel 3 of Group 1
+ {2, 0}, // PA5 is channel 2 of Group 1
+ {1, 0}, // PA6 is channel 1 of Group 1
+ {4, 0}, // PA7 is channel 4 of Group 1
+ // Port B definitions
+ {1, 6}, // PB0
+ {3, 5},
+ {2, 5},
+ {1, 5},
+ {3, 4},
+ {2, 4},
+ {1, 4},
+ {3, 3}, // PB7
+ // Port C definitions
+ {0, 0}, // PC0
+ {0, 0},
+ {1, 2},
+ {3, 1},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}, // PC7
+ // Port D definitions
+ {2, 7}, // PD0
+ {1, 7},
+ {3, 6},
+ {2, 6},
+ {2, 3},
+ {1, 3},
+ {3, 2},
+ {2, 2}, // PD7
+ // Port E definitions
+ {0, 0}, // PE0
+ {0, 0},
+ {0, 0},
+ {4, 6},
+ {4, 7},
+ {3, 7},
+ {0, 0},
+ {4, 1} // PE7
+};
+
+/* Private functions prototype -----------------------------------------------*/
+void SoftDelay(uint16_t val);
+void CreateMask(uint16_t idx_bk, uint8_t GPIO);
+void TSL_Init_GPIOs(void);
+void TSL_Init_TIMs(void);
+TSL_Status_enum_T TSL_Init_RI(void);
+
+
+/**
+ * @brief Initializes the touch sensing GPIOs.
+ * @param None
+ * @retval None
+ */
+void TSL_Init_GPIOs(void)
+{
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]); // Pointer to the first bank
+ CONST TSL_ChannelSrc_T *p_chSrc = p_bank->p_chSrc; // Pointer to the source channel of the current bank
+ uint16_t number_of_channels = 0;
+ uint16_t idx_bk;
+ uint16_t idx_ch;
+
+ // Initializes each bank and configures the used GPIO
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+ number_of_channels = p_bank->NbChannels;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // GPIO in Output
+ GPIO_DDR_OUT(p_bank->shield_sampling);
+ GPIO_DDR_OUT(p_bank->shield_channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_bank->shield_sampling);
+ GPIO_CR1_PP(p_bank->shield_channel);
+ // Output in Low level
+ GPIO_ODR_LOW(p_bank->shield_sampling);
+ GPIO_ODR_LOW(p_bank->shield_channel);
+#endif
+
+ // Initialize the mask for channel and sampling
+ for (idx_ch = 0; idx_ch < number_of_channels; idx_ch++)
+ {
+ // GPIO are configured in PP Low mode when inactive
+ // GPIO in Output
+ GPIO_DDR_OUT(p_chSrc->sampling);
+ GPIO_DDR_OUT(p_chSrc->channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_chSrc->sampling);
+ GPIO_CR1_PP(p_chSrc->channel);
+ // Output in Low level
+ GPIO_ODR_LOW(p_chSrc->sampling);
+ GPIO_ODR_LOW(p_chSrc->channel);
+ // Next channel
+ p_chSrc++;
+ }
+ }
+}
+
+
+/**
+ * @brief Initializes the timers used for touch sensing hardware acquisition.
+ * @param None
+ * @retval None
+ */
+void TSL_Init_TIMs(void)
+{
+ CLK->PCKENR1 |= 0x03; // Enable TIM2 and TIM3 clocks
+
+ //==============================
+ // TIMER 2 configuration: Master
+ //==============================
+ // Channel 1 as output, set PWM mode 1
+ TIM2->CCMR1 = 0x60;
+ TIM2->CCMR2 = 0x60;
+ // Main Output Enable
+ TIM2->BKR |= 0x80; // MOE=1
+ // Center-Aligned mode 3
+ TIM2->CR1 |= 0x60; // CMS=11
+ // OC2 polarity = active low
+ TIM2->CCER1 |= 0x20; // CC2P=1
+ // Enable OC2
+ TIM2->CCER1 |= 0x10; // CC2E=1
+ // Set the Prescaler value
+ TIM2->PSCR = 0; // fCK_CNT = 16MHz/(0+1) = 16MHz --> T=62.5ns
+ // Set the Autoreload value (signal frequency)
+ TIM2->ARRH = (uint8_t)(TIM_RELOAD >> 8);
+ TIM2->ARRL = (uint8_t)(TIM_RELOAD);
+ // Set PWM1 duty cycle
+ TIM2->CCR1H = (uint8_t)(TIM2_PWM_CH1_WIDTH >> 8);
+ TIM2->CCR1L = (uint8_t)(TIM2_PWM_CH1_WIDTH);
+ // Set PWM2 duty cycle
+ TIM2->CCR2H = (uint8_t)(TIM2_PWM_CH2_WIDTH >> 8);
+ TIM2->CCR2L = (uint8_t)(TIM2_PWM_CH2_WIDTH);
+ // Select Master mode, Internal Trigger selection, Gated mode
+ TIM2->SMCR = 0x35; // TS=011=ITR3(TIM2), SMS=101=Gated mode enabled
+ // Map OC1REF to TRGO
+ TIM2->CR2 = 0x40; // MMS=100
+ // Enable OC1
+ TIM2->CCER1 |= 0x01; // CC1E=1
+ // Set Update generation
+ TIM2->EGR |= 0x01; // UG=1
+ // Set Break interrupt flag
+ TIM2->SR1 |= 0x80;
+
+ //==============================
+ // TIMER 3 configuration: slave
+ //==============================
+ // Enable External Clock mode 2, external trigger filter, trigger on high level or rising edge
+ TIM3->ETR = 0x42; // ETP=0, ECE=1, ETF=0010
+ // Capture/Compare 1 configured as Input: h/w detection mapped on TI2FP1
+ TIM3->CCMR1 = 0x02; // CC1S=10
+ // Capture/Compare 2 configured as Output: MaxCount
+ TIM3->CCMR2 = 0; // CC2S=00
+ // Enable CC1 channel as Input for Capture function
+ TIM3->CCER1 = 0x01; // CC1E=1
+ // Enable counter (slave must be enabled first)
+ TIM3->CR1 |= 0x01; // CEN=1
+}
+
+
+/**
+ * @brief Init routing interface.
+ * @param None
+ * @retval None
+ */
+TSL_Status_enum_T TSL_Init_RI(void)
+{
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]); // Pointer to the first bank
+ CONST TSL_ChannelSrc_T *p_chSrc = p_bank->p_chSrc; // Pointer to the source channel of the current bank
+ uint16_t number_of_channels = 0;
+ uint16_t idx_bk;
+ uint16_t idx_ch;
+
+ // Enable comparator clock to activate the RI block
+ CLK->PCKENR2 |= CLK_PCKENR2_COMP;
+
+ // Enable H/W acquisition sequence
+ RI->CR |= 0x04; // AM=1
+
+ // Enable Channel Acquisition interrupt
+ RI->CR |= 0x01; // TIE=1
+
+ // Suspend Timer2 on h/w detection
+ RI->CR |= 0x08; // THALT=1
+
+ // Enable schmitt trigger required for H/W acq mode.
+ COMP->CSR1 |= 0x04; // STE=1
+
+ // Initializes each bank and configures the used GPIO
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+ number_of_channels = p_bank->NbChannels;
+
+ // Masks initialisation
+ BankMask[idx_bk].ch1 = 0;
+ BankMask[idx_bk].ch2 = 0;
+ BankMask[idx_bk].ch3 = 0;
+ BankMask[idx_bk].ch4 = 0;
+
+ // Get which channel is used for sampling only one time because it's the same for each couple
+ SamplingMask[idx_bk] = (uint8_t)GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Create Mask per bank
+ CreateMask(idx_bk,p_bank->shield_sampling);
+ CreateMask(idx_bk,p_bank->shield_channel);
+ ChannelMask[idx_bk] |= (uint8_t)(3 << (2 * ((GPIO_to_SW_Conf[p_bank->shield_channel].IO_Channel) - 1)));
+ if ((SamplingMask[idx_bk] != (uint8_t)GPIO_to_SW_Conf[p_bank->shield_sampling].IO_Channel))
+ {
+ return TSL_STATUS_ERROR;
+ }
+#endif
+
+ // Initializes the mask for channel and sampling
+ for (idx_ch = 0; idx_ch < number_of_channels; idx_ch++)
+ {
+ // Create Mask per bank
+ CreateMask(idx_bk,p_chSrc->channel);
+ CreateMask(idx_bk,p_chSrc->sampling);
+ ChannelMask[idx_bk] |= (uint8_t)(3 << (2 * ((GPIO_to_SW_Conf[p_chSrc->channel].IO_Channel) - 1)));
+ if ((SamplingMask[idx_bk] != (uint8_t)GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel))
+ {
+ return TSL_STATUS_ERROR;
+ }
+ // Next channel
+ p_chSrc++;
+ }
+
+ // Unlock IO to RI register : IO controlled by GPIO
+ RI->IOCMR1 &= (uint8_t)(~BankMask[idx_bk].ch1);
+ RI->IOCMR2 &= (uint8_t)(~BankMask[idx_bk].ch2);
+ RI->IOCMR3 &= (uint8_t)(~BankMask[idx_bk].ch3);
+ RI->IOCMR4 &= (uint8_t)(~BankMask[idx_bk].ch4);
+ }
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Create Mask for all banks
+ * @param[in] idx_bk Index of the Bank to configure
+ * @param[in] GPIO Pin number
+ * @retval None
+ */
+void CreateMask(uint16_t idx_bk, uint8_t GPIO)
+{
+ switch(GPIO_to_SW_Conf[GPIO].IO_Channel)
+ {
+ case 1:
+ BankMask[idx_bk].ch1 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask for all first channel
+ break;
+ case 2:
+ BankMask[idx_bk].ch2 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask for all second channel
+ break;
+ case 3:
+ BankMask[idx_bk].ch3 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask fo all third channel
+ break;
+ case 4:
+ BankMask[idx_bk].ch4 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask for all fourth channel
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * @brief Initializes the acquisition module.
+ * @param None
+ * @retval retval
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+ TSL_Init_GPIOs();
+ TSL_Init_TIMs();
+ TSL_Init_RI();
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Configures a Bank.
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ uint8_t idx;
+ uint16_t idx_dest;
+ uint16_t idx_ch;
+ uint16_t number_of_channels = 0;
+ CONST TSL_Bank_T *p_bank; // Pointer to the current bank
+ CONST TSL_ChannelDest_T *p_chDest; // Pointer to the first destination channel of the current bank
+ CONST TSL_ChannelSrc_T *p_chSrc; // Pointer to the fisrt source channel of the current bank
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ OldStatus = 0;
+
+ TSL_Globals.This_Bank = idx_bk;
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ number_of_channels = p_bank->NbChannels;
+ p_chDest = p_bank->p_chDest;
+ p_chSrc = p_bank->p_chSrc;
+
+ // Reset the disable mask
+ DisableSampling = 0;
+ for (idx = 0; idx < MAX_CHANNEL_NUMBER_BY_GROUP; idx++)
+ {
+ DisableMask[idx] = 0;
+ }
+
+#if (TSLPRM_USE_SHIELD > 0)
+ DISABLE_SAMPLING(p_bank->shield_sampling);
+#endif
+
+ // Loop for each channel of this bank
+ for (idx_ch = 0; idx_ch < number_of_channels; idx_ch++)
+ {
+
+ idx_dest = p_chDest->IdxDest;
+
+ // Mode Status OFF
+ if (p_bank->p_chData[idx_dest].Flags.ObjStatus == TSL_OBJ_STATUS_OFF)
+ {
+ // Update Mask if channels are disabled
+ DISABLE_MASK(p_chSrc->channel);
+ DISABLE_MASK(p_chSrc->sampling);
+ }
+
+ // Mode Status BURST ONLY
+ if (p_bank->p_chData[idx_dest].Flags.ObjStatus == TSL_OBJ_STATUS_BURST_ONLY)
+ {
+ DISABLE_SAMPLING(p_chSrc->sampling);
+ }
+
+ tab_MeasurementCounter[GPIO_to_SW_Conf[p_chSrc->sampling].IO_Group] = 0;
+
+ // Next channel
+ p_chSrc++;
+ p_chDest++;
+ }
+
+ // Get Mask for the current bank
+ CurrentBank[0] = (uint8_t)(BankMask[idx_bk].ch1 & (~DisableMask[0])); // Mask for all 1st channel are used by channels and sampling for this bank
+ CurrentBank[1] = (uint8_t)(BankMask[idx_bk].ch2 & (~DisableMask[1])); // Mask for all 2nd channel are used by channels and sampling for this bank
+ CurrentBank[2] = (uint8_t)(BankMask[idx_bk].ch3 & (~DisableMask[2])); // Mask for all 3rd channel are used by channels and sampling for this bank
+ CurrentBank[3] = (uint8_t)(BankMask[idx_bk].ch4 & (~DisableMask[3])); // Mask for all 4th channel are used by channels and sampling for this bank
+
+ CurrentChannel = ChannelMask[idx_bk]; // Mask for channels
+ CurrentSampling = (uint8_t)(3 << (2 * (SamplingMask[idx_bk] - 1))); // Mask for sampling
+ ChannelSampling = SamplingMask[idx_bk]; // Mask for the channel used by sampling
+
+ // Channel's state of the current bank
+ BankDone = (uint8_t)(CurrentBank[ChannelSampling - 1] & (~DisableSampling));
+
+ // Select the IO Input register corresponding to the channel sampling (to optimize the measurement)
+ p_IOIRx = RI_IOIRx_Register[ChannelSampling - 1];
+
+ // Select the IO Mask register corresponding to the channel sampling (to optimize the measurement)
+ p_IOMRx = RI_IOMRx_Register[ChannelSampling - 1];
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Start acquisition on a previously configured bank
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+#if (TSLPRM_IODEF > 0)
+
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]);
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ TSL_tNb_T number_of_channels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+
+ //============================
+ // All GPIOs in Input floating
+ //============================
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // GPIO in Input
+ GPIO_DDR_IN(p_bank->shield_sampling);
+ GPIO_DDR_IN(p_bank->shield_channel);
+ // GPIO in floating mode
+ GPIO_CR1_FLOATING(p_bank->shield_sampling);
+ GPIO_CR1_FLOATING(p_bank->shield_channel);
+#endif // TSLPRM_USE_SHIELD
+
+ number_of_channels = p_bank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < number_of_channels;
+ idx_ch++)
+ {
+ // GPIO in Input
+ GPIO_DDR_IN(p_chSrc->sampling);
+ GPIO_DDR_IN(p_chSrc->channel);
+ // GPIO in floating mode
+ GPIO_CR1_FLOATING(p_chSrc->sampling);
+ GPIO_CR1_FLOATING(p_chSrc->channel);
+ p_chSrc++;
+ }
+ }
+#endif // TSLPRM_IODEF
+
+ // Test if this bank is not empty
+ if (BankDone != 0)
+ {
+
+ // Set the AL bit to exit from WFI mode only on PXS interrupt
+ CFG->GCR |= (uint8_t)CFG_GCR_AL;
+
+ //--------------------------------------------
+ // Configure Timer3 for the MaxCount detection
+ //--------------------------------------------
+
+ // Clear the Slave timer counter
+ TIM3->CNTRH = 0;
+ TIM3->CNTRL = 0;
+
+ // Timer3 interruption routine to detect MaxCount
+ // Warning: the high byte must be written before the low byte
+ TIM3->CCR2H = (uint8_t)((TSL_Params.AcqMax+1) >> 8);
+ TIM3->CCR2L = (uint8_t)(TSL_Params.AcqMax+1);
+
+ // Clear all Timer3 flags...
+ TIM3->SR1 = 0;
+ TIM3->SR2 = 0;
+
+ // Enable Capture/Compare 2 interrupt: MaxCount
+ TIM3->IER |= 0x04; // CC2IE=1
+
+ //--------------------------------------------
+
+ // Enable necessary IOs
+ RI->IOCMR1 |= (uint8_t)CurrentBank[0];
+ RI->IOCMR2 |= (uint8_t)CurrentBank[1];
+ RI->IOCMR3 |= (uint8_t)CurrentBank[2];
+ RI->IOCMR4 |= (uint8_t)CurrentBank[3];
+
+ // Discharge all capacitors
+ RI->IOSR1 &= (uint8_t)(~CurrentBank[0]);
+ RI->IOSR2 &= (uint8_t)(~CurrentBank[1]);
+ RI->IOSR3 &= (uint8_t)(~CurrentBank[2]);
+ RI->IOSR4 &= (uint8_t)(~CurrentBank[3]);
+
+ // Wait a complete discharge
+ SoftDelay(TSLPRM_DELAY_DISCHARGE_ALL);
+
+ // Configure channel capacitors and sampling capacitors
+ RI->IOGCR = (uint8_t)(0x55 & (~CurrentSampling));
+
+ RI->IOSR1 |= (uint8_t)CurrentBank[0];
+ RI->IOSR2 |= (uint8_t)CurrentBank[1];
+ RI->IOSR3 |= (uint8_t)CurrentBank[2];
+ RI->IOSR4 |= (uint8_t)CurrentBank[3];
+
+ // Start acquisition
+ TSL_Acq_Status = TSL_STATUS_BUSY;
+
+ // Start the Master timer counter
+ TIM2->CR1 |= 0x01; // CEN=1
+ }
+ else
+ {
+ TSL_Acq_Status = TSL_STATUS_OK;
+ }
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ return TSL_Acq_Status;
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndex_T index)
+{
+ return(tab_MeasurementCounter[index]);
+}
+
+
+/**
+ * @brief Check noise (not used)
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ return TSL_ACQ_STATUS_OK;
+}
+
+
+/**
+ * @brief Used during HW acquisition mode.
+ * @param None
+ * @retval None
+ * @note Must be called by the TIM3 Capture/Compare interrupt routine.
+ */
+void TSL_CT_HWacq_TIM3(void)
+{
+ uint8_t new_status;
+ uint8_t idx = 0;
+ uint16_t timer_count;
+
+ TIM2->CR1 &= (uint8_t)(~0x01); // Stop master counter
+
+ RI->IOMR1 = 0;
+ RI->IOMR2 = 0;
+ RI->IOMR3 = 0;
+ RI->IOMR4 = 0;
+
+ // Discharge all capacitors (electrode and sampling capacitor IOs)
+ RI->IOSR1 &= (uint8_t)(~(CurrentBank[0]));
+ RI->IOSR2 &= (uint8_t)(~(CurrentBank[1]));
+ RI->IOSR3 &= (uint8_t)(~(CurrentBank[2]));
+ RI->IOSR4 &= (uint8_t)(~(CurrentBank[3]));
+
+ TSL_Acq_Status = TSL_STATUS_OK;
+
+ // Clear all Timer3 flags...
+ TIM3->SR1 = 0;
+ TIM3->SR2 = 0;
+
+ // Read capture counter
+ timer_count = (uint16_t)(TIM3->CCR1H << 8);
+ timer_count += TIM3->CCR1L;
+
+ new_status = (uint8_t)(BankDone & (~(OldStatus)));
+
+ while ((new_status != 0) && (idx < 8))
+ {
+ if ((new_status & (1 << idx)) != 0)
+ {
+ tab_MeasurementCounter[idx] = timer_count;
+ new_status &= (uint8_t)(~(1 << idx));
+ OldStatus |= (uint8_t)(1 << idx);
+ *p_IOMRx |= (uint8_t)(1 << idx); // Mask IO which reach VIH
+ }
+ idx++;
+ }
+}
+
+
+/**
+ * @brief Used during HW acquisition mode.
+ * @param None
+ * @retval None
+ * @note Must be called by the RI interrupt routine.
+ * Timer 2 and 3 are halted during this interrupt but counter is not reset.
+ */
+void TSL_CT_HWacq_RI(void)
+{
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]);
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ TSL_tNb_T number_of_channels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+
+ __IO uint8_t IOIRx;
+ uint8_t new_status;
+ uint8_t idx = 0;
+ uint16_t timer_count;
+
+ IOIRx = *p_IOIRx;
+
+ // Test RI Input register corresponding to sampling capacitors
+ if ((IOIRx & BankDone) != OldStatus)
+ {
+ // Read capture counter
+ timer_count = (uint16_t)(TIM3->CCR1H << 8);
+ timer_count += TIM3->CCR1L;
+
+ new_status = (uint8_t)((BankDone & IOIRx) & (~(OldStatus)));
+
+ while ((new_status != 0) && (idx < 8))
+ {
+ if ((new_status & (1 << idx)) != 0)
+ {
+ tab_MeasurementCounter[idx] = timer_count;
+ new_status &= (uint8_t)(~(1 << idx));
+ OldStatus |= (uint8_t)(1 << idx);
+ *p_IOMRx |= (uint8_t)(1 << idx); // Mask IO which reach VIH
+ }
+ idx++;
+ }
+
+ // When Current bank is completed
+ if ((OldStatus == BankDone))
+ {
+
+ // Disable master counter
+ TIM2->CR1 &= (uint8_t)(~0x01); // Stop master counter
+
+ // Reset IO Mask
+ RI->IOMR1 = 0;
+ RI->IOMR2 = 0;
+ RI->IOMR3 = 0;
+ RI->IOMR4 = 0;
+
+ // Disable necessary IOs
+ RI->IOSR1 &= (uint8_t)(~(CurrentBank[0]));
+ RI->IOSR2 &= (uint8_t)(~(CurrentBank[1]));
+ RI->IOSR3 &= (uint8_t)(~(CurrentBank[2]));
+ RI->IOSR4 &= (uint8_t)(~(CurrentBank[3]));
+
+ RI->IOCMR1 &= (uint8_t)(~(CurrentBank[0]));
+ RI->IOCMR2 &= (uint8_t)(~(CurrentBank[1]));
+ RI->IOCMR3 &= (uint8_t)(~(CurrentBank[2]));
+ RI->IOCMR4 &= (uint8_t)(~(CurrentBank[3]));
+
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+ number_of_channels = p_bank->NbChannels;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // GPIO in Output
+ GPIO_DDR_OUT(p_bank->shield_sampling);
+ GPIO_DDR_OUT(p_bank->shield_channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_bank->shield_sampling);
+ GPIO_CR1_PP(p_bank->shield_channel);
+ // Output in Low level
+ GPIO_ODR_LOW(p_bank->shield_sampling);
+ GPIO_ODR_LOW(p_bank->shield_channel);
+#endif
+ // Initialize the mask for channel and sampling
+ for (idx_ch = 0; idx_ch < number_of_channels; idx_ch++)
+ {
+ // GPIO are configured in PP Low mode when inactive
+ // GPIO in Output
+ GPIO_DDR_OUT(p_chSrc->sampling);
+ GPIO_DDR_OUT(p_chSrc->channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_chSrc->sampling);
+ GPIO_CR1_PP(p_chSrc->channel);
+ // Output in Low level
+ GPIO_ODR_LOW(p_chSrc->sampling);
+ GPIO_ODR_LOW(p_chSrc->channel);
+ // Next channel
+ p_chSrc++;
+ }
+ }
+
+#if TSLPRM_USE_ZONE > 0
+
+ TSL_acq_BankGetResult(TSL_Globals.This_Bank, 0, 0); // Get Bank Result
+
+ if ((TSL_Globals.This_Zone == 0) || (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks))
+ {
+ CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing
+ TSL_Globals.This_Bank = 0;
+ }
+ else
+ {
+ if (TSL_acq_ZoneConfig(TSL_Globals.This_Zone, TSL_Globals.Index_In_This_Zone) != TSL_STATUS_ERROR)
+ {
+ // Start Bank acquisition
+ TSL_acq_BankStartAcq();
+ }
+ else
+ {
+ CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing
+ TSL_Globals.This_Bank = 0;
+ }
+ }
+#else
+ CFG->GCR &= (uint8_t)(~CFG_GCR_AL);
+#endif
+ }
+ }
+
+ // Reset Interrupt flag
+ RI->CR |= 0x02; // CAIF=1
+ TSL_Acq_Status = TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Check if a filter must be used on the current channel (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if a filter can be applied
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ return TSL_TRUE;
+}
+
+
+/**
+ * @brief Compute the Delta value
+ * @param[in] ref Reference value
+ * @param[in] meas Last Measurement value
+ * @retval Delta value
+ */
+TSL_tDelta_T TSL_acq_ComputeDelta(TSL_tRef_T ref, TSL_tMeas_T meas)
+{
+ return((TSL_tDelta_T)(ref - meas));
+}
+
+
+/**
+ * @brief Compute the Measurement value
+ * @param[in] ref Reference value
+ * @param[in] delta Delta value
+ * @retval Measurement value
+ */
+TSL_tMeas_T TSL_acq_ComputeMeas(TSL_tRef_T ref, TSL_tDelta_T delta)
+{
+ return((TSL_tMeas_T)(ref - delta));
+}
+
+
+/**
+ * @brief Test if the Reference is incorrect (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if the Reference is out of range
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ return TSL_FALSE;
+}
+
+
+/**
+ * @brief Test if the measure has crossed the reference target (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result TRUE if the Reference is valid
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ return TSL_TRUE;
+}
+
+
+#if defined(__ICCSTM8__)
+#pragma optimize=low
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * @retval None
+ */
+void SoftDelay(uint16_t val)
+{
+ uint16_t idx;
+ for (idx = val; idx > 0; idx--)
+ {
+ nop();
+ }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_sw.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_sw.c
new file mode 100644
index 0000000..0334c22
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8l_sw.c
@@ -0,0 +1,1426 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm8l_sw.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the acquisition
+ * on STM8L products using the software acquisition mode.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm8l_sw.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+
+/** Structure containing RI IO informations according to GPIO.
+ */
+typedef struct
+{
+ unsigned int IO_Channel : 4; /**< Channel number from 1 to 4 in the Routing interface group */
+ unsigned int IO_Group : 4; /**< Group number in the Routing interface */
+} TSL_IOConf_T;
+
+/* Private defines -----------------------------------------------------------*/
+
+/** Define if maximum channel number is 3 or 4 according to the Device Density
+ */
+#if defined(STM8L15X_LD) || defined(STM8L10X)
+#define MAX_CHANNEL_NUMBER_BY_GROUP (4)
+#else
+#define MAX_CHANNEL_NUMBER_BY_GROUP (3)
+#endif // defined(STM8L15X_LD) || defined(STM8L10X)
+
+#if defined(_COSMIC_)
+#define INLINE @inline
+#elif defined(_RAISONANCE_)
+#define INLINE inline
+#elif defined(_IAR_)
+#define INLINE
+#else
+#error "Compiler not Supported"
+#endif
+
+/* Private macros ------------------------------------------------------------*/
+
+#if !defined(STM8L10X)
+#define GPIO_PORT(GPIO) (GPIO >> 3) /**< Get the GPIO port*/
+#define GPIO_BIT(GPIO) (GPIO & 0x07) /**< Get the GPIO pin number*/
+#else
+#define GPIO_PORT(GPIO) (GPIO >> 2) /**< Get the GPIO port*/
+#define GPIO_BIT(GPIO) (GPIO & 0x03) /**< Get the GPIO pin number*/
+#endif // !defined(STM8L10X)
+
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS))) /**< Check if the index have a good range*/
+
+#define GPIO_ODR_HIGH(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->ODR |= (uint8_t)(1 << GPIO_BIT(GPIO)))
+#define GPIO_ODR_LOW(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->ODR &= (uint8_t)(~(1 << GPIO_BIT(GPIO))))
+#define GPIO_DDR_IN(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->DDR &= (uint8_t)(~(1 << GPIO_BIT(GPIO))))
+#define GPIO_DDR_OUT(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->DDR |= (uint8_t)(1 << GPIO_BIT(GPIO)))
+#define GPIO_CR1_PP(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->CR1 |= (uint8_t)(1 << GPIO_BIT(GPIO)))
+#define GPIO_CR1_FLOATING(GPIO) (p_GPIOx[GPIO_PORT(GPIO)]->CR1 &= (uint8_t)(~(1 << GPIO_BIT(GPIO))))
+
+#define DISABLE_MASK(GPIO) (DisableMask[(GPIO_to_SW_Conf[GPIO].IO_Channel)-1] |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group)) /**< Create disable mask array to modify initial bank mask before acquisition (only for STATUS_OFF)*/
+#define DISABLE_SAMPLING(GPIO) (DisableSampling |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group)) /**< Create disable sampling mask to don't take sampling measurement of corresponding channels(for STATUS_BURST_ONLY and shield) */
+
+/* Private variables ---------------------------------------------------------*/
+
+uint8_t SpreadCounter = TSLPRM_SPREAD_MIN;
+
+uint16_t ChargeTransferCounter; // This variable count the charge transfer number in the acquisition loop
+uint8_t BankDone; // Control if all activate sampling reach the VIH level
+uint8_t CurrentSampling; // Mask to control IOGCR register
+uint8_t CurrentChannel; // Mask to control IOGCR register
+uint8_t ChannelSampling; // Contain the channel number where all sampling are connected
+uint8_t DisableSampling; // Disable sampling mask when the Burst Only mode is activated for one channel of the current bank(not get the measure)
+
+TSL_Bank_Config_Mask_T BankMask[TSLPRM_TOTAL_BANKS]; // Complete masks (channel and sampling) to configure IOCMRx and IOSRx registers for all banks
+uint8_t SamplingMask[TSLPRM_TOTAL_BANKS]; // Sampling mask to configure IOGCR register for all banks
+uint8_t DisableMask[MAX_CHANNEL_NUMBER_BY_GROUP]; // Complete disable mask(channel and sampling) when the Channel OFF mode is activated for one channel of the current bank(to modifie the CurrentBank)
+uint8_t CurrentBank[MAX_CHANNEL_NUMBER_BY_GROUP]; // Complete mask for the current bank
+
+#if !defined(STM8L10X)
+
+#if defined(STM8L15X_LD)
+__IO uint8_t *RI_IOIRx_Register[MAX_CHANNEL_NUMBER_BY_GROUP] = {&(RI->IOIR1), &(RI->IOIR2), &(RI->IOIR3), &(RI->IOIR4)};
+#else
+__IO uint8_t *RI_IOIRx_Register[MAX_CHANNEL_NUMBER_BY_GROUP] = {&(RI->IOIR1), &(RI->IOIR2), &(RI->IOIR3)};
+#endif // STM8L15X_LD
+
+__IO uint8_t *p_IOIRx; // Pointer to the IOIRx register (x from 1 to 4)
+GPIO_TypeDef *p_GPIOx[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF};
+
+uint16_t tab_MeasurementCounter[8] = {0}; // Measurement of each sampling of the current bank
+uint8_t ChannelMask[TSLPRM_TOTAL_BANKS]; // Channel mask to configure IOGCR register for all banks
+
+/* Table which do the link between GPIO and switch configuation:{x,y}
+ x = channel number
+ y = group number - 1
+ Note: {0,0} = not connect to IO switch
+*/
+CONST TSL_IOConf_T GPIO_to_SW_Conf[40] =
+{
+ // Port A definitions
+ {0, 0}, // PA0
+ {0, 0}, // PA1
+ {0, 0}, // PA2
+ {0, 0}, // PA3
+ {3, 0}, // PA4 is channel 3 of Group 1
+ {2, 0}, // PA5 is channel 2 of Group 1
+ {1, 0}, // PA6 is channel 1 of Group 1
+ {4, 0}, // PA7 is channel 4 of Group 1
+ // Port B definitions
+ {1, 6}, // PB0
+ {3, 5},
+ {2, 5},
+ {1, 5},
+ {3, 4},
+ {2, 4},
+ {1, 4},
+ {3, 3}, // PB7
+ // Port C definitions
+ {0, 0}, // PC0
+ {0, 0},
+ {1, 2},
+ {3, 1},
+ {2, 1},
+ {0, 0},
+ {0, 0},
+ {1, 1}, // PC7
+ // Port D definitions
+ {2, 7}, // PD0
+ {1, 7},
+ {3, 6},
+ {2, 6},
+ {2, 3},
+ {1, 3},
+ {3, 2},
+ {2, 2}, // PD7
+ // Port E definitions
+ {0, 0}, // PE0
+ {0, 0},
+ {0, 0},
+ {4, 6},
+ {4, 7},
+ {3, 7},
+ {0, 0},
+ {4, 1} // PE7
+};
+
+#else // STM8L10X
+
+__IO uint8_t *p_GPIOx_IDR;
+__IO uint8_t *GPIOx_IDR[2] = {&(GPIOB->IDR), &(GPIOD->IDR)};
+
+GPIO_TypeDef *p_GPIOx[] = {GPIOB, GPIOD};
+
+uint16_t tab_MeasurementCounter[2] = {0}; // Measurement of each sampling of the current bank
+uint8_t Bank_IO_CompMask[TSLPRM_TOTAL_BANKS]; // IO Mask for Comparator register to control SW
+uint8_t BankSamplingCompMask[TSLPRM_TOTAL_BANKS]; // Sampling Mask for Comparator register to control SW
+uint8_t Bank_IOShield_CompMask[TSLPRM_TOTAL_BANKS];
+uint8_t BankSamplingShieldCompMask[TSLPRM_TOTAL_BANKS];
+
+/* Table which do the link between GPIO and switch configuation:{x,y}
+ x = channel number
+ y = group number - 1
+ Note: {0,0} = not connect to IO switch
+*/
+CONST TSL_IOConf_T GPIO_to_SW_Conf[8] =
+{
+ // Port B definitions
+ {1, 0}, // PB0 is channel 1 of Group 1
+ {2, 0}, // PB1 is channel 2 of Group 1
+ {1, 1}, // PB2 is channel 1 of Group 2
+ {2, 1}, // PB3 is channel 2 of Group 2
+ // Port D definitions
+ {3, 0}, // PD0 is channel 3 of Group 1
+ {4, 0}, // PD1 is channel 4 of Group 1
+ {3, 1}, // PD2 is channel 3 of Group 2
+ {4, 1} // PD3 is channel 4 of Group 2
+};
+
+#endif // !defined(STM8L10X)
+
+/* Private functions prototype -----------------------------------------------*/
+void SoftDelay(uint16_t val);
+void CreateMask(TSL_tIndex_T idx_bk, uint8_t GPIO);
+void GetCounter(__IO uint8_t *p_reg, uint8_t *p_old_status);
+INLINE void __Delay_Charge(void);
+void CreateIOMask(TSL_tIndex_T idx_bk, uint8_t GPIO);
+void CreateSamplingMask(TSL_tIndex_T idx_bk, uint8_t GPIO);
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+INLINE void SwSpreadSpectrum(void);
+#endif
+
+
+/**
+ * @brief Delay in NOPs to apply during charging time.
+ * @param None
+ * @retval None
+ */
+INLINE void __Delay_Charge(void)
+{
+#if TSLPRM_DELAY_CHARGE > 0
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 1
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 2
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 3
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 4
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 5
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 6
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 7
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 8
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 9
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 10
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 11
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 12
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 13
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 14
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 15
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 16
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 17
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 18
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 19
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 20
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 21
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 22
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 23
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 24
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 25
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 26
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 27
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 28
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 29
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 30
+ nop();
+#endif
+#if TSLPRM_DELAY_CHARGE > 31
+ nop();
+#endif
+}
+
+
+/**
+ * @brief Delay in NOPs to apply during transfering time.
+ * @param None
+ * @retval None
+ */
+INLINE void __Delay_Transfer(void)
+{
+#if TSLPRM_DELAY_TRANSFER > 0
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 1
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 2
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 3
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 4
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 5
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 6
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 7
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 8
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 9
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 10
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 11
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 12
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 13
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 14
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 15
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 16
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 17
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 18
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 19
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 20
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 21
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 22
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 23
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 24
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 25
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 26
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 27
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 28
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 29
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 30
+ nop();
+#endif
+#if TSLPRM_DELAY_TRANSFER > 31
+ nop();
+#endif
+}
+
+
+/**
+ * @brief Initialize the acquisition module.
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]); // Pointer to the first bank
+ CONST TSL_ChannelSrc_T *p_chSrc = p_bank->p_chSrc; // Pointer to the source channel of the current bank
+ TSL_tNb_T number_of_channels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+
+#if !defined(STM8L10X)
+ // Enable comparator clock to activate the RI block
+ CLK->PCKENR2 |= CLK_PCKENR2_COMP;
+#endif // !defined(STM8L10X)
+
+ // Enable mode software (bit AM)
+#if defined(STM8L15X_LD)
+ RI->CR &= (uint8_t)(~0x04); // Mode SW
+#endif // STM8L15X_LD
+
+ // Initializes each bank and configures the used GPIO
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+ number_of_channels = p_bank->NbChannels;
+
+#if !defined(STM8L10X)
+ // Mask Initialization
+ BankMask[idx_bk].ch1 = 0;
+ BankMask[idx_bk].ch2 = 0;
+ BankMask[idx_bk].ch3 = 0;
+ BankMask[idx_bk].ch4 = 0;
+#else
+ // Mask Initialization
+ BankMask[idx_bk].GPIOB_IO = 0;
+ BankMask[idx_bk].GPIOB_Samp = 0;
+ BankMask[idx_bk].GPIOD_IO = 0;
+ BankMask[idx_bk].GPIOD_Samp = 0;
+#endif // !defined(STM8L10X)
+
+ // Get which channel is used for sampling only one time because it's the same for each couple
+ SamplingMask[idx_bk] = (uint8_t)GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel;
+
+#if (TSLPRM_USE_SHIELD > 0)
+
+ // Create Mask per bank for shield
+#if !defined(STM8L10X)
+ CreateMask(idx_bk, p_bank->shield_sampling);
+ CreateMask(idx_bk, p_bank->shield_channel);
+ ChannelMask[idx_bk] |= (uint8_t)(3 << (2 * ((GPIO_to_SW_Conf[p_bank->shield_channel].IO_Channel) - 1)));
+#else
+ CreateIOMask(idx_bk, p_bank->shield_channel);
+ CreateSamplingMask(idx_bk, p_bank->shield_sampling);
+#endif // !defined(STM8L10X)
+
+ // Check if shield sampling capacitors are in the same number of channel for each group
+ if ((SamplingMask[idx_bk] != (uint8_t)GPIO_to_SW_Conf[p_bank->shield_sampling].IO_Channel))
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ // GPIO in Output
+ GPIO_DDR_OUT(p_bank->shield_sampling);
+ GPIO_DDR_OUT(p_bank->shield_channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_bank->shield_sampling);
+ GPIO_CR1_PP(p_bank->shield_channel);
+ // Output in Low level
+ GPIO_ODR_LOW(p_bank->shield_sampling);
+ GPIO_ODR_LOW(p_bank->shield_channel);
+
+ // Activate Comparator 1
+ if (GPIO_to_SW_Conf[p_bank->shield_sampling].IO_Group == 0)
+ {
+ COMP->CR |= 0x02;
+ }
+ // Activate Comparator 2
+ if (GPIO_to_SW_Conf[p_bank->shield_sampling].IO_Group == 1)
+ {
+ COMP->CR |= 0x04;
+ }
+
+#endif // TSLPRM_USE_SHIELD
+
+ // Initialize the mask for channel and sampling
+ for (idx_ch = 0; idx_ch < number_of_channels; idx_ch++)
+ {
+#if !defined(STM8L10X)
+ // Create Mask per bank for channel and sampling
+ CreateMask(idx_bk, p_chSrc->channel);
+ CreateMask(idx_bk, p_chSrc->sampling);
+ ChannelMask[idx_bk] |= (uint8_t)(3 << (2 * ((GPIO_to_SW_Conf[p_chSrc->channel].IO_Channel) - 1)));
+ // Check if sampling capacitors are in the same number of channel for each group
+ if ((SamplingMask[idx_bk] != (uint8_t)GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel))
+ {
+ return TSL_STATUS_ERROR;
+ }
+#else
+ // Activate Comparator 1
+ if (p_chSrc->IdxSrc == 0)
+ {
+ COMP->CR |= 0x02;
+ }
+ // Activate Comparator 2
+ if (p_chSrc->IdxSrc == 1)
+ {
+ COMP->CR |= 0x04;
+ }
+ // Create Mask per bank for channel and sampling
+ CreateIOMask(idx_bk,p_chSrc->channel);
+ Bank_IO_CompMask[idx_bk] |= (uint8_t)(1 << (GPIO_to_SW_Conf[p_chSrc->channel].IO_Channel - 1));
+ Bank_IO_CompMask[idx_bk] = (uint8_t)(Bank_IO_CompMask[idx_bk] << (4 * GPIO_to_SW_Conf[p_chSrc->channel].IO_Group));
+ CreateSamplingMask(idx_bk,p_chSrc->sampling);
+ BankSamplingCompMask[idx_bk] |= (uint8_t)(1 << (GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel - 1));
+ BankSamplingCompMask[idx_bk] = (uint8_t)(BankSamplingCompMask[idx_bk] << (4 * GPIO_to_SW_Conf[p_chSrc->sampling].IO_Group));
+ if ((SamplingMask[idx_bk] != (uint8_t)GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel))
+ {
+ return TSL_STATUS_ERROR;
+ }
+#if (TSLPRM_USE_SHIELD > 0)
+ Bank_IOShield_CompMask[idx_bk] |= (uint8_t)(1 << (GPIO_to_SW_Conf[p_bank->shield_channel].IO_Channel - 1));
+ Bank_IOShield_CompMask[idx_bk] = (uint8_t)(Bank_IOShield_CompMask[idx_bk] << (4 * GPIO_to_SW_Conf[p_bank->shield_channel].IO_Group));
+ BankSamplingShieldCompMask[idx_bk] |= (uint8_t)(1 << (GPIO_to_SW_Conf[p_bank->shield_sampling].IO_Channel - 1));
+ BankSamplingShieldCompMask[idx_bk] = (uint8_t)(BankSamplingShieldCompMask[idx_bk] << (4 * GPIO_to_SW_Conf[p_bank->shield_sampling].IO_Group));
+ Bank_IO_CompMask[idx_bk] = (uint8_t)(Bank_IO_CompMask[idx_bk] | Bank_IOShield_CompMask[idx_bk]);
+ BankSamplingCompMask[idx_bk] = (uint8_t)(BankSamplingCompMask[idx_bk] | BankSamplingShieldCompMask[idx_bk]);
+#endif
+#endif // !defined(STM8L10X)
+
+ // GPIO are configured in PP Low mode when inactive
+ // GPIO in Output
+ GPIO_DDR_OUT(p_chSrc->sampling);
+ GPIO_DDR_OUT(p_chSrc->channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_chSrc->sampling);
+ GPIO_CR1_PP(p_chSrc->channel);
+ // Output in Low level
+ GPIO_ODR_LOW(p_chSrc->sampling);
+ GPIO_ODR_LOW(p_chSrc->channel);
+
+ p_chSrc++; // Next channel
+ }
+
+#if !defined(STM8L10X)
+ // Unlock IO to RI register: IO controlled by GPIO
+ RI->IOCMR1 &= (uint8_t)(~BankMask[idx_bk].ch1);
+ RI->IOCMR2 &= (uint8_t)(~BankMask[idx_bk].ch2);
+ RI->IOCMR3 &= (uint8_t)(~BankMask[idx_bk].ch3);
+#if defined(STM8L15X_LD)
+ RI->IOCMR4 &= (uint8_t)(~BankMask[idx_bk].ch4);
+#endif // STM8L15X_LD || STM8L10X
+#endif // !defined(STM8L10X)
+ }
+
+ return TSL_STATUS_OK;
+}
+
+
+#if !defined(STM8L10X)
+/**
+ * @brief Create Mask for all banks
+ * @param[in] idx_bk Index of the Bank to configure
+ * @param[in] GPIO Pin number
+ * @retval None
+ */
+void CreateMask(TSL_tIndex_T idx_bk, uint8_t GPIO)
+{
+ switch (GPIO_to_SW_Conf[GPIO].IO_Channel)
+ {
+ case 1:
+ BankMask[idx_bk].ch1 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask for all first channel
+ break;
+ case 2:
+ BankMask[idx_bk].ch2 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask for all second channel
+ break;
+ case 3:
+ BankMask[idx_bk].ch3 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask fo all third channel
+ break;
+#if defined(STM8L15X_LD) || defined(STM8L10X)
+ case 4:
+ BankMask[idx_bk].ch4 |= (uint8_t)(1 << GPIO_to_SW_Conf[GPIO].IO_Group); // Mask for all fourth channel
+ break;
+#endif // STM8L15X_LD || STM8L10X
+ default:
+ break;
+ }
+}
+
+#else
+
+/**
+ * @brief Create IO Mask for all banks
+ * @param[in] idx_bk Index of the Bank to configure
+ * @param[in] GPIO Pin number
+ * @retval None
+ */
+void CreateIOMask(TSL_tIndex_T idx_bk, uint8_t GPIO)
+{
+ switch (GPIO_PORT(GPIO))
+ {
+ case 0:
+ BankMask[idx_bk].GPIOB_IO |= (uint8_t)(1 << GPIO_BIT(GPIO));
+ break;
+ case 1:
+ BankMask[idx_bk].GPIOD_IO |= (uint8_t)(1 << GPIO_BIT(GPIO));
+ break;
+ default:
+ break;
+ }
+}
+
+
+/**
+ * @brief Create Sampling Mask for all banks
+ * @param[in] idx_bk Index of the Bank to configure
+ * @param[in] GPIO Pin number
+ * @retval None
+ */
+void CreateSamplingMask(TSL_tIndex_T idx_bk, uint8_t GPIO)
+{
+ switch (GPIO_PORT(GPIO))
+ {
+ case 0:
+ BankMask[idx_bk].GPIOB_Samp |= (uint8_t)(1 << GPIO_BIT(GPIO));
+ break;
+ case 1:
+ BankMask[idx_bk].GPIOD_Samp |= (uint8_t)(1 << GPIO_BIT(GPIO));
+ break;
+ default:
+ break;
+ }
+}
+
+#endif // !defined(STM8L10X)
+
+
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+/**
+ * @brief Spread Spectrum using a variable software delay.
+ * @param None
+ * @retval None
+ */
+INLINE void SwSpreadSpectrum(void)
+{
+ uint8_t idx;
+
+ SpreadCounter++;
+
+ if (SpreadCounter == TSLPRM_SPREAD_MAX)
+ {
+ SpreadCounter = TSLPRM_SPREAD_MIN;
+ }
+
+ idx = SpreadCounter;
+
+ while (--idx) {}
+}
+#endif
+
+
+/**
+ * @brief Bank configuration
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ uint8_t idx_i;
+#if defined(STM8L10X)
+ uint8_t GroupUsed = 0;
+#endif
+ TSL_tIndex_T idx_dest;
+ TSL_tIndex_T idx_ch;
+ TSL_tNb_T number_of_channels = 0;
+ CONST TSL_Bank_T *p_bank; // Pointer to the current bank
+ CONST TSL_ChannelDest_T *p_chDest; // Pointer to the first destination channel of the current bank
+ CONST TSL_ChannelSrc_T *p_chSrc; // Pointer to the fisrt source channel of the current bank
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ number_of_channels = p_bank->NbChannels;
+ p_chDest = p_bank->p_chDest;
+ p_chSrc = p_bank->p_chSrc;
+
+ // Reset the disable mask
+ DisableSampling = 0;
+ for (idx_i = 0; idx_i < MAX_CHANNEL_NUMBER_BY_GROUP; idx_i++)
+ {
+ DisableMask[idx_i] = 0;
+ }
+
+ BankDone = 0;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ DISABLE_SAMPLING(p_bank->shield_sampling);
+#endif // TSLPRM_USE_SHIELD
+
+ ChannelSampling = SamplingMask[idx_bk]; // Mask for the channel used by sampling
+
+ // Loop for each channel of this bank
+ for (idx_ch = 0; idx_ch < number_of_channels; idx_ch++)
+ {
+ idx_dest = p_chDest->IdxDest;
+#if defined(STM8L10X)
+ if (p_chSrc->IdxSrc == 0)
+ {
+ GroupUsed |= 0x01;
+ }
+ if (p_chSrc->IdxSrc == 1)
+ {
+ GroupUsed |= 0x02;
+ }
+#endif // defined(STM8L10X)
+
+ // Mode Status OFF
+ if (p_bank->p_chData[idx_dest].Flags.ObjStatus == TSL_OBJ_STATUS_OFF)
+ {
+#if !defined(STM8L10X)
+ // Update Mask if channels are disabled
+ DISABLE_MASK(p_chSrc->channel);
+ DISABLE_MASK(p_chSrc->sampling);
+#else
+ // Update Mask if channels are disabled
+ if (GPIO_to_SW_Conf[p_chSrc->channel].IO_Channel > 2)
+ {
+ DisableMask[2] |= (uint8_t)(1 << ((2 * GPIO_to_SW_Conf[p_chSrc->channel].IO_Group) + (GPIO_to_SW_Conf[p_chSrc->channel].IO_Channel - 3)));
+ }
+ else
+ {
+ DisableMask[0] |= (uint8_t)(1 << ((2 * GPIO_to_SW_Conf[p_chSrc->channel].IO_Group) + (GPIO_to_SW_Conf[p_chSrc->channel].IO_Channel - 1)));
+ }
+ if (GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel > 2)
+ {
+ DisableMask[3] |= (uint8_t)(1 << ((2 * GPIO_to_SW_Conf[p_chSrc->sampling].IO_Group) + (GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel - 3)));
+ }
+ else
+ {
+ DisableMask[1] |= (uint8_t)(1<<((2 * GPIO_to_SW_Conf[p_chSrc->sampling].IO_Group) + (GPIO_to_SW_Conf[p_chSrc->sampling].IO_Channel - 1)));
+ }
+#endif // !defined(STM8L10X)
+ }
+
+ // Mode Status BURST ONLY
+ if (p_bank->p_chData[idx_dest].Flags.ObjStatus == TSL_OBJ_STATUS_BURST_ONLY)
+ {
+#if !defined(STM8L10X)
+ DISABLE_SAMPLING(p_chSrc->sampling);
+#else
+ if (p_chSrc->IdxSrc == 0)
+ {
+ GroupUsed &= (uint8_t)(~0x01);
+ }
+ if (p_chSrc->IdxSrc == 1)
+ {
+ GroupUsed &= (uint8_t)(~0x02);
+ }
+#endif // !defined(STM8L10X)
+ }
+
+ tab_MeasurementCounter[GPIO_to_SW_Conf[p_chSrc->sampling].IO_Group] = 0;
+
+ // Next channel
+ p_chSrc++;
+ p_chDest++;
+ }
+
+#if !defined(STM8L10X)
+ //Get Mask for the current bank
+ CurrentBank[0] = (uint8_t)(BankMask[idx_bk].ch1 & (~DisableMask[0])); // Mask for all 1st channel are used by channels and sampling for this bank
+ CurrentBank[1] = (uint8_t)(BankMask[idx_bk].ch2 & (~DisableMask[1])); // Mask for all 2nd channel are used by channels and sampling for this bank
+ CurrentBank[2] = (uint8_t)(BankMask[idx_bk].ch3 & (~DisableMask[2])); // Mask for all 3rd channel are used by channels and sampling for this bank
+#if defined(STM8L15X_LD)
+ CurrentBank[3] = (uint8_t)(BankMask[idx_bk].ch4 & (~DisableMask[3])); // Mask for all 4th channel are used by channels and sampling for this bank
+#endif // STM8L15X_LD
+ CurrentChannel = ChannelMask[idx_bk]; // Mask for channels
+ CurrentSampling = (uint8_t)(3 << (2 * (SamplingMask[idx_bk] - 1))); // Mask for sampling
+
+ // Channel's state of the current bank
+ BankDone = (uint8_t)(CurrentBank[ChannelSampling - 1] & (~DisableSampling));
+
+ // Select the Input register corresponding to the channel sampling (to optimize the measurement)
+ p_IOIRx = RI_IOIRx_Register[ChannelSampling - 1];
+
+#else
+ //Get Mask for the current bank
+ CurrentBank[0] = (uint8_t)(BankMask[idx_bk].GPIOB_IO & (~DisableMask[0]));
+ CurrentBank[1] = (uint8_t)(BankMask[idx_bk].GPIOB_Samp & (~DisableMask[1]));
+ CurrentBank[2] = (uint8_t)(BankMask[idx_bk].GPIOD_IO & (~DisableMask[2]));
+ CurrentBank[3] = (uint8_t)(BankMask[idx_bk].GPIOD_Samp & (~DisableMask[3]));
+
+ CurrentChannel = (uint8_t)(Bank_IO_CompMask[idx_bk]); // Mask for channels
+ CurrentSampling = (uint8_t)(BankSamplingCompMask[idx_bk]); // Mask for sampling
+
+ // Select the Input register corresponding to the channel sampling (to optimize the measurement) and update BankDone, which is the mask where there are sampling capacitors
+ if (ChannelSampling > 2) // GPIOD
+ {
+ p_GPIOx_IDR = GPIOx_IDR[1];
+ if ((GroupUsed & 0x01) == 1)
+ {
+ BankDone |= (uint8_t)(1 << (ChannelSampling - 3));
+ }
+ if((GroupUsed & 0x02) == 2)
+ {
+ BankDone |= (uint8_t)(1 << (2 + (ChannelSampling - 3)));
+ }
+
+ }
+ else // GPIOB
+ {
+ p_GPIOx_IDR = GPIOx_IDR[0];
+ if ((GroupUsed & 0x01) == 1)
+ {
+ BankDone |= (uint8_t)(1 << (ChannelSampling - 1));
+ }
+ if ((GroupUsed & 0x02) == 2)
+ {
+ BankDone |= (uint8_t)(1 << (2 + (ChannelSampling - 1)));
+ }
+ }
+
+#endif // !defined(STM8L10X)
+
+ return TSL_STATUS_OK;
+}
+
+
+#if !defined(STM8L10X)
+
+/**
+ * @brief Start acquisition
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]);
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ TSL_tNb_T number_of_channels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+ uint8_t step3, step5, deadtime1, deadtime2; //intermediate variables to speed-up the acquisition loop
+
+ uint8_t old_status = 0;
+
+ ChargeTransferCounter = 0;
+
+#if (TSLPRM_IODEF > 0)
+ //============================
+ // All GPIOs in Input floating
+ //============================
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // GPIO in floating mode
+ GPIO_CR1_FLOATING(p_bank->shield_sampling);
+ GPIO_CR1_FLOATING(p_bank->shield_channel);
+ // GPIO in Input
+ GPIO_DDR_IN(p_bank->shield_sampling);
+ GPIO_DDR_IN(p_bank->shield_channel);
+#endif // TSLPRM_USE_SHIELD
+
+ number_of_channels = p_bank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < number_of_channels;
+ idx_ch++)
+ {
+ // GPIO in floating mode
+ GPIO_CR1_FLOATING(p_chSrc->sampling);
+ GPIO_CR1_FLOATING(p_chSrc->channel);
+ // GPIO in Input
+ GPIO_DDR_IN(p_chSrc->sampling);
+ GPIO_DDR_IN(p_chSrc->channel);
+ p_chSrc++;
+ }
+ }
+#endif // TSLPRM_IODEF
+
+ // Test if this bank is not empty
+ if (BankDone != 0)
+ {
+ // Enable necessary IOs
+ RI->IOCMR1 |= (uint8_t)CurrentBank[0];
+ RI->IOCMR2 |= (uint8_t)CurrentBank[1];
+ RI->IOCMR3 |= (uint8_t)CurrentBank[2];
+#if defined(STM8L15X_LD)
+ RI->IOCMR4 |= (uint8_t)CurrentBank[3];
+#endif // STM8L15X_LD
+
+ RI->IOSR1 |= (uint8_t)CurrentBank[0];
+ RI->IOSR2 |= (uint8_t)CurrentBank[1];
+ RI->IOSR3 |= (uint8_t)CurrentBank[2];
+#if defined(STM8L15X_LD)
+ RI->IOSR4 |= (uint8_t)CurrentBank[3];
+#endif // STM8L15X_LD
+
+ /* STEP1 : Discharging all capacitors
+ ==> all IOs in Push-Pull LOW */
+ RI->IOGCR &= (uint8_t)(~(CurrentChannel | CurrentSampling));
+
+ /* STEP2: Waiting for complete discharge */
+ SoftDelay(TSLPRM_DELAY_DISCHARGE_ALL);
+ // Dead Time
+ RI->IOGCR |= (uint8_t)(0xAA & (CurrentChannel | CurrentSampling));
+
+ // Close switch sampling
+ RI->IOGCR |= CurrentSampling;
+
+ /* Copmpute RI->IOGCR for each step */
+ /* STEP3: Charging C-Touch
+ ==> Channels in Push-Pull HIGH
+ ==> Sampling kept open */
+ step3 = (uint8_t)(RI->IOGCR ^ CurrentChannel);
+ /* Deadtime */
+ deadtime1 = RI->IOGCR ; // equivalent to step3 ^ (uint8_t)CurrentChannel;
+ /* STEP5: Transfering C-Touch charge in C-Sampling
+ ==> Close IOs Switchs */
+ step5 = (uint8_t)(RI->IOGCR | CurrentChannel);
+ /* Deadtime */
+ deadtime2 = (uint8_t)(step5 & (0xAA | (~CurrentChannel)));
+
+ // Loop while all sampling have not reach the VIH level
+ do
+ {
+ /* STEP3: Charging C-Touch */
+ RI->IOGCR = step3;
+ // Get the measurement of counter if the value of Input register change
+ if ((*p_IOIRx & BankDone) != old_status)
+ {
+ GetCounter(p_IOIRx, &old_status);
+ }
+
+ /* STEP4 : Waiting for good chargement */
+ __Delay_Charge();
+
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+ SwSpreadSpectrum();
+#endif
+
+ /* Dead Time */
+ RI->IOGCR = deadtime1;
+ /* STEP5: Transfering C-Touch charge in C-Sampling */
+ RI->IOGCR = step5;
+
+ ChargeTransferCounter++;
+
+ /* STEP6: Waiting for good transfer */
+ __Delay_Transfer();
+
+ /* Dead Time */
+ RI->IOGCR = deadtime1;
+ } while ((old_status != BankDone) && (ChargeTransferCounter <= TSL_Params.AcqMax));
+
+ // Get the value of counter if he reach the Max count
+ if(ChargeTransferCounter > TSL_Params.AcqMax)
+ {
+ GetCounter(&BankDone, &old_status);
+ }
+
+ // Disable necessary IOs
+ RI->IOSR1 &= (uint8_t)(~(CurrentBank[0]));
+ RI->IOSR2 &= (uint8_t)(~(CurrentBank[1]));
+ RI->IOSR3 &= (uint8_t)(~(CurrentBank[2]));
+#if defined(STM8L15X_LD)
+ RI->IOSR4 &= (uint8_t)(~(CurrentBank[3]));
+#endif
+
+ RI->IOCMR1 &= (uint8_t)(~(CurrentBank[0]));
+ RI->IOCMR2 &= (uint8_t)(~(CurrentBank[1]));
+ RI->IOCMR3 &= (uint8_t)(~(CurrentBank[2]));
+#if defined(STM8L15X_LD)
+ RI->IOCMR4 &= (uint8_t)(~(CurrentBank[3]));
+#endif
+
+ //====================
+ // All GPIOs in PP Low
+ //====================
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Output in Low level
+ GPIO_ODR_LOW(p_bank->shield_sampling);
+ GPIO_ODR_LOW(p_bank->shield_channel);
+ // GPIO in Output
+ GPIO_DDR_OUT(p_bank->shield_sampling);
+ GPIO_DDR_OUT(p_bank->shield_channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_bank->shield_sampling);
+ GPIO_CR1_PP(p_bank->shield_channel);
+#endif // TSLPRM_USE_SHIELD
+
+ number_of_channels = p_bank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < number_of_channels;
+ idx_ch++)
+ {
+ // Output in Low level
+ GPIO_ODR_LOW(p_chSrc->sampling);
+ GPIO_ODR_LOW(p_chSrc->channel);
+ // GPIO in Output
+ GPIO_DDR_OUT(p_chSrc->sampling);
+ GPIO_DDR_OUT(p_chSrc->channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_chSrc->sampling);
+ GPIO_CR1_PP(p_chSrc->channel);
+ p_chSrc++;
+ }
+ }
+
+ }
+}
+
+#else // STM8L10X
+
+/**
+ * @brief Start acquisition
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+ CONST TSL_Bank_T *p_bank = &(TSL_Globals.Bank_Array[0]);
+ CONST TSL_ChannelSrc_T *p_chSrc;
+ TSL_tNb_T number_of_channels = 0;
+ TSL_tIndex_T idx_bk;
+ TSL_tIndex_T idx_ch;
+
+ uint8_t old_status = 0;
+
+ ChargeTransferCounter = 0;
+
+#if (TSLPRM_IODEF > 0)
+ //============================
+ // All GPIOs in Input floating
+ //============================
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS; idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // GPIO in floating mode
+ GPIO_CR1_FLOATING(p_bank->shield_sampling);
+ GPIO_CR1_FLOATING(p_bank->shield_channel);
+ // GPIO in Input
+ GPIO_DDR_IN(p_bank->shield_sampling);
+ GPIO_DDR_IN(p_bank->shield_channel);
+#endif
+
+ number_of_channels = p_bank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < number_of_channels;
+ idx_ch++)
+ {
+ // GPIO in floating mode
+ GPIO_CR1_FLOATING(p_chSrc->sampling);
+ GPIO_CR1_FLOATING(p_chSrc->channel);
+ // GPIO in Input
+ GPIO_DDR_IN(p_chSrc->sampling);
+ GPIO_DDR_IN(p_chSrc->channel);
+
+ p_chSrc++;
+ }
+ }
+#endif // TSLPRM_IODEF
+
+ // Test if this bank is not empty
+ if (BankDone != 0)
+ {
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ disableInterrupts();
+#endif //TSLPRM_PROTECT_IO_ACCESS
+
+ /* STEP1 : Discharging all capacitors
+ ==> all IOs in open-drain LOW */
+ GPIOB->ODR &= (uint8_t)(~(CurrentBank[0] | CurrentBank[1]));
+ GPIOB->CR1 &= (uint8_t)(~(CurrentBank[0] | CurrentBank[1]));
+ GPIOB->DDR |= (uint8_t)(CurrentBank[0] | CurrentBank[1]);
+ GPIOD->ODR &= (uint8_t)(~(CurrentBank[2] | CurrentBank[3]));
+ GPIOD->CR1 &= (uint8_t)(~(CurrentBank[2] | CurrentBank[3]));
+ GPIOD->DDR |= (uint8_t)(CurrentBank[2] | CurrentBank[3]);
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ enableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ COMP->CCS &= (uint8_t)(~(CurrentSampling |CurrentChannel));
+
+ /* STEP2: Waiting for complete discharge */
+ SoftDelay(TSLPRM_DELAY_DISCHARGE_ALL);
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ disableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ // Dead Time
+ GPIOB->DDR &= (uint8_t)(~(CurrentBank[0] | CurrentBank[1]));
+ GPIOD->DDR &= (uint8_t)(~(CurrentBank[2] | CurrentBank[3]));
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ enableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ GPIOB->ODR |= (uint8_t)(CurrentBank[0]);
+ GPIOD->ODR |= (uint8_t)(CurrentBank[2]);
+
+ // Loop while all sampling have not reach the VIH level
+ do
+ {
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ disableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ /* STEP3: Charging C-Touch
+ ==> Channels in Push-Pull HIGH
+ ==> Sampling kept open */
+ GPIOB->DDR |= (uint8_t)(CurrentBank[0]);
+ GPIOB->CR1 |= (uint8_t)(CurrentBank[0]);
+ GPIOD->DDR |= (uint8_t)(CurrentBank[2]);
+ GPIOD->CR1 |= (uint8_t)(CurrentBank[2]);
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ enableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ /* STEP4 : Waiting for good chargement */
+ __Delay_Charge();
+
+#if (TSLPRM_USE_SPREAD_SPECTRUM > 0)
+ SwSpreadSpectrum();
+#endif
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ disableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ // Dead Time
+ GPIOB->CR1 &= (uint8_t)(~(CurrentBank[0]));
+ GPIOB->DDR &= (uint8_t)(~(CurrentBank[0]));
+ GPIOD->CR1 &= (uint8_t)(~(CurrentBank[2]));
+ GPIOD->DDR &= (uint8_t)(~(CurrentBank[2]));
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ enableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ /* STEP5: Transfering C-Touch charge in C-Sampling
+ ==> Close IOs Switchs */
+
+ // Close switch sampling
+ COMP->CCS |= (uint8_t)CurrentSampling;
+ COMP->CCS |= (uint8_t)CurrentChannel;
+
+ /* STEP6: Waiting for good transfer */
+ __Delay_Transfer();
+
+ //Dead Time
+ COMP->CCS &= (uint8_t)(~(CurrentChannel | CurrentSampling));
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ disableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ // Get the measurement of counter if the value of Input register change
+ if ((*p_GPIOx_IDR & BankDone) != old_status)
+ {
+ GetCounter(p_GPIOx_IDR, &old_status);
+ }
+
+#ifdef TSLPRM_PROTECT_IO_ACCESS
+ enableInterrupts();
+#endif // TSLPRM_PROTECT_IO_ACCESS
+
+ ChargeTransferCounter++;
+
+ } while ((old_status != BankDone) && (ChargeTransferCounter != (TSL_Params.AcqMax+1)));
+
+ // Get the value of counter if he reach the Max count
+ if(ChargeTransferCounter == (TSL_Params.AcqMax+1))
+ {
+ GetCounter(&BankDone, &old_status);
+ }
+
+ //====================
+ // All GPIOs in PP Low
+ //====================
+ for (idx_bk = 0; idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)
+ {
+ p_bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ p_chSrc = p_bank->p_chSrc;
+
+#if (TSLPRM_USE_SHIELD > 0)
+ // Output in Low level
+ GPIO_ODR_LOW(p_bank->shield_sampling);
+ GPIO_ODR_LOW(p_bank->shield_channel);
+ // GPIO in Output
+ GPIO_DDR_OUT(p_bank->shield_sampling);
+ GPIO_DDR_OUT(p_bank->shield_channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_bank->shield_sampling);
+ GPIO_CR1_PP(p_bank->shield_channel);
+#endif // TSLPRM_USE_SHIELD
+
+ number_of_channels = p_bank->NbChannels;
+
+ for (idx_ch = 0;
+ idx_ch < number_of_channels;
+ idx_ch++)
+ {
+ // Output in Low level
+ GPIO_ODR_LOW(p_chSrc->sampling);
+ GPIO_ODR_LOW(p_chSrc->channel);
+ // GPIO in Output
+ GPIO_DDR_OUT(p_chSrc->sampling);
+ GPIO_DDR_OUT(p_chSrc->channel);
+ // GPIO in PP
+ GPIO_CR1_PP(p_chSrc->sampling);
+ GPIO_CR1_PP(p_chSrc->channel);
+ p_chSrc++;
+ }
+ }
+
+ }
+}
+
+#endif
+
+
+/**
+ * @brief Do the measurement
+ * @param *p_reg Pointer to the Input register
+ * @param *p_old_status Pointer to the previous status value
+ * @retval None
+ */
+
+void GetCounter(__IO uint8_t *p_reg, uint8_t *p_old_status)
+{
+
+ uint8_t new_status = 0;
+ uint8_t idx_i = 0;
+ uint8_t mask_i = 1;
+#if defined(STM8L10X)
+ uint8_t idx_j = 4;
+ uint8_t idx_group = 0;
+#else
+ uint8_t idx_j = 8;
+#endif // defined(STM8L10X)
+
+ new_status = *p_reg;
+ new_status = (uint8_t)(new_status & BankDone & (~(*p_old_status)));
+
+ while ((new_status != 0) && (idx_i < idx_j))
+ {
+ if ((new_status & mask_i) != 0)
+ {
+#if defined(STM8L10X)
+ tab_MeasurementCounter[idx_group]= ChargeTransferCounter;
+#else
+ tab_MeasurementCounter[idx_i] = ChargeTransferCounter;
+#endif // defined(STM8L10X)
+ *p_old_status |= mask_i;
+ new_status &= (uint8_t)(~mask_i);
+ }
+ idx_i++;
+ mask_i <<= 1;
+#if defined(STM8L10X)
+ if (idx_i > 1)
+ {
+ idx_group = 1;
+ }
+#endif // defined(STM8L10X)
+ }
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndex_T index)
+{
+ return(tab_MeasurementCounter[index]);
+}
+
+
+/**
+ * @brief Check noise (not used)
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ return TSL_ACQ_STATUS_OK;
+}
+
+
+/**
+ * @brief Check if a filter must be used on the current channel (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if a filter can be applied
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ return TSL_TRUE;
+}
+
+
+/**
+ * @brief Compute the Delta value
+ * @param[in] ref Reference value
+ * @param[in] meas Last Measurement value
+ * @retval Delta value
+ */
+TSL_tDelta_T TSL_acq_ComputeDelta(TSL_tRef_T ref, TSL_tMeas_T meas)
+{
+ return((TSL_tDelta_T)(ref - meas));
+}
+
+
+/**
+ * @brief Compute the Measurement value
+ * @param[in] ref Reference value
+ * @param[in] delta Delta value
+ * @retval Measurement value
+ */
+TSL_tMeas_T TSL_acq_ComputeMeas(TSL_tRef_T ref, TSL_tDelta_T delta)
+{
+ return((TSL_tMeas_T)(ref - delta));
+}
+
+
+/**
+ * @brief Test if the Reference is incorrect (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @retval Result TRUE if the Reference is out of range
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ return TSL_FALSE;
+}
+
+
+/**
+ * @brief Test if the measure has crossed the reference target (not used)
+ * @param[in] pCh Pointer on the channel data information
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result TRUE if the Reference is valid
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ return TSL_TRUE;
+}
+
+
+#if defined(__ICCSTM8__)
+#pragma optimize=low
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * @retval None
+ */
+void SoftDelay(uint16_t val)
+{
+ uint16_t idx;
+ for (idx = val; idx > 0; idx--)
+ {
+ nop();
+ }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8tl5x.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8tl5x.c
new file mode 100644
index 0000000..9298122
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_acq_stm8tl5x.c
@@ -0,0 +1,906 @@
+/**
+ ******************************************************************************
+ * @file tsl_acq_stm8tl5x.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the PXS acquisition
+ * on STM8TL5x products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_acq_stm8tl5x.h"
+#include "tsl_globals.h"
+#include "stm8tl5x_it.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+
+/* Private defines -----------------------------------------------------------*/
+#define EPCC_INIT_VALUE (0x80)
+#define CS_MIDDLE_VALUE (17)
+#define CS_MAX_VALUE (32)
+#define MAX_MEASURE (0xFFFF)
+
+/* Private macros ------------------------------------------------------------*/
+#define IS_BANK_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_BANKS)))
+#define IS_SOURCE_INDEX_OK(INDEX) (((INDEX) == 0) || (((INDEX) > 0) && ((INDEX) < TSLPRM_TOTAL_CHANNELS)))
+#define IS_EPCC_STATUS_OK(STATUS) ((STATUS & TSL_EPCC_CHANGE_MASK) != 0)
+#define IS_CSSEL_OK(CSSEL) (((CSSEL) == 0) || (((CSSEL) > 0) && ((CSSEL) < CS_MAX_VALUE)))
+
+/* Private variables ---------------------------------------------------------*/
+TSL_BankConfig_T PXS_BankConfig[TSLPRM_TOTAL_BANKS];
+CONST uint8_t PXS_CSsorting[] = {0, 1, 2, 8, 3, 4, 5, 9, 6, 10, 16, 11, 7, 12, 17, 13, 18, 19, 14, 24, 15, 20, 25, 21, 26, 22, 27, 23, 28, 29, 30, 31};
+
+/* Private functions prototype -----------------------------------------------*/
+void TSL_PXS_CS_CalibrateBank(TSL_tIndex_T idx_bk);
+int8_t TSL_PXS_EPCC_CalibrateBank(TSL_tIndex_T bank);
+TSL_Status_enum_T TSL_PXS_EPCC_CalibrateZone(CONST TSL_Zone_T *);
+void SoftDelay(uint16_t val);
+
+/**
+ * @brief Initializes the acquisition module.
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_Init(void)
+{
+
+ TSL_Status_enum_T retval = TSL_STATUS_OK;
+
+ TSL_tIndex_T i;
+ TSL_tIndex_T j;
+ TSL_tIndex_T idx_bk; // Bank index
+ uint16_t TxInUseMask = 0;
+ uint16_t RxInUseMask = 0;
+ CONST TSL_Bank_T *bank;
+ uint8_t *CSArray;
+
+ // Enable the PXS IP clock
+ CLK->PCKENR1 |= CLK_PCKENR1_PXS;
+
+ // Initialization of PXS IP
+ PXS->CKCR1 &= (uint8_t)~PXS_CKCR1_PRESC;
+
+#if (TSLPRM_PXS_HSI == 16000)
+ PXS->CKCR1 |= PXS_CKCR1_16MHZ;
+#elif (TSLPRM_PXS_HSI == 8000)
+ PXS->CKCR1 |= PXS_CKCR1_8MHZ;
+#elif (TSLPRM_PXS_HSI == 4000)
+ PXS->CKCR1 |= PXS_CKCR1_4MHZ;
+#elif (TSLPRM_PXS_HSI == 2000)
+ PXS->CKCR1 |= PXS_CKCR1_2MHZ;
+#elif (TSLPRM_PXS_HSI == 1000)
+ PXS->CKCR1 |= PXS_CKCR1_1MHZ;
+#elif (TSLPRM_PXS_HSI == 500)
+ PXS->CKCR1 |= PXS_CKCR1_500KHZ;
+#elif (TSLPRM_PXS_HSI == 250)
+ PXS->CKCR1 |= PXS_CKCR1_250KHZ;
+#elif (TSLPRM_PXS_HSI == 125)
+ PXS->CKCR1 |= PXS_CKCR1_125KHZ;
+#else
+ PXS->CKCR1 |= PXS_CKCR1_16MHZ; // Default
+#endif
+
+ PXS->CKCR2 = (uint8_t)(((uint8_t)TSLPRM_PXS_UP_LENGTH & 0x07) << 4) | ((uint8_t)TSLPRM_PXS_PASS_LENGTH & 0x07);
+
+#if TSLPRM_PXS_RF_DETECTION > 0
+ enablePXSNoiseDetection();
+#endif
+
+ setPXSStab(TSLPRM_PXS_STAB);
+ setPXSBias(TSLPRM_PXS_BIAS);
+
+ // Initialization of the GPIO shared with the used TX
+ for (i = 0; i < TSLPRM_TOTAL_BANKS; i++)
+ {
+ bank = &(TSL_Globals.Bank_Array[i]);
+ CSArray = PXS_BankConfig[i].CSSEL;
+ TxInUseMask |= bank->msk_TX;
+ // Set the mask with the receivers use as receiver or as transmitter
+ RxInUseMask |= bank->msk_RXEN;
+ // Set the CS to 0
+ for (j = 0; j <= TSLPRM_HIGH_CHANNEL_NB; j++)
+ {
+ *CSArray = 0;
+ CSArray++;
+ }
+ }
+
+ GPIOD->ODR &= (uint8_t)(~(TxInUseMask & 0x00FF));
+ // Set the port as output
+ GPIOD->DDR |= (uint8_t)(TxInUseMask & 0x00FF);
+ // Configure the port as open-drain
+ GPIOD->CR1 &= (uint8_t)(~(TxInUseMask & 0x00FF));
+#if TSLPRM_PXS_INACTIVE_TX > 0
+ // Configure as floating
+ GPIOD->ODR |= (uint8_t)(TxInUseMask & 0x00FF);
+#else
+ // Drive them to VSS
+ GPIOD->ODR &= (uint8_t)(~(TxInUseMask & 0x00FF));
+#endif
+ GPIOB->ODR &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));
+ // Set the port as output
+ GPIOB->DDR |= (uint8_t)((TxInUseMask & 0xFF00) >> 8);
+ // Configure the port as open-drain
+ GPIOB->CR1 &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));
+#if TSLPRM_PXS_INACTIVE_TX > 0
+ // Configure as floating
+ GPIOB->ODR |= (uint8_t)((TxInUseMask & 0xFF00) >> 8);
+#else
+ // Drive it to VSS
+ GPIOB->ODR &= (uint8_t)(~((TxInUseMask & 0xFF00) >> 8));
+#endif
+
+ enablePXS();
+
+#if TSLPRM_PXS_INACTIVE_RX > 0
+ PXS->RXINSR = 0x3FF;
+#else
+ PXS->RXINSR = 0x0000;
+#endif
+
+#if TSLPRM_PXS_RX_COUPLING > 0
+ enablePXSCoupling();
+#else
+ disablePXSCoupling()
+#endif
+
+#if TSLPRM_PXS_SYNCHRONIZE > 0
+ enablePXSSync();
+#if TSLPRM_PXS_SYNCHRO_EDGE > 0
+ selectPXSSyncRisingEdge();
+#else
+ selectPXSSyncFallingEdge();
+#endif
+#else
+ disablePXSSync();
+#endif
+
+#if TSLPRM_USE_ACQ_INTERRUPT > 0
+ enablePXSInterrupts(PXS_CR2_EOCITEN);
+#endif
+ // Configure the acquisition mode
+ PXS->RXCR3 = (uint16_t)RxInUseMask;
+ PXS->RXCR2 = (uint16_t)RxInUseMask;
+
+#if TSLPRM_ACQ_MAX > 0
+ PXS->MAXR = TSLPRM_ACQ_MAX;
+ PXS->MAXENR = 0x03FF;
+#else
+ PXS->MAXENR = 0;
+#endif
+
+ // Calibrate the CS for all banks
+ for (idx_bk = 0;idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)
+ {
+ TSL_PXS_CS_CalibrateBank(idx_bk);
+ }
+
+
+ // Calibrate the EPCC for all banks
+ for (idx_bk = 0;idx_bk < TSLPRM_TOTAL_BANKS;idx_bk++)
+ {
+ if (TSL_PXS_EPCC_CalibrateBank(idx_bk) > 0)
+ {
+ retval = TSL_STATUS_ERROR;
+ }
+ }
+#if TSLPRM_PXS_LOW_POWER_MODE > 0
+ setPXSLowPower();
+#else
+ resetPXSLowPower();
+#endif
+
+ return retval;
+
+}
+
+/**
+ * @brief Calibrate the CS for a selected acquisition bank
+ * @param[in] idx_bk Index of the bank
+ * @retval Number of Receivers not correctly calibrated
+ */
+void TSL_PXS_CS_CalibrateBank(TSL_tIndex_T idx_bk)
+{
+ TSL_tIndex_T idx_ch;
+ uint8_t currentCS = 24;
+ uint8_t CS_delta = 4; // Value to add/substract to/from the current CS
+ CONST TSL_Bank_T *bank;
+ CONST uint16_t targetCount = TSLPRM_KEY_TARGET_REFERENCE / TSLPRM_KEY_TARGET_ATTENUATION;
+ CONST uint16_t targetCountError = targetCount >> 3;
+ bool CalibrationDone = FALSE;
+ uint16_t measSup[TSLPRM_HIGH_CHANNEL_NB+1];
+ uint16_t measInf[TSLPRM_HIGH_CHANNEL_NB+1];
+ uint8_t CSsup[TSLPRM_HIGH_CHANNEL_NB+1];
+ uint8_t CSinf[TSLPRM_HIGH_CHANNEL_NB+1];
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+#if TSLPRM_USE_ACQ_INTERRUPT == 0
+ enablePXSInterrupts(PXS_CR2_EOCITEN);
+#endif
+
+ bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ resetPXSLowPower();
+ TSL_acq_BankConfig(idx_bk);
+
+ PXS->MAXR = TSLPRM_KEY_TARGET_REFERENCE;
+
+ WFE->CR1 |= WFE_CR1_PXS_EV;
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ PXS->RXEPCCSELR[idx_ch] = 0;
+ PXS->RXCSSELR[idx_ch] = currentCS;
+ CSsup[idx_ch] = 0;
+ CSinf[idx_ch] = 0;
+ measInf[idx_ch] = 0;
+ measSup[idx_ch] = 0xFFFF;
+
+ }
+ do
+ {
+ startPXSAcquisition();
+ wfe();
+ clearPXS_ISR_EOCF;
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
+ {
+ if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > targetCount - targetCountError))
+ {
+ PXS->RXCSSELR[idx_ch] -= 8;
+ }
+ }
+ }
+ currentCS -= 8;
+ }
+ while (currentCS);
+
+
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ PXS->RXCSSELR[idx_ch] += CS_delta;
+ }
+
+ do
+ {
+ CS_delta >>= 1;
+ if ((CS_delta == 0) && (CalibrationDone == FALSE))
+ {
+ CalibrationDone = TRUE;
+ CS_delta = 1;
+ }
+
+ startPXSAcquisition();
+ wfe();
+ clearPXS_ISR_EOCF;
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
+ {
+ if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > targetCount))
+ {
+ measSup[idx_ch] = PXS->RXCNTR[idx_ch];
+ CSsup[idx_ch] = PXS->RXCSSELR[idx_ch];
+ PXS->RXCSSELR[idx_ch] -= CS_delta;
+ }
+ else //if (PXS->RXCNTR[idx_ch] < targetCount )
+ {
+ measInf[idx_ch] = PXS->RXCNTR[idx_ch];
+ CSinf[idx_ch] = PXS->RXCSSELR[idx_ch];
+ PXS->RXCSSELR[idx_ch] += CS_delta;
+ }
+// else
+// {
+ // Do nothing (MISRA requirement)
+// }
+ }
+ }
+ }
+ while ((CalibrationDone == FALSE) || (CS_delta != 0));
+
+
+ // Restore configuration
+#if TSLPRM_ACQ_MAX > 0
+ PXS->MAXR = TSLPRM_ACQ_MAX;
+#else
+ PXS->MAXENR = 0;
+#endif
+
+ WFE->CR1 &= (uint8_t)~WFE_CR1_PXS_EV;
+#if TSLPRM_USE_ACQ_INTERRUPT == 0
+ disablePXSInterrupts(PXS_CR2_EOCITEN);
+#endif
+
+ // Store the CS
+ for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
+ {
+ if ((measSup[idx_ch] == 0) || ((measSup[idx_ch] - targetCount) > (targetCount - measInf[idx_ch])))
+ {
+ PXS_BankConfig[idx_bk].CSSEL[idx_ch] = CSinf[idx_ch];
+ }
+ else
+ {
+ PXS_BankConfig[idx_bk].CSSEL[idx_ch] = CSsup[idx_ch];
+ }
+ }
+}
+
+
+/**
+ * @brief Calibrate the EPCC for a selected acquisition bank
+ * @param[in] idx_bk Index of the bank
+ * @retval Number Number of Receivers not correctly calibrated
+ */
+int8_t TSL_PXS_EPCC_CalibrateBank(TSL_tIndex_T idx_bk)
+{
+ TSL_tIndex_T idx_ch;
+ uint8_t currentEPCC, trial, goodEPCC = 0;
+ uint8_t EPCCtoCompute = 0; // Used to define if all the EPCC have their final value
+ uint8_t EPCC_delta = EPCC_INIT_VALUE; // Value to add/substract to/from the current EPCC
+ CONST TSL_Bank_T *bank;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+#if TSLPRM_USE_ACQ_INTERRUPT == 0
+ enablePXSInterrupts(PXS_CR2_EOCITEN);
+#endif
+
+ bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ resetPXSLowPower();
+ TSL_acq_BankConfig(idx_bk);
+
+ PXS->MAXR = 2 * TSLPRM_KEY_TARGET_REFERENCE;
+
+ WFE->CR1 |= WFE_CR1_PXS_EV;
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ PXS->RXEPCCSELR[idx_ch] = EPCC_delta;
+ if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
+ {
+ EPCCtoCompute++;
+ }
+ }
+ do
+ {
+ EPCC_delta >>= 1;
+ startPXSAcquisition();
+ wfe();
+ clearPXS_ISR_EOCF;
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
+ {
+ if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > TSLPRM_KEY_TARGET_REFERENCE))
+ {
+ PXS->RXEPCCSELR[idx_ch] -= EPCC_delta;
+ }
+ else if (PXS->RXCNTR[idx_ch] < TSLPRM_KEY_TARGET_REFERENCE)
+ {
+ PXS->RXEPCCSELR[idx_ch] += EPCC_delta;
+ }
+ else
+ {
+ // Do nothing (MISRA requirement)
+ }
+ }
+ }
+ }
+ while (EPCC_delta >= 1);
+ // Second pass to fine-tune
+ trial = TSLPRM_PXS_EPCC_FINE_TUNING_ITERATION;
+ do
+ {
+ startPXSAcquisition();
+ goodEPCC = 0; // Reset the goodEPCC variable
+ wfe();
+ clearPXS_ISR_EOCF;
+ for (idx_ch = 0; idx_ch <= TSLPRM_HIGH_CHANNEL_NB; idx_ch++)
+ {
+ if (bank->msk_channels & (uint16_t)((uint16_t)1 << idx_ch))
+ {
+ currentEPCC = PXS->RXEPCCSELR[idx_ch]; //this affectation allow to avoid computation of the structure address
+ if (!(PXS->RXSR & (uint16_t)((uint16_t)1 << idx_ch)) || (PXS->RXCNTR[idx_ch] > (TSLPRM_KEY_TARGET_REFERENCE + TSLPRM_KEY_TARGET_REFERENCE_ERROR)))
+ {
+ if (currentEPCC > 0)
+ {
+ if ((currentEPCC & 0x07) != 0)
+ {
+ currentEPCC--;
+ }
+ else
+ {
+ currentEPCC -= 3; // This is due to the non linearity of the EPCC
+ }
+ }
+ }
+ else if (PXS->RXCNTR[idx_ch] < (TSLPRM_KEY_TARGET_REFERENCE - TSLPRM_KEY_TARGET_REFERENCE_ERROR))
+ {
+ if (currentEPCC < 0xFF)
+ {
+ if ((currentEPCC & 0x07) != 0x07)
+ {
+ currentEPCC++;
+ }
+ else
+ {
+ currentEPCC += 2; // This is due to the non linearity of the EPCC
+ }
+ }
+ else // Invert the change in case the sorting is not reliable
+ {
+ currentEPCC--;
+ }
+ }
+ else
+ {
+ goodEPCC++;
+ }
+ PXS->RXEPCCSELR[idx_ch] = currentEPCC;
+ }
+ }
+ trial--;
+ }
+ while ((goodEPCC < EPCCtoCompute) && (trial));
+
+ // Restore configuration
+#if TSLPRM_ACQ_MAX > 0
+ PXS->MAXR = TSLPRM_ACQ_MAX;
+#else
+ PXS->MAXENR = 0;
+#endif
+
+ WFE->CR1 &= (uint8_t)~WFE_CR1_PXS_EV;
+#if TSLPRM_USE_ACQ_INTERRUPT == 0
+ disablePXSInterrupts(PXS_CR2_EOCITEN);
+#endif
+
+ // Store the EPCC
+ for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
+ {
+ PXS_BankConfig[idx_bk].EPCCSEL[idx_ch] = PXS->RXEPCCSELR[idx_ch];
+ }
+
+ return((int8_t)(EPCCtoCompute - goodEPCC));
+}
+
+
+#if TSLPRM_USE_ZONE > 0
+/**
+ * @brief Calibrate the EPCC for a set of acquisition banks.
+ * @param[in] zone Set of banks to calibrate the EPCC
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_PXS_EPCC_CalibrateZone(CONST TSL_Zone_T *zone)
+{
+ uint16_t idx_bk;
+ TSL_Status_enum_T retval = TSL_STATUS_OK;
+ for (idx_bk = 0; idx_bk < zone->NbBanks; idx_bk++)
+ {
+ if (TSL_PXS_EPCC_CalibrateBank(zone->BankIndex[idx_bk]) > 0)
+ {
+ retval = TSL_STATUS_ERROR;
+ }
+ }
+ return(retval);
+}
+#endif
+
+
+/**
+ * @brief Test the reference and update the EPCC/CS if needed
+ * @param[in] pCh pointer on the channel data information
+ * @retval Result
+ */
+TSL_Bool_enum_T TSL_acq_TestReferenceOutOfRange(TSL_ChannelData_T *pCh)
+{
+ uint16_t reference, target_error = 0;
+ TSL_Bool_enum_T result = TSL_FALSE;
+
+ if (pCh->Flags.EPCCStatus != TSL_EPCC_STATUS_LOCKED)
+ {
+ reference = pCh->Ref;
+#if TSLPRM_TOTAL_TKEYS > 0
+ if (TSL_Globals.This_Obj->Type & TSL_OBJ_TYPE_TKEY_MASK)
+ {
+ target_error = TSLPRM_TOUCHKEY_REFERENCE_RANGE;
+ }
+#endif
+
+#if TSLPRM_TOTAL_LNRTS > 0
+ if (TSL_Globals.This_Obj->Type & TSL_OBJ_TYPE_LINROT_MASK)
+ {
+ target_error = TSLPRM_LINROT_REFERENCE_RANGE;
+ }
+#endif
+ if ((reference != 0) && ((reference > (TSLPRM_KEY_TARGET_REFERENCE + target_error)) || (reference < (TSLPRM_KEY_TARGET_REFERENCE - target_error))))
+ {
+ if (reference < (TSLPRM_KEY_TARGET_REFERENCE - target_error))
+ {
+ pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_INCREASE;
+ }
+ else if (reference > (TSLPRM_KEY_TARGET_REFERENCE + target_error))
+ {
+ pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_DECREASE;
+ }
+ else
+ {
+ // Do nothing (MISRA requirement)
+ }
+ result = TSL_TRUE;
+ }
+ }
+ return(result);
+}
+
+/**
+ * @brief Test if the measure has crossed the reference target
+ * @param[in] pCh Pointer to the channel Data under test
+ * @param[in] new_meas Measure of the last acquisition on this channel
+ * @retval Result Result of the test
+ */
+TSL_Bool_enum_T TSL_acq_TestFirstReferenceIsValid(TSL_ChannelData_T *pCh, TSL_tMeas_T new_meas)
+{
+ TSL_Bool_enum_T result = TSL_TRUE;
+ TSL_EPCCStatus_enum_T EPCCStatus;
+
+ EPCCStatus = pCh->Flags.EPCCStatus;
+ if (EPCCStatus & TSL_EPCC_CHANGE_MASK)
+ {
+ // If the previous reference and the new one are on each side of the reference target
+ // the EPCC is no more tested and the calibration continues.
+ if (((EPCCStatus == TSL_EPCC_STATUS_INCREASE) && (new_meas >= TSLPRM_KEY_TARGET_REFERENCE))
+ || ((EPCCStatus == TSL_EPCC_STATUS_DECREASE) && (new_meas <= TSLPRM_KEY_TARGET_REFERENCE)))
+ {
+ pCh->Flags.EPCCStatus = TSL_EPCC_STATUS_UNLOCKED;
+ }
+ else
+ {
+ result = TSL_FALSE;
+ }
+ }
+
+ return(result);
+}
+
+
+/**
+ * @brief Increase or decrease the CS value
+ * @param[in] pCSSEL Address of the CS to be modified
+ * @param[in] change Define if the Cs must be increased or decreased
+ * @retval None
+ */
+void TSL_acq_UpdateCS(uint8_t *pCSSEL, TSL_EPCCStatus_enum_T change)
+{
+ uint16_t indexCS;
+
+ assert_param(IS_EPCC_STATUS_OK(change));
+ assert_param(IS_CSSEL_OK(*pCSSEL));
+
+ if (*pCSSEL > CS_MIDDLE_VALUE)
+ {
+ indexCS = (CS_MIDDLE_VALUE - 1);
+ }
+ else
+ {
+ indexCS = 0;
+ }
+ while ((PXS_CSsorting[indexCS] != *pCSSEL) && (indexCS < CS_MAX_VALUE))
+ {
+ indexCS++;
+ }
+ if (change == TSL_EPCC_STATUS_INCREASE)
+ {
+ *pCSSEL = PXS_CSsorting[indexCS + 1];
+ }
+ else
+ {
+ *pCSSEL = PXS_CSsorting[indexCS - 1];
+ }
+}
+
+
+/**
+ * @brief Configures a Bank.
+ * @param[in] idx_bk Index of the Bank to configure
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankConfig(TSL_tIndex_T idx_bk)
+{
+ TSL_Status_enum_T retval = TSL_STATUS_OK;
+ uint16_t idx_ch;
+ TSL_ChannelFlags_T flags;
+ CONST TSL_Bank_T *bank = &(TSL_Globals.Bank_Array[idx_bk]);
+ CONST TSL_ChannelSrc_T *pchSrc = bank->p_chSrc;
+ CONST TSL_ChannelDest_T *pchDest = bank->p_chDest;
+ TSL_tMaskRX enabledRX = 0;
+ uint8_t *pEPCCSEL, *pCSSEL;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_BANK_INDEX_OK(idx_bk));
+
+ TSL_Globals.This_Bank = idx_bk;
+
+ selectPXSRxGroup(bank->msk_group);
+ for (idx_ch = 0;idx_ch < bank->NbChannels;idx_ch++)
+ {
+ flags = bank->p_chData[pchDest->IdxDest].Flags;
+ if (flags.ObjStatus == TSL_OBJ_STATUS_ON)
+ {
+ enabledRX |= (1 << pchSrc->IdxSrc);
+ if (flags.EPCCStatus & TSL_EPCC_CHANGE_MASK)
+ {
+ pEPCCSEL = &PXS_BankConfig[idx_bk].EPCCSEL[pchSrc->IdxSrc];
+ if (flags.EPCCStatus == TSL_EPCC_STATUS_INCREASE)
+ {
+ if ((*pEPCCSEL) < 0xFF)
+ {
+ if (((*pEPCCSEL) & 0x07) != 0x07)
+ {
+ (*pEPCCSEL)++;
+ }
+ else
+ {
+ if ((*pEPCCSEL) < 0xFE)
+ {
+ (*pEPCCSEL) += 2; // This is due to the non linearity of the PCC
+ }
+ else
+ {
+ (*pEPCCSEL)++;
+ }
+ }
+
+ }
+ else
+ {
+ pCSSEL = &PXS_BankConfig[idx_bk].CSSEL[pchSrc->IdxSrc];
+ if (*pCSSEL < 0x1F)
+ {
+ TSL_acq_UpdateCS(pCSSEL, TSL_EPCC_STATUS_INCREASE);
+ }
+ else
+ {}
+ }
+ }
+ else
+ {
+ if ((*pEPCCSEL) > 0)
+ {
+ if (((*pEPCCSEL) & 0x07) != 0)
+ {
+ (*pEPCCSEL)--;
+ }
+ else
+ {
+ if ((*pEPCCSEL) > 3)
+ {
+ (*pEPCCSEL) -= 3; // This is due to the non linearity of the PCC
+ }
+ else
+ {
+ (*pEPCCSEL)--;
+ }
+ }
+ }
+ else
+ {
+ pCSSEL = &PXS_BankConfig[idx_bk].CSSEL[pchSrc->IdxSrc];
+ if (*pCSSEL > 0)
+ {
+ TSL_acq_UpdateCS(pCSSEL, TSL_EPCC_STATUS_DECREASE);
+ }
+ else
+ {}
+ }
+ }
+ }
+ }
+
+ // Next channel
+ pchSrc++;
+ pchDest++;
+ }
+
+ // The two following loops are more efficient than the two instructions in the same loop
+ for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
+ {
+ PXS->RXCSSELR[idx_ch] = PXS_BankConfig[idx_bk].CSSEL[idx_ch];
+ }
+ for (idx_ch = 0;idx_ch <= TSLPRM_HIGH_CHANNEL_NB;idx_ch++)
+ {
+ PXS->RXEPCCSELR[idx_ch] = PXS_BankConfig[idx_bk].EPCCSEL[idx_ch];
+ }
+
+ PXS->TXENR = bank->msk_TX; // Enable the Tx selected (if any)
+ PXS->RXCR1 = bank->msk_channels; // Configure the Rx and the Tx function modes
+
+ // Enable the Rx which are not disabled including the potential Rx configured as Tx
+ PXS->RXENR = bank->msk_RXEN & ((uint16_t)(~bank->msk_channels) | enabledRX);
+
+ if (enabledRX == 0)
+ {
+ retval = TSL_STATUS_ERROR;
+ }
+
+ return(retval);
+
+}
+
+
+/**
+ * @brief Test if EPCC are changing
+ * @param[in] pCh Channel to be processed
+ * @retval bool Test result
+ */
+TSL_Bool_enum_T TSL_acq_UseFilter(TSL_ChannelData_T *pCh)
+{
+ if (pCh->Flags.EPCCStatus & TSL_EPCC_CHANGE_MASK)
+ {
+ return (TSL_FALSE);
+ }
+ else
+ {
+ return(TSL_TRUE);
+ }
+}
+
+
+/**
+ * @brief Start acquisition on a previously configured bank
+ * @param None
+ * @retval None
+ */
+void TSL_acq_BankStartAcq(void)
+{
+ // Start acquisition
+ startPXSAcquisition();
+}
+
+
+/**
+ * @brief Wait end of acquisition
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_acq_BankWaitEOC(void)
+{
+ TSL_Status_enum_T retval = TSL_STATUS_BUSY;
+
+ if (checkPXSInterruptStatusFlag(PXS_ISR_EOCF)) // Check EOC flag
+ {
+ if (PXS->RXSR != TSL_Globals.Bank_Array[TSL_Globals.This_Bank].msk_channels) // Check MCE flag
+ {
+ retval = TSL_STATUS_ERROR;
+ }
+ else
+ {
+ retval = TSL_STATUS_OK;
+ }
+ }
+
+ return retval;
+}
+
+
+/**
+ * @brief Check noise detection
+ * @param None
+ * @retval Status
+ */
+TSL_AcqStatus_enum_T TSL_acq_CheckNoise(void)
+{
+ TSL_AcqStatus_enum_T retval = TSL_ACQ_STATUS_OK;
+#if TSLPRM_PXS_RF_DETECTION > 0
+ if (checkPXSInterruptStatusFlag(PXS_ISR_NOISEDETF) == PXS_ISR_NOISEDETF)
+ {
+ retval = TSL_ACQ_STATUS_NOISE;
+ }
+#endif
+ return(retval);
+}
+
+
+/**
+ * @brief Return the current measure
+ * @param[in] index Index of the measure source
+ * @retval Measure
+ */
+TSL_tMeas_T TSL_acq_GetMeas(TSL_tIndexSrc_T index)
+{
+ uint16_t CurrentReceiver;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_SOURCE_INDEX_OK(index));
+
+ CurrentReceiver = (uint16_t)(((uint16_t)1) << index);
+
+ if (PXS->RXSR & CurrentReceiver)
+ {
+ return(PXS->RXCNTR[index]);
+ }
+ else
+ {
+ return(MAX_MEASURE);
+ }
+}
+
+
+/**
+ * @brief Process the PXS Interrupt routine
+ * @param None
+ * @retval None
+ */
+INTERRUPT_HANDLER(TSL_acq_ProcessIT, 2)
+{
+ clearPXS_ISR_EOCF;
+
+ TSL_acq_BankGetResult(TSL_Globals.This_Bank, 0, 0); // No noise filter
+
+#if TSLPRM_USE_ZONE > 0
+ if ((TSL_Globals.This_Zone == 0) || (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks))
+ {
+ CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing
+ PXS->RXENR = 0; // To reduce consumption
+ PXS->TXENR = 0; // To reduce consumption
+ TSL_Globals.This_Bank = 0;
+ }
+ else
+ {
+ if (TSL_acq_ZoneConfig(TSL_Globals.This_Zone, TSL_Globals.Index_In_This_Zone) != TSL_STATUS_ERROR)
+ {
+ // Start Bank acquisition
+ TSL_acq_BankStartAcq();
+#if TSLPRM_PXS_LOW_POWER_MODE > 0
+ if (TSL_Globals.Index_In_This_Zone >= TSL_Globals.This_Zone->NbBanks)
+ {
+ setPXSLowPower();
+ }
+#endif
+ }
+
+ }
+#else
+ CFG->GCR &= (uint8_t)(~CFG_GCR_AL); // Reset Activation level to resume main processing
+ PXS->RXENR = 0; // To reduce consumption
+ PXS->TXENR = 0; // To reduce consumption
+#endif
+}
+
+
+#if defined(__ICCSTM8__)
+#pragma optimize=low
+#endif
+/**
+ * @brief Software delay (private routine)
+ * @param val Wait delay
+ * @retval None
+ */
+void SoftDelay(uint16_t val)
+{
+ __IO uint16_t idx;
+ for (idx = val; idx > 0; idx--)
+ {
+ nop();
+ }
+}
+
+/******************* (C) COPYRIGHT 2014 STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_dxs.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_dxs.c
new file mode 100644
index 0000000..c721b80
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_dxs.c
@@ -0,0 +1,181 @@
+/**
+ ******************************************************************************
+ * @file tsl_dxs.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the
+ * Detection Exclusion System (DxS) algorithm.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_dxs.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+#define THIS_OBJ_TYPE TSL_Globals.This_Obj->Type
+
+#define THIS_TKEY TSL_Globals.This_TKey
+#define THIS_TKEY_STATEID TSL_Globals.This_TKey->p_Data->StateId
+#define THIS_TKEY_DXSLOCK TSL_Globals.This_TKey->p_Data->DxSLock
+#define THIS_TKEY_CHANGE TSL_Globals.This_TKey->p_Data->Change
+
+#define THIS_LINROT TSL_Globals.This_LinRot
+#define THIS_LINROT_STATEID TSL_Globals.This_LinRot->p_Data->StateId
+#define THIS_LINROT_DXSLOCK TSL_Globals.This_LinRot->p_Data->DxSLock
+#define THIS_LINROT_CHANGE TSL_Globals.This_LinRot->p_Data->Change
+
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Detection Exclusion System on the first object in detect state
+ * @param[in] objgrp Pointer to the objects group to process
+ * @retval None
+ */
+void TSL_dxs_FirstObj(CONST TSL_ObjectGroup_T *objgrp)
+{
+#if TSLPRM_USE_DXS > 0
+
+ TSL_tIndex_T idx_obj;
+ CONST TSL_Object_T *pobj;
+ CONST TSL_Object_T *pobj_candidate = 0; // Candidate object for being in Detect state + DxSLock flag
+ TSL_tIndex_T obj_locked = 0; // Object with Lock flag
+
+ // Exit if no object are in DETECT state.
+ if ((objgrp->StateMask & TSL_STATE_DETECT_BIT_MASK) == 0)
+ {
+ return;
+ }
+
+ pobj = objgrp->p_Obj; // First object in the group
+
+ // Process all objects
+ for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
+ {
+
+ // Assign global object
+ TSL_obj_SetGlobalObj(pobj);
+
+ //--------------------------------------------------------------------------
+#if TSLPRM_TOTAL_TKEYS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEY) || (THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEYB))
+ {
+ if (THIS_TKEY_STATEID == TSL_STATEID_DETECT)
+ {
+ if (THIS_TKEY_DXSLOCK == TSL_TRUE)
+ {
+ if (!obj_locked)
+ {
+ obj_locked = 1;
+ pobj_candidate = 0;
+ }
+ else
+ {
+ THIS_TKEY_STATEID = TSL_STATEID_TOUCH;
+ THIS_TKEY_CHANGE = TSL_STATE_CHANGED;
+ }
+ }
+ else
+ {
+ THIS_TKEY_STATEID = TSL_STATEID_TOUCH;
+ THIS_TKEY_CHANGE = TSL_STATE_CHANGED;
+ if ((!pobj_candidate) && (!obj_locked))
+ {
+ pobj_candidate = pobj;
+ }
+ }
+ }
+ }
+#endif // TSLPRM_TOTAL_TKEYS > 0
+
+ //--------------------------------------------------------------------------
+#if TSLPRM_TOTAL_LNRTS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB) ||
+ (THIS_OBJ_TYPE == TSL_OBJ_ROTARY) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARYB))
+ {
+ if (THIS_LINROT_STATEID == TSL_STATEID_DETECT)
+ {
+ if (THIS_LINROT_DXSLOCK == TSL_TRUE)
+ {
+ if (!obj_locked)
+ {
+ obj_locked = 1;
+ pobj_candidate = 0;
+ }
+ else
+ {
+ THIS_LINROT_STATEID = TSL_STATEID_TOUCH;
+ THIS_LINROT_CHANGE = TSL_STATE_CHANGED;
+ }
+ }
+ else
+ {
+ THIS_LINROT_STATEID = TSL_STATEID_TOUCH;
+ THIS_LINROT_CHANGE = TSL_STATE_CHANGED;
+ if ((!pobj_candidate) && (!obj_locked))
+ {
+ pobj_candidate = pobj;
+ }
+ }
+ }
+ }
+#endif // TSLPRM_TOTAL_LNRTS > 0
+
+ pobj++; // Next object
+
+ } // // for all objects
+
+ // Change state from TOUCH to DETECT + DxSLock flag on the candidate object only
+ if (pobj_candidate)
+ {
+
+ // Assign global object
+ TSL_obj_SetGlobalObj(pobj_candidate);
+
+#if TSLPRM_TOTAL_TKEYS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEY) || (THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEYB))
+ {
+ THIS_TKEY_STATEID = TSL_STATEID_DETECT;
+ THIS_TKEY_CHANGE = TSL_STATE_CHANGED;
+ THIS_TKEY_DXSLOCK = TSL_TRUE;
+ }
+#endif // TSLPRM_TOTAL_TKEYS > 0
+
+#if TSLPRM_TOTAL_LNRTS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB) ||
+ (THIS_OBJ_TYPE == TSL_OBJ_ROTARY) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARYB))
+ {
+ THIS_LINROT_STATEID = TSL_STATEID_DETECT;
+ THIS_LINROT_CHANGE = TSL_STATE_CHANGED;
+ THIS_LINROT_DXSLOCK = TSL_TRUE;
+ }
+#endif // TSLPRM_TOTAL_LNRTS > 0
+
+ }
+
+#endif // TSLPRM_USE_DXS > 0
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_ecs.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_ecs.c
new file mode 100644
index 0000000..ae5e50a
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_ecs.c
@@ -0,0 +1,331 @@
+/**
+ ******************************************************************************
+ * @file tsl_ecs.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the ECS.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_ecs.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+#define THIS_OBJ_TYPE TSL_Globals.This_Obj->Type
+#define THIS_TKEY_REF TSL_Globals.This_TKey->p_ChD->Ref
+#define THIS_TKEY_REFREST TSL_Globals.This_TKey->p_ChD->RefRest
+#define THIS_TKEY_DELTA TSL_Globals.This_TKey->p_ChD->Delta
+#define THIS_TKEY_STATEID TSL_Globals.This_TKey->p_Data->StateId
+
+#define THIS_LINROT_STATEID TSL_Globals.This_LinRot->p_Data->StateId
+#define THIS_LINROT_NB_CHANNELS TSL_Globals.This_LinRot->NbChannels
+
+/* Private macros ------------------------------------------------------------*/
+#define IS_K_COEFF_OK(COEFF) (((COEFF) == 0) || (((COEFF) > 0) && ((COEFF) < 256)))
+#define IS_POINTER_INITIALIZED(POINTER) ((POINTER) != 0)
+
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Calculate the K coefficient
+ * @param[in] objgrp Pointer to the objects group to process
+ * @param[in] k_slow K coefficient when objects have different delta variation
+ * @param[in] k_fast K coefficient when objects have the same delta variation
+ * @retval K coefficient (slow or fast)
+ */
+TSL_tKCoeff_T TSL_ecs_CalcK(TSL_ObjectGroup_T *objgrp, TSL_tKCoeff_T k_slow, TSL_tKCoeff_T k_fast)
+{
+ TSL_tIndex_T idx_obj; // Index of current object
+ TSL_tIndex_T idx_ch; // Index of current channel
+ TSL_tDelta_T ldelta = 0; // Temporary delta
+ TSL_tDelta_T ECS_Fast_Enable = 1;
+ TSL_tDelta_T ECS_Fast_Direction = 0;
+ CONST TSL_Object_T *pobj;
+ TSL_tKCoeff_T retval = k_slow;
+ TSL_tNb_T nb_channels = 0; // Number of channels inside current object
+ TSL_ChannelData_T *p_Ch = 0;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_K_COEFF_OK(k_slow));
+ assert_param(IS_K_COEFF_OK(k_fast));
+
+ pobj = objgrp->p_Obj; // First object in the group
+
+ // Process all objects
+ for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
+ {
+
+ // Assign global object
+ TSL_obj_SetGlobalObj(pobj);
+
+#if TSLPRM_TOTAL_TKEYS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEY) || (THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEYB))
+ {
+ // Ignore object if not in Release state (OFF or Error in this case)
+ if (THIS_TKEY_STATEID != TSL_STATEID_RELEASE)
+ {
+ pobj++; // Next object
+ continue; // Stop processing of current object
+ }
+ nb_channels = 1;
+ p_Ch = TSL_Globals.This_TKey->p_ChD;
+ }
+#endif
+
+#if TSLPRM_TOTAL_LNRTS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB) ||
+ (THIS_OBJ_TYPE == TSL_OBJ_ROTARY) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARYB))
+ {
+ // Ignore object if not in Release state (OFF or Error in this case)
+ if (THIS_LINROT_STATEID != TSL_STATEID_RELEASE)
+ {
+ pobj++; // Next object
+ continue; // Stop processing of current object
+ }
+ nb_channels = THIS_LINROT_NB_CHANNELS;
+ p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ }
+#endif
+
+ // Check channel pointer variable (if USE_FULL_ASSERT is defined)
+ assert_param(IS_POINTER_INITIALIZED(p_Ch));
+
+ // Check all channels of current object
+ for (idx_ch = 0; idx_ch < nb_channels; idx_ch++)
+ {
+
+ ldelta = p_Ch->Delta;
+
+ // Check delta
+ if (ldelta == 0) // No Fast ECS !
+ {
+ ECS_Fast_Enable = 0;
+ }
+ else
+ {
+ if (ldelta < 0)
+ {
+ if (ECS_Fast_Direction > 0) // No Fast ECS !
+ {
+ ECS_Fast_Enable = 0;
+ }
+ else
+ {
+ ECS_Fast_Direction = -1;
+ }
+ }
+ else
+ {
+ if (ECS_Fast_Direction < 0) // No Fast ECS !
+ {
+ ECS_Fast_Enable = 0;
+ }
+ else
+ {
+ ECS_Fast_Direction = 1;
+ }
+ }
+ }
+
+ p_Ch++; // Next channel
+
+ } // for all channels of current object
+
+ pobj++; // Next object
+
+ } // for all objects
+
+ // Assign K fast following Delta variations
+ if (ECS_Fast_Enable)
+ {
+ retval = k_fast;
+ }
+
+ return retval;
+}
+
+
+/**
+ * @brief Calculate the new Reference on a group of objects
+ * @param[in] objgrp Pointer to the objects group to process
+ * @param[in] Kcoeff K coefficient to apply
+ * @retval None
+ */
+void TSL_ecs_ProcessK(TSL_ObjectGroup_T *objgrp, TSL_tKCoeff_T Kcoeff)
+{
+ TSL_tIndex_T idx_obj; // Index of current object
+ TSL_tIndex_T idx_ch; // Index of current channel
+ CONST TSL_Object_T *pobj;
+ TSL_tKCoeff_T Kcoeff_comp;
+ uint32_t ECS_meas;
+ uint32_t ECS_ref;
+ TSL_tNb_T nb_channels = 0; // Number of channels inside current object
+ TSL_ChannelData_T *p_Ch = 0;
+ void(*pFunc_SetStateCalibration)(TSL_tCounter_T delay) = 0;
+
+ // Check parameters (if USE_FULL_ASSERT is defined)
+ assert_param(IS_K_COEFF_OK(Kcoeff));
+
+ pobj = objgrp->p_Obj; // First object in the group
+
+ // Calculate the K coefficient complement
+ Kcoeff_comp = (0xFF ^ Kcoeff) + 1;
+
+ // Process all objects
+ for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
+ {
+
+ // Assign global object
+ TSL_obj_SetGlobalObj(pobj);
+
+#if TSLPRM_TOTAL_TKEYS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEY) || (THIS_OBJ_TYPE == TSL_OBJ_TOUCHKEYB))
+ {
+ // Ignore object if not in Release state (OFF or Error in this case)
+ if (THIS_TKEY_STATEID != TSL_STATEID_RELEASE)
+ {
+ pobj++; // Next object
+ continue; // Stop processing of current object
+ }
+ nb_channels = 1;
+ p_Ch = TSL_Globals.This_TKey->p_ChD;
+ pFunc_SetStateCalibration = &TSL_tkey_SetStateCalibration;
+ }
+#endif
+
+#if TSLPRM_TOTAL_LNRTS > 0
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB) ||
+ (THIS_OBJ_TYPE == TSL_OBJ_ROTARY) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARYB))
+ {
+ // Ignore object if not in Release state (OFF or Error in this case)
+ if (THIS_LINROT_STATEID != TSL_STATEID_RELEASE)
+ {
+ pobj++; // Next object
+ continue; // Stop processing of current object
+ }
+ nb_channels = THIS_LINROT_NB_CHANNELS;
+ p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ pFunc_SetStateCalibration = &TSL_linrot_SetStateCalibration;
+ }
+#endif
+
+ // Check channel pointer variable (if USE_FULL_ASSERT is defined)
+ assert_param(IS_POINTER_INITIALIZED(p_Ch));
+
+ // Calculate the new reference + rest for all channels
+ for (idx_ch = 0; idx_ch < nb_channels; idx_ch++)
+ {
+ ECS_meas = TSL_acq_ComputeMeas(p_Ch->Ref, p_Ch->Delta);
+ ECS_meas <<= 8;
+
+ ECS_ref = (uint32_t)(p_Ch->Ref);
+ ECS_ref <<= 8;
+ ECS_ref += p_Ch->RefRest;
+ ECS_ref *= Kcoeff_comp;
+ ECS_ref += (Kcoeff * ECS_meas);
+
+ p_Ch->RefRest = (TSL_tRefRest_T)((ECS_ref >> 8) & 0xFF);
+ p_Ch->Ref = (TSL_tRef_T)(ECS_ref >> 16);
+
+ // Go in Calibration state in the Reference is out of Range
+ if (TSL_acq_TestReferenceOutOfRange(p_Ch) == TSL_TRUE)
+ {
+ pFunc_SetStateCalibration(0);
+ }
+
+ p_Ch++; // Next channel
+ }
+
+ pobj++; // Next object
+
+ } // for all objects
+
+}
+
+
+/**
+ * @brief ECS algorithm on a group of objects
+ * The ECS is only performed if at least an object is in Release state and
+ * if no objects are in active states (Prox, Detect or Touch)
+ * An optional delay is added after the ECS condition (all sensors in Release state) is reached.
+ * @param[in] objgrp Pointer to the objects group to process
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_ecs_Process(TSL_ObjectGroup_T *objgrp)
+{
+ TSL_tKCoeff_T MyKcoeff;
+ TSL_Status_enum_T retval;
+
+ if ((objgrp->StateMask & TSL_STATE_RELEASE_BIT_MASK) && !(objgrp->StateMask & TSL_STATEMASK_ACTIVE))
+ {
+#if TSLPRM_ECS_DELAY > 0
+ if (!objgrp->ECS_wait)
+ {
+ disableInterrupts();
+ objgrp->ECS_start_time = TSL_Globals.Tick_ms; // Save the current time
+ enableInterrupts();
+ objgrp->ECS_wait = 1;
+ objgrp->ECS_exec = 0;
+ }
+#else
+ objgrp->ECS_exec = 1;
+#endif
+ }
+ else
+ {
+#if TSLPRM_ECS_DELAY > 0
+ objgrp->ECS_wait = 0;
+#endif
+ objgrp->ECS_exec = 0;
+ }
+
+#if TSLPRM_ECS_DELAY > 0
+ if (objgrp->ECS_wait && (!objgrp->ECS_exec))
+ {
+ // Execute the ECS only when the delay has elapsed
+ if (TSL_tim_CheckDelay_ms(TSLPRM_ECS_DELAY, &objgrp->ECS_start_time) == TSL_STATUS_OK)
+ {
+ objgrp->ECS_exec = 1;
+ }
+ }
+#endif
+
+ if (objgrp->ECS_exec)
+ {
+ // Calculate the K coefficient
+ MyKcoeff = TSL_ecs_CalcK(objgrp, TSLPRM_ECS_K_SLOW, TSLPRM_ECS_K_FAST);
+ // Process the objects
+ TSL_ecs_ProcessK(objgrp, MyKcoeff);
+ retval = TSL_STATUS_OK;
+ }
+ else
+ {
+ retval = TSL_STATUS_BUSY;
+ }
+
+ return retval;
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_filter.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_filter.c
new file mode 100644
index 0000000..8357154
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_filter.c
@@ -0,0 +1,137 @@
+/**
+ ******************************************************************************
+ * @file tsl_filter.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the signal or delta filters.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_filter.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/* Noise Filter description
+ ------------------------
+
+The noise filter is a first order IRR digital filter based on the following formula:
+
+S(n) = (1-k).S(n-1)+ k.N(n)
+
+S(n) : sample number n of the filtered signal
+N(n) : sample number n of the raw signal
+k : filter coefficient parameter in [0..1]
+
+The filter sampling rate is the acquisition rate.
+
+In order to optimize the implementation in the firmware, the above formula is
+modified in order to have only one multiply operation:
+
+S(n) = S(n-1) + k.(N(n) - S(n-1))
+
+Additionally, we use k = K/256 with K an unsigned 8-bit integer.
+
+The K is given by the ACQ_FILTER_COEFF constant.
+
+S(n) = S(n-1) + K.(N(n) - S(n-1))/(2^8)
+
+and the division can be done easily with bit shifting.
+
+As we are in the digital world, this formula presents a drawback:
+if the difference between S(n-1) and N(n) is less than 1/k, there will be no
+difference between S(n-1) and S(n).
+
+As a consequence, there will be a static error of up to 1/k.
+
+In the STMTouch Driver, the S(n) is stored in the Meas element of the data
+structure after each acquisition:
+
+Meas(n) = S(n) = N(n)
+
+The formula is then:
+
+Meas(n) = Meas(n-1) + K.(Meas(n) - Meas(n-1))/(2^8)
+
+In order to reduce the static error, we can use "Meas(n) = S(n).2^P".
+
+The P is given by the ACQ_FILTER_RANGE constant.
+
+This would shift the signal value left and provides a few additional low
+significant bits useful to reduce the static error.
+
+Warning: all thresholds must be shifted accordingly if the parameter P is
+different from 0.
+
+If we report this into the filter formula we obtain:
+
+Meas(n) = Meas(n-1) + K.[ Meas(n)*2^P - Meas(n-1)]/2^8
+
+In this case the static error is reduced to 1/(k.2^P)
+*/
+
+#define ACQ_FILTER_RANGE (0) /* Range[0..5] - Warning: all thresholds must be shifted if different from 0 */
+
+#define ACQ_FILTER_COEFF (128) /* Range[1..255] - First order filter coefficient (k = ACQ_FILTER_COEFF/256) */
+
+/**
+ * @brief Example of measure value filter
+ * @param[in] measn1 Previous measure value
+ * @param[in] measn Current measure value
+ * @retval Filtered measure
+ */
+TSL_tMeas_T TSL_filt_MeasFilter(TSL_tMeas_T measn1, TSL_tMeas_T measn)
+{
+ TSL_tMeas_T val;
+
+ val = (TSL_tMeas_T)(measn << ACQ_FILTER_RANGE);
+
+ if (measn1 != 0)
+ {
+ if (val > measn1)
+ {
+ val = measn1 + ((ACQ_FILTER_COEFF * (val - measn1)) >> 8);
+ }
+ else
+ {
+ val = measn1 - ((ACQ_FILTER_COEFF * (measn1 - val)) >> 8);
+ }
+ }
+
+ return(val);
+}
+
+
+/**
+ * @brief Example of delta value filter
+ * @param[in] delta Delta value to modify
+ * @retval Filtered delta
+ */
+TSL_tDelta_T TSL_filt_DeltaFilter(TSL_tDelta_T delta)
+{
+ return(delta);
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_globals.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_globals.c
new file mode 100644
index 0000000..4aa0d94
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_globals.c
@@ -0,0 +1,33 @@
+/**
+ ******************************************************************************
+ * @file tsl_globals.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains global variables.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_globals.h"
+
+TSL_Globals_T TSL_Globals; /**< Global variables used by main() and TSL modules */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c
new file mode 100644
index 0000000..561e15c
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c
@@ -0,0 +1,2103 @@
+/**
+ ******************************************************************************
+ * @file tsl_linrot.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage Linear and Rotary sensors.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_linrot.h"
+#include "tsl_globals.h"
+
+#if TSLPRM_TOTAL_LNRTS > 0
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+
+#define THIS_OBJ_TYPE TSL_Globals.This_Obj->Type
+
+#define THIS_STATEID TSL_Globals.This_LinRot->p_Data->StateId
+#define THIS_RAW_POSITION TSL_Globals.This_LinRot->p_Data->RawPosition
+#define THIS_POSITION TSL_Globals.This_LinRot->p_Data->Position
+#define THIS_CHANGE TSL_Globals.This_LinRot->p_Data->Change
+#define THIS_POSCHANGE TSL_Globals.This_LinRot->p_Data->PosChange
+#define THIS_COUNTER_DEB TSL_Globals.This_LinRot->p_Data->CounterDebounce
+#define THIS_COUNTER_DIR TSL_Globals.This_LinRot->p_Data->CounterDirection
+#define THIS_COUNTER_DTO TSL_Globals.This_LinRot->p_Data->CounterDTO
+#define THIS_DXSLOCK TSL_Globals.This_LinRot->p_Data->DxSLock
+#define THIS_DIRECTION TSL_Globals.This_LinRot->p_Data->Direction
+
+#define THIS_PROXIN_TH TSL_Globals.This_LinRot->p_Param->ProxInTh
+#define THIS_PROXOUT_TH TSL_Globals.This_LinRot->p_Param->ProxOutTh
+#define THIS_DETECTIN_TH TSL_Globals.This_LinRot->p_Param->DetectInTh
+#define THIS_DETECTOUT_TH TSL_Globals.This_LinRot->p_Param->DetectOutTh
+#define THIS_CALIB_TH TSL_Globals.This_LinRot->p_Param->CalibTh
+
+#define THIS_RESOLUTION TSL_Globals.This_LinRot->p_Param->Resolution
+#define THIS_DIR_CHG_POS TSL_Globals.This_LinRot->p_Param->DirChangePos
+
+#define THIS_COUNTER_DEB_CALIB TSL_Globals.This_LinRot->p_Param->CounterDebCalib
+#define THIS_COUNTER_DEB_PROX TSL_Globals.This_LinRot->p_Param->CounterDebProx
+#define THIS_COUNTER_DEB_DETECT TSL_Globals.This_LinRot->p_Param->CounterDebDetect
+#define THIS_COUNTER_DEB_RELEASE TSL_Globals.This_LinRot->p_Param->CounterDebRelease
+#define THIS_COUNTER_DEB_ERROR TSL_Globals.This_LinRot->p_Param->CounterDebError
+#define THIS_COUNTER_DEB_DIRECTION TSL_Globals.This_LinRot->p_Param->CounterDebDirection
+
+#define THIS_NB_CHANNELS TSL_Globals.This_LinRot->NbChannels
+#define THIS_SCT_COMP TSL_Globals.This_LinRot->SctComp
+#define THIS_POS_CORR TSL_Globals.This_LinRot->PosCorr
+
+#if TSLPRM_DTO > 0
+#define DTO_GET_TIME {TSL_linrot_DTOGetTime();}
+#else
+#define DTO_GET_TIME
+#endif
+
+/* Private variables ---------------------------------------------------------*/
+
+//================================================================
+// See AN2869 for more details on Linear and Rotary sensors design
+//================================================================
+
+//==============================================================================
+// 3 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3
+//==============================================================================
+#if TSLPRM_USE_3CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_LIN_M1[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -96, 0 }, // maj = 1; i = 0
+ { 32, 0, -160 }, // maj = 2; i = 1
+ { 0, 96, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 3 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3
+//==============================================================================
+#if TSLPRM_USE_3CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_LIN_M2[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -192, 0 }, // maj = 1; i = 0
+ { 64, 0, -320 }, // maj = 2; i = 1
+ { 0, 192, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 3 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH1
+//==============================================================================
+#if TSLPRM_USE_3CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_LIN_H[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -96, 160 }, // maj = 1; i = 0
+ { 32, 0, -160 }, // maj = 2; i = 1
+ { -224, 96, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 3 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3
+//==============================================================================
+#if TSLPRM_USE_3CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_ROT_M[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -64, 107 }, // maj = 1; i = 0
+ { 21, 0, -107 }, // maj = 2; i = 1
+ { -149, 64, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3 CH4
+//==============================================================================
+#if TSLPRM_USE_4CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_LIN_M1[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -64, 0, 0 }, // maj = 1; i = 0
+ { 21, 0, -107, 0 }, // maj = 2; i = 1
+ { 0, 64, 0, -149 }, // maj = 3; i = 2
+ { 0, 0, 107, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3 CH4
+//==============================================================================
+#if TSLPRM_USE_4CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_LIN_M2[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -96, 0, 0 }, // maj = 1; i = 0
+ { 32, 0, -160, 0 }, // maj = 2; i = 1
+ { 0, 96, 0, -224 }, // maj = 3; i = 2
+ { 0, 0, 160, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH4 CH1
+//==============================================================================
+#if TSLPRM_USE_4CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_LIN_H[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -64, 0, 149 }, // maj = 1; i = 0
+ { 21, 0, -107, 0 }, // maj = 2; i = 1
+ { 0, 64, 0, -149 }, // maj = 3; i = 2
+ { -192, 0, 107, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3 CH4
+//==============================================================================
+#if TSLPRM_USE_4CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_ROT_M[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -48, 0, 112 }, // maj = 1; i = 0
+ { 16, 0, -80, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112 }, // maj = 3; i = 2
+ { -144, 0, 80, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3 CH4 CH5
+//==============================================================================
+#if TSLPRM_USE_5CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_LIN_M1[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -48, 0, 0, 0 }, // maj = 1; i = 0
+ { 16, 0, -80, 0, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112, 0 }, // maj = 3; i = 2
+ { 0, 0, 80, 0, -144 }, // maj = 4; i = 3
+ { 0, 0, 0, 112, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5
+//==============================================================================
+#if TSLPRM_USE_5CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_LIN_M2[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -64, 0, 0, 0 }, // maj = 1; i = 0
+ { 21, 0, -107, 0, 0 }, // maj = 2; i = 1
+ { 0, 64, 0, -149, 0 }, // maj = 3; i = 2
+ { 0, 0, 107, 0, -192 }, // maj = 4; i = 3
+ { 0, 0, 0, 149, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH4 CH5 CH1
+//==============================================================================
+#if TSLPRM_USE_5CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_LIN_H[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -48, 0, 0, 144 }, // maj = 1; i = 0
+ { 16, 0, -80, 0, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112, 0 }, // maj = 3; i = 2
+ { 0, 0, 80, 0, -144 }, // maj = 4; i = 3
+ { -176, 0, 0, 112, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5
+//==============================================================================
+#if TSLPRM_USE_5CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_ROT_M[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -38, 0, 0, 115 }, // maj = 1; i = 0
+ { 13, 0, -64, 0, 0 }, // maj = 2; i = 1
+ { 0, 38, 0, -90, 0 }, // maj = 3; i = 2
+ { 0, 0, 64, 0, -115 }, // maj = 4; i = 3
+ {-141, 0, 0, 90, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - ROTARY - DUAL
+// i.e. CH1 CH2 CH3 CH4 CH5 CH1 CH3 CH5 CH2 CH4
+//==============================================================================
+#if TSLPRM_USE_5CH_ROT_D > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_ROT_D[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -19, -83, 122, 58 }, // maj = 1; i = 0
+ { 6, 0, -32, -122, 96 }, // maj = 2; i = 1
+ { 70, 19, 0, -45, -96 }, // maj = 3; i = 2
+ {-134, 109, 32, 0, -58 }, // maj = 4; i = 3
+ { -70, -109, 83, 45, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6
+//==============================================================================
+#if TSLPRM_USE_6CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_LIN_M1[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -38, 0, 0, 0, 0 }, // maj = 1; i = 0
+ { 13, 0, -64, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 38, 0, -90, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 64, 0, -115, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 90, 0, -141 }, // maj = 5; i = 4
+ { 0, 0, 0, 0, 115, 0 } // maj = 6; i = 5
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6
+//==============================================================================
+#if TSLPRM_USE_6CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_LIN_M2[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -48, 0, 0, 0, 0 }, // maj = 1; i = 0
+ { 16, 0, -80, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 80, 0, -144, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 112, 0, -176 }, // maj = 5; i = 4
+ { 0, 0, 0, 0, 144, 0 } // maj = 6; i = 5
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6 CH1
+//==============================================================================
+#if TSLPRM_USE_6CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_LIN_H[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -38, 0, 0, 0, 141 }, // maj = 1; i = 0
+ { 13, 0, -64, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 38, 0, -90, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 64, 0, -115, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 90, 0, -141 }, // maj = 5; i = 4
+ {-166, 0, 0, 0, 115, 0 } // maj = 6; i = 5
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6
+//==============================================================================
+#if TSLPRM_USE_6CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_ROT_M[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -32, 0, 0, 0, 117 }, // maj = 1; i = 0
+ { 11, 0, -53, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 32, 0, -75, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 53, 0, -96, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 75, 0, -117 }, // maj = 5; i = 4
+ {-139, 0, 0, 0, 96, 0 } // maj = 6; i = 5
+};
+#endif
+
+//------------------
+// Common parameters
+//------------------
+
+#define DIRECTION_CHANGE_MAX_DISPLACEMENT (255)
+#define DIRECTION_CHANGE_TOTAL_STEPS (256)
+#define RESOLUTION_CALCULATION (8)
+
+static TSL_tNb_T CalibDiv;
+
+/* Private functions prototype -----------------------------------------------*/
+
+void TSL_linrot_DTOGetTime(void);
+void TSL_linrot_ProcessCh_All_SetStatus(TSL_ObjStatus_enum_T sts);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DataReady(void);
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_AcqStatus(TSL_AcqStatus_enum_T sts);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_AcqStatusError(void);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAboveEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAbove(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_DeltaBelowEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+void TSL_linrot_ProcessCh_All_ClearRef(void);
+TSL_tDelta_T TSL_linrot_NormDelta(TSL_ChannelData_T *ch, TSL_tIndex_T idx);
+
+
+//==============================================================================
+// "Object methods" functions
+//==============================================================================
+
+/**
+ * @brief Init parameters with default values from configuration file
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_Init(void)
+{
+ // Thresholds
+#if TSLPRM_USE_PROX > 0
+ THIS_PROXIN_TH = TSLPRM_LINROT_PROX_IN_TH;
+ THIS_PROXOUT_TH = TSLPRM_LINROT_PROX_OUT_TH;
+#endif
+ THIS_DETECTIN_TH = TSLPRM_LINROT_DETECT_IN_TH;
+ THIS_DETECTOUT_TH = TSLPRM_LINROT_DETECT_OUT_TH;
+ THIS_CALIB_TH = TSLPRM_LINROT_CALIB_TH;
+
+ // Debounce counters
+ THIS_COUNTER_DEB_CALIB = TSLPRM_DEBOUNCE_CALIB;
+#if TSLPRM_USE_PROX > 0
+ THIS_COUNTER_DEB_PROX = TSLPRM_DEBOUNCE_PROX;
+#endif
+ THIS_COUNTER_DEB_DETECT = TSLPRM_DEBOUNCE_DETECT;
+ THIS_COUNTER_DEB_RELEASE = TSLPRM_DEBOUNCE_RELEASE;
+ THIS_COUNTER_DEB_ERROR = TSLPRM_DEBOUNCE_ERROR;
+
+ // Other parameters for linear/rotary only
+ THIS_RESOLUTION = TSLPRM_LINROT_RESOLUTION;
+ THIS_DIR_CHG_POS = TSLPRM_LINROT_DIR_CHG_POS;
+ THIS_COUNTER_DEB_DIRECTION = TSLPRM_LINROT_DIR_CHG_DEB;
+
+ // Initial state
+ TSL_linrot_SetStateCalibration(TSLPRM_CALIB_DELAY);
+}
+
+
+/**
+ * @brief Process the State Machine
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_Process(void)
+{
+ TSL_StateId_enum_T prev_state_id;
+
+ // Check if at least one channel has a data ready
+ if ((TSL_linrot_ProcessCh_One_DataReady() == TSL_STATUS_OK) || (THIS_STATEID == TSL_STATEID_OFF))
+ {
+
+ prev_state_id = THIS_STATEID;
+
+#if TSLPRM_TOTAL_LINROTS > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEAR) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARY))
+ {
+ // Launch the object state function
+ TSL_Globals.This_LinRot->p_SM[THIS_STATEID].StateFunc();
+ }
+#endif
+
+#if TSLPRM_TOTAL_LINROTS_B > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEARB) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARYB))
+ {
+ // Launch the TSL_Params state function
+ TSL_Params.p_LinRotSM[THIS_STATEID].StateFunc();
+ }
+#endif
+
+ // Check if the new state has changed
+ if (THIS_STATEID == prev_state_id)
+ {
+ THIS_CHANGE = TSL_STATE_NOT_CHANGED;
+ }
+ else
+ {
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ }
+
+#if TSLPRM_USE_DXS > 0
+ if (THIS_STATEID != TSL_STATEID_DETECT)
+ {
+ THIS_DXSLOCK = TSL_FALSE;
+ }
+ if (THIS_STATEID == TSL_STATEID_TOUCH)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+#endif
+
+ }
+}
+
+
+/**
+ * @brief Calculate the position
+ * @param None
+ * @retval Status Return OK if position calculation is correct
+ * @note The position is calculated only if the number of channels is greater than 2
+ */
+TSL_Status_enum_T TSL_linrot_CalcPos(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+ static TSL_tDelta_T delta1;
+ static TSL_tDelta_T delta2;
+ static TSL_tDelta_T delta3;
+ static TSL_tIndex_T index1;
+ static TSL_tIndex_T index2;
+ TSL_tNb_T minor;
+ TSL_tNb_T major;
+ TSL_tNb_T sector_computation = 0;
+ TSL_tNb_T position_correction = 0;
+ TSL_tsignPosition_T new_position = 0;
+ TSL_tPosition_T u_new_position = 0;
+
+ delta1 = 0;
+ delta2 = 0;
+ delta3 = 0;
+
+ index1 = 0;
+ index2 = 0;
+
+ // The position change flag will be set only if a new position is detected.
+ THIS_POSCHANGE = TSL_STATE_NOT_CHANGED;
+
+ // The position is calculated only if the number of channels is greater than 2
+ if (THIS_NB_CHANNELS < 3)
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ //--------------------------------------------------------------------------
+ // Sort the channels' delta
+ // - delta1 and index1 = biggest
+ // - delta2 and index2 = middle
+ // - delta3 and index3 = lowest
+ //--------------------------------------------------------------------------
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+ // The Delta must be positive only otherwise it is noise
+ if (norm_delta < 0) {norm_delta = 0;}
+
+ if (norm_delta > delta1)
+ {
+ delta3 = delta2;
+ delta2 = delta1;
+ delta1 = norm_delta;
+ index2 = index1;
+ index1 = idx;
+ }
+ else
+ {
+ if (norm_delta > delta2)
+ {
+ delta3 = delta2;
+ delta2 = norm_delta;
+ index2 = idx;
+ }
+ else
+ {
+ if (norm_delta > delta3)
+ {
+ delta3 = norm_delta;
+ }
+ }
+ }
+
+ p_Ch++; // Next channel
+
+ } // for all channels
+
+ // Noise filter: we need at least two significant Delta measurements
+ if (delta2 < ((TSL_tThreshold_T)(THIS_DETECTOUT_TH >> 1) - 1))
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ //----------------------------------------------------------------------------
+ // Position calculation...
+ //----------------------------------------------------------------------------
+
+ /*----------------------------------------------------------------------------
+ B = Biggest signal measured (Delta1/Index1)
+ M = Middle signal measured (Delta2/Index2)
+ S = Smallest signal measured (Delta3/Index3)
+
+ - The equation to find the position is:
+ Position = Offset +/- [ Sector_Size x ( Major / (Major + Minor) ) ]
+
+ - The Offset is the position of the middle of the Middle signal segment.
+ All the Offset values are stored in the ROM table Table_POSITION_OFFSET.
+
+ - Major = Biggest - Smallest signals
+ Minor = Middle - Smallest signals
+
+ - The Sector_Size depends of the number of channels used
+ ----------------------------------------------------------------------------*/
+
+ // Calculates the Major and Minor parameters
+ minor = (TSL_tNb_T)(delta2 - delta3); // Middle - Smallest signals
+ major = (TSL_tNb_T)(delta1 - delta3); // Biggest - Smallest signals
+
+ // Select the offset position in the position offset constant table
+ // Equal to: new_position = TABLE_POSITION_OFFSET_xCH_xxx[index1][index2];
+ new_position = *(TSL_Globals.This_LinRot->p_PosOff + (index1 * THIS_NB_CHANNELS) + index2);
+ sector_computation = THIS_SCT_COMP;
+ position_correction = THIS_POS_CORR;
+
+ // Calculates: [ Sector_Size x ( Major / (Major + Minor) ) ]
+ sector_computation = major * sector_computation;
+ sector_computation = sector_computation / (major + minor);
+
+ // Use the sign bit from position table to define the interpretation direction.
+ // The NewPosition is multiplied by 2 because the Offset stored in the ROM
+ // table is divided by 2...
+ if (new_position > 0) // Means Offset is > 0 in the position table
+ {
+ new_position = (TSL_tsignPosition_T)(new_position << 1);
+ new_position += sector_computation;
+ }
+ else // means Offset is <= 0 in the ROM table
+ {
+ new_position = (TSL_tsignPosition_T)((-new_position) << 1);
+ new_position -= sector_computation;
+ }
+
+ // Position is calculated differently if LINEAR or ROTARY sensor
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB))
+ {
+
+ // First adjustment used to shift all the values to obtain the "zero"
+ if (new_position > 0)
+ {
+ new_position -= position_correction;
+ }
+ else
+ {
+ new_position = new_position + (256 - position_correction);
+ }
+
+ // Second adjustment used to clamp the values at both ends of sensor
+ if (new_position < 0)
+ {
+ new_position = 0;
+ }
+
+ if (new_position > 255)
+ {
+ new_position = 255;
+ }
+
+ }
+ else // ROTARY sensor: keep only the low byte
+ {
+ new_position = (TSL_tPosition_T)new_position;
+ }
+
+ //----------------------------------------------------------------------------
+ // Direction Change Process
+ //----------------------------------------------------------------------------
+
+ if (THIS_DIRECTION == TSL_TRUE) // Anticlockwise direction ...
+ {
+
+ // Check Direction changed and Position overflow from 0x00 to 0xFF not realized !
+ if (((TSL_tPosition_T)new_position > THIS_RAW_POSITION) && (((TSL_tPosition_T)new_position - THIS_RAW_POSITION) < DIRECTION_CHANGE_MAX_DISPLACEMENT))
+ {
+ if (new_position < (uint16_t)(THIS_RAW_POSITION + THIS_DIR_CHG_POS))
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_FALSE; // New direction accepted: clockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ // Check position overflow from 0xFF to 0x00 to be filtered !
+ if ((new_position + DIRECTION_CHANGE_MAX_DISPLACEMENT) < THIS_RAW_POSITION)
+ {
+ if ((new_position + DIRECTION_CHANGE_TOTAL_STEPS) < (uint16_t)(THIS_RAW_POSITION + THIS_DIR_CHG_POS))
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_FALSE; // New direction accepted: clockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ }
+ else // Clockwise direction... DEFAULT SETTING !
+ {
+
+ // Check Direction changed and Position overflow from 0xFF to 0x00 not realized !
+ if (((TSL_tPosition_T)new_position < THIS_RAW_POSITION) && ((THIS_RAW_POSITION - (TSL_tPosition_T)new_position) < DIRECTION_CHANGE_MAX_DISPLACEMENT))
+ {
+ if ((new_position + THIS_DIR_CHG_POS) > THIS_RAW_POSITION)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_TRUE; // New direction accepted: anticlockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ // Check position overflow from 0x00 to 0xFF to be filtered !
+ if (new_position > (uint16_t)(THIS_RAW_POSITION + DIRECTION_CHANGE_MAX_DISPLACEMENT))
+ {
+ if ((new_position + THIS_DIR_CHG_POS) > (uint16_t)(THIS_RAW_POSITION + DIRECTION_CHANGE_TOTAL_STEPS))
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_TRUE; // New direction accepted: anticlockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+ // Final result...
+ //----------------------------------------------------------------------------
+
+ // The Raw Position is always updated
+ // The Position is updated only if different from the previous one
+
+ THIS_RAW_POSITION = (TSL_tPosition_T)new_position;
+
+ u_new_position = (TSL_tPosition_T)((TSL_tPosition_T)new_position >> (RESOLUTION_CALCULATION - THIS_RESOLUTION));
+
+ if (THIS_POSITION == u_new_position)
+ {
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_POSITION = u_new_position;
+ THIS_POSCHANGE = TSL_STATE_CHANGED;
+ return TSL_STATUS_OK;
+ }
+
+}
+
+
+//==============================================================================
+// Utility functions
+//==============================================================================
+
+/**
+ * @brief Go in Calibration state
+ * @param[in] delay Delay before calibration starts (stabilization of noise filter)
+ * @retval None
+ */
+void TSL_linrot_SetStateCalibration(TSL_tCounter_T delay)
+{
+ THIS_STATEID = TSL_STATEID_CALIB;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ TSL_linrot_ProcessCh_All_SetStatus(TSL_OBJ_STATUS_ON);
+
+ switch (TSL_Params.NbCalibSamples)
+ {
+ case 4:
+ CalibDiv = 2;
+ break;
+ case 16:
+ CalibDiv = 4;
+ break;
+ default:
+ TSL_Params.NbCalibSamples = 8;
+ CalibDiv = 3;
+ break;
+ }
+
+ // If a noise filter is used, the counter must be initialized to a value
+ // different from 0 in order to stabilize the filter.
+ THIS_COUNTER_DEB = (TSL_tCounter_T)(delay + (TSL_tCounter_T)TSL_Params.NbCalibSamples);
+ TSL_linrot_ProcessCh_All_ClearRef();
+}
+
+
+/**
+ * @brief Go in Off state with sensor "off"
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_SetStateOff(void)
+{
+ THIS_STATEID = TSL_STATEID_OFF;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ TSL_linrot_ProcessCh_All_SetStatus(TSL_OBJ_STATUS_OFF);
+}
+
+
+#if !defined(TSLPRM_STM8TL5X) && !defined(STM8TL5X)
+/**
+ * @brief Go in Off state with sensor in "Burst mode only"
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_SetStateBurstOnly(void)
+{
+ THIS_STATEID = TSL_STATEID_OFF;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ TSL_linrot_ProcessCh_All_SetStatus(TSL_OBJ_STATUS_BURST_ONLY);
+}
+#endif
+
+
+/**
+ * @brief Return the current state identifier
+ * @param None
+ * @retval State id
+ */
+TSL_StateId_enum_T TSL_linrot_GetStateId(void)
+{
+ return(THIS_STATEID);
+}
+
+
+/**
+ * @brief Return the current state mask
+ * @param None
+ * @retval State mask
+ */
+TSL_StateMask_enum_T TSL_linrot_GetStateMask(void)
+{
+ TSL_StateMask_enum_T state_mask = TSL_STATEMASK_UNKNOWN;
+
+#if TSLPRM_TOTAL_LINROTS > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEAR) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARY))
+ {
+ state_mask = TSL_Globals.This_LinRot->p_SM[THIS_STATEID].StateMask;
+ }
+#endif
+
+#if TSLPRM_TOTAL_LINROTS_B > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEARB) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARYB))
+ {
+ state_mask = TSL_Params.p_LinRotSM[THIS_STATEID].StateMask;
+ }
+#endif
+
+ return state_mask;
+}
+
+
+/**
+ * @brief Return the Change flag
+ * @param None
+ * @retval Change flag status
+ */
+TSL_tNb_T TSL_linrot_IsChanged(void)
+{
+ return(THIS_CHANGE);
+}
+
+
+//==============================================================================
+// State machine functions
+//==============================================================================
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Release processing (previous state = Proximity)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebReleaseProxStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_PROX; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_PROX; // Go back to the previous state
+ }
+ else
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+#endif // if TSLPRM_USE_PROX > 0
+
+
+/**
+ * @brief Debounce Release processing (previous state = Detect)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebReleaseDetectStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ return;
+ }
+#endif
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+
+
+/**
+ * @brief Debounce Release processing (previous state = Touch)
+ * Same as Debounce Release Detect processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebReleaseTouchStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ return;
+ }
+#endif
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+
+
+/**
+ * @brief Release state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_ReleaseStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_RELEASE;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_PROXIN_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX;
+ }
+ return;
+ }
+#endif
+
+ // Check delta for re-calibration
+ if (TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(THIS_CALIB_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_CALIB;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_CALIB;
+ }
+ }
+ }
+}
+
+
+/**
+ * @brief Debounce Calibration processing (previous state = Release)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebCalibrationStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(THIS_CALIB_TH, 1) == TSL_STATUS_OK) // Still below recalibration threshold
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ // else stay in Debounce Calibration
+ }
+ else // Go back to previous state
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+
+
+/**
+ * @brief Calibration state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_CalibrationStateProcess(void)
+{
+ TSL_tMeas_T new_meas;
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch;
+
+#if TSLPRM_CALIB_DELAY > 0
+ // Noise filter stabilization time
+ if (THIS_COUNTER_DEB > (TSL_tCounter_T)TSL_Params.NbCalibSamples)
+ {
+ THIS_COUNTER_DEB--;
+ return; // Skip the sample
+ }
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_CALIB;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ // Process all channels
+ p_Ch = TSL_Globals.This_LinRot->p_ChD;
+
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+ // Get the new measure or Calculate it
+#if TSLPRM_USE_MEAS > 0
+ new_meas = p_Ch->Meas;
+#else // Calculate it
+ new_meas = TSL_acq_ComputeMeas(p_Ch->Ref, p_Ch->Delta);
+#endif
+
+ // Verify the first Reference value
+ if (THIS_COUNTER_DEB == (TSL_tCounter_T)TSL_Params.NbCalibSamples)
+ {
+ if (TSL_acq_TestFirstReferenceIsValid(p_Ch, new_meas))
+ {
+ p_Ch->Ref = new_meas;
+ }
+ else
+ {
+ p_Ch->Ref = 0;
+ return;
+ }
+ }
+ else
+ {
+ // Add the measure in temporary Reference
+ p_Ch->Ref += new_meas;
+
+ // Check reference overflow
+ if (p_Ch->Ref < new_meas)
+ {
+ p_Ch->Ref = 0; // Suppress the bad reference
+ THIS_STATEID = TSL_STATEID_ERROR;
+ return;
+ }
+ }
+
+ p_Ch++; // Next channel
+ }
+
+ // Check that we have all the needed measurements
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ // Process all channels
+ p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ // Divide temporary Reference by the number of samples
+ p_Ch->Ref >>= CalibDiv;
+ p_Ch->RefRest = 0;
+ p_Ch->Delta = 0;
+ p_Ch++; // Next channel
+ }
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Release)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebProxStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_PROXIN_TH, 0) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Detect)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebProxDetectStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_DETECT;
+ }
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Touch)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebProxTouchStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_TOUCH;
+ }
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Proximity state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_ProxStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_PROX;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_All_DeltaBelowEqu(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_PROX;
+ }
+ return;
+ }
+
+ // Stay in Proximity state
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ //------------------------------------
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ }
+#endif
+
+ }
+}
+#endif
+
+
+/**
+ * @brief Debounce Detect processing (previous state = Release or Proximity)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebDetectStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Detect
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_PROXIN_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX;
+ }
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+#else
+ THIS_STATEID = TSL_STATEID_RELEASE;
+#endif
+ }
+ }
+}
+
+
+/**
+ * @brief Detect state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DetectStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_Status_enum_T pos_sts;
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_DETECT;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ //-------------------
+ // Calculate position
+ //-------------------
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARY))
+ {
+ // Call the specific method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#else
+ TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#endif
+ }
+ else // TSL_OBJ_LINEARB or TSL_OBJ_ROTARYB
+ {
+ // Call the default method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Params.p_LinRotMT->CalcPosition();
+#else
+ TSL_Params.p_LinRotMT->CalcPosition();
+#endif
+ }
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ // Only if the Position has NOT changed
+ //-------------------------------------
+ if (pos_sts == TSL_STATUS_OK)
+ {
+ DTO_GET_TIME; // Take current time
+ }
+ else
+ {
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ }
+ }
+#endif
+ return; // Normal operation, stay in Detect state
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX_DETECT;
+ }
+ return;
+ }
+#endif
+
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_DETECT;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Touch state processing
+ * Same as Detect state
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_TouchStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_Status_enum_T pos_sts;
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_TOUCH;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ //-------------------
+ // Calculate position
+ //-------------------
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARY))
+ {
+ // Call the specific method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#else
+ TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#endif
+ }
+ else // TSL_OBJ_LINEARB or TSL_OBJ_ROTARYB
+ {
+ // Call the default method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Params.p_LinRotMT->CalcPosition();
+#else
+ TSL_Params.p_LinRotMT->CalcPosition();
+#endif
+ }
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ // Only if the Position has NOT changed
+ //-------------------------------------
+ if (pos_sts == TSL_STATUS_OK)
+ {
+ DTO_GET_TIME; // Take current time
+ }
+ else
+ {
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ }
+ }
+#endif
+ return; // Normal operation, stay in Touch state
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX_TOUCH;
+ }
+ return;
+ }
+#endif
+
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_TOUCH;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Debounce error state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebErrorStateProcess(void)
+{
+ volatile TSL_StateMask_enum_T mask;
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ // Get state mask
+ mask = TSL_linrot_GetStateMask();
+ // Mask Error and Debounce bits
+#ifdef _RAISONANCE_
+ mask &= ~(TSL_STATE_DEBOUNCE_BIT_MASK | TSL_STATE_ERROR_BIT_MASK);
+#else
+ mask &= (TSL_StateMask_enum_T)(~(TSL_STATE_DEBOUNCE_BIT_MASK | TSL_STATE_ERROR_BIT_MASK));
+#endif
+ // Go back to the previous state
+ switch (mask)
+ {
+ case TSL_STATEMASK_RELEASE :
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ break;
+ case TSL_STATEMASK_PROX :
+ THIS_STATEID = TSL_STATEID_PROX;
+ break;
+ case TSL_STATEMASK_DETECT :
+ THIS_STATEID = TSL_STATEID_DETECT;
+ break;
+ case TSL_STATEMASK_TOUCH :
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ break;
+ default:
+ TSL_linrot_SetStateCalibration(0);
+ break;
+ }
+ }
+}
+
+
+//==============================================================================
+// Private functions
+//==============================================================================
+
+/**
+ * @brief Get the current time in second and affect it to the DTO counter (Private)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DTOGetTime(void)
+{
+ disableInterrupts();
+ THIS_COUNTER_DTO = (TSL_tCounter_T)TSL_Globals.Tick_sec;
+ enableInterrupts();
+}
+
+
+/**
+ * @brief Set all channels status to ON, OFF or BURST ONLY
+ * @param sts Channel status
+ * @retval None
+ */
+void TSL_linrot_ProcessCh_All_SetStatus(TSL_ObjStatus_enum_T sts)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ // Init channels status
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ p_Ch->Flags.ObjStatus = sts;
+ p_Ch++;
+ }
+}
+
+
+/**
+ * @brief Check if at least one channel has a data ready
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DataReady(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_Status_enum_T retval = TSL_STATUS_ERROR;
+ // Return OK if at least one channel has a data ready
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ if (p_Ch->Flags.DataReady == TSL_DATA_READY)
+ {
+ p_Ch->Flags.DataReady = TSL_DATA_NOT_READY; // The new data is processed
+ retval = TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return retval;
+}
+
+
+/**
+ * @brief Check if all channels are equal to the status passed
+ * @param sts Status to be checked
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_AcqStatus(TSL_AcqStatus_enum_T sts)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ // Return OK if ALL channels have the correct acq status
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ if (p_Ch->Flags.AcqStatus != sts)
+ {
+ return TSL_STATUS_ERROR;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Check if at least one channel is in error
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_AcqStatusError(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ // Return OK if at least one channel is in acquisition error min or max
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ if (p_Ch->Flags.AcqStatus & TSL_ACQ_STATUS_ERROR_MASK)
+ {
+ return TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if at least one channel is below or equal a threshold (inverted)
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if at least one channel is below or equal the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta <= -lth) // Warning!!! The threshold is inverted
+#else
+ if (norm_delta <= -th) // Warning!!! The threshold is inverted
+#endif
+ {
+ return TSL_STATUS_OK;
+ }
+
+ p_Ch++;
+ }
+
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if at least one channel is above or equal a threshold
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAboveEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if at least one channel is above or equal the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta >= lth)
+#else
+ if (norm_delta >= th)
+#endif
+ {
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta < 0)
+ {
+ p_Ch++;
+ continue;
+ }
+#endif
+ return TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if at least one channel is stricly above a threshold
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAbove(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if at least one channel is above the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta > lth)
+#else
+ if (norm_delta > th)
+#endif
+ {
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta < 0)
+ {
+ p_Ch++;
+ continue;
+ }
+#endif
+ return TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if all channels are below or equal a threshold
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_DeltaBelowEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if ALL channels are below or equal the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta > lth)
+#else
+ if (norm_delta > th)
+#endif
+ {
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta < 0)
+ {
+ p_Ch++;
+ continue;
+ }
+#endif
+ return TSL_STATUS_ERROR;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Clear the Reference and ReferenceRest for all channels
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_ProcessCh_All_ClearRef(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ p_Ch->Ref = 0;
+ p_Ch->RefRest = 0;
+ p_Ch++;
+ }
+}
+
+
+/**
+ * @brief Normalize a Delta value
+ * @param ch Pointer to the current channel
+ * @param idx Index of the channel
+ * @retval Normalized Delta value
+ */
+TSL_tDelta_T TSL_linrot_NormDelta(TSL_ChannelData_T *ch, TSL_tIndex_T idx)
+{
+ uint32_t tmpdelta = ch->Delta;
+
+ // Apply coefficient
+ if (TSL_Globals.This_LinRot->p_DeltaCoeff[idx] != 0x0100)
+ {
+ tmpdelta = (uint32_t)(tmpdelta * TSL_Globals.This_LinRot->p_DeltaCoeff[idx]);
+ tmpdelta = tmpdelta >> (uint8_t)8;
+ }
+
+ return (TSL_tDelta_T)tmpdelta;
+}
+
+#endif
+// #if TSLPRM_TOTAL_LNRTS > 0
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_object.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_object.c
new file mode 100644
index 0000000..7c2e9bf
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_object.c
@@ -0,0 +1,258 @@
+/**
+ ******************************************************************************
+ * @file tsl_object.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the sensors in general.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_object.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Initialize a group of Objects
+ * @param[in] objgrp Pointer to the group of objects
+ * @retval None
+ */
+void TSL_obj_GroupInit(TSL_ObjectGroup_T *objgrp)
+{
+ TSL_tIndex_T idx_obj;
+ CONST TSL_Object_T *pobj;
+ TSL_tNb_T objgrp_state_mask = 0;
+
+ pobj = objgrp->p_Obj; // First object in the group
+
+ objgrp->Change = TSL_STATE_NOT_CHANGED;
+
+ // Process all objects
+ for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
+ {
+
+ // Assign global object
+ TSL_obj_SetGlobalObj(pobj);
+
+ switch (pobj->Type)
+ {
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_TOUCHKEYS > 0
+ case TSL_OBJ_TOUCHKEY:
+ // Call the specific method
+ TSL_Globals.This_TKey->p_Methods->Init();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_TKey->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Update object group state mask
+ objgrp_state_mask |= TSL_Globals.This_TKey->p_SM[TSL_Globals.This_TKey->p_Data->StateId].StateMask;
+ break;
+#endif
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_TOUCHKEYS_B > 0
+ case TSL_OBJ_TOUCHKEYB:
+ // Call the default method
+ TSL_Params.p_TKeyMT->Init();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_TKey->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Get object state mask from state machine in TSL_Params
+ objgrp_state_mask |= TSL_Params.p_TKeySM[TSL_Globals.This_TKey->p_Data->StateId].StateMask;
+ break;
+#endif
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_LINROTS > 0
+ case TSL_OBJ_LINEAR:
+ case TSL_OBJ_ROTARY:
+ // Call the specific method
+ TSL_Globals.This_LinRot->p_Methods->Init();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_LinRot->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Update object group state mask
+ objgrp_state_mask |= TSL_Globals.This_LinRot->p_SM[TSL_Globals.This_LinRot->p_Data->StateId].StateMask;
+ break;
+#endif
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_LINROTS_B > 0
+ case TSL_OBJ_LINEARB:
+ case TSL_OBJ_ROTARYB:
+ // Call the default method
+ TSL_Params.p_LinRotMT->Init();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_LinRot->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Get object state mask from state machine in TSL_Params
+ objgrp_state_mask |= TSL_Params.p_LinRotSM[TSL_Globals.This_LinRot->p_Data->StateId].StateMask;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ pobj++; // Next object
+ }
+
+ // Update the object group state mask
+ objgrp->StateMask = objgrp_state_mask;
+}
+
+
+/**
+ * @brief Process the state machine on a group of Objects
+ * @param[in] objgrp Pointer to the group of objects to process
+ * @retval None
+ */
+void TSL_obj_GroupProcess(TSL_ObjectGroup_T *objgrp)
+{
+ TSL_tIndex_T idx_obj;
+ CONST TSL_Object_T *pobj;
+ TSL_tNb_T objgrp_state_mask = 0;
+
+ pobj = objgrp->p_Obj; // First object in the group
+
+ objgrp->Change = TSL_STATE_NOT_CHANGED;
+
+ // Process all objects
+ for (idx_obj = 0; idx_obj < objgrp->NbObjects; idx_obj++)
+ {
+
+ // Assign global object
+ TSL_obj_SetGlobalObj(pobj);
+
+ switch (pobj->Type)
+ {
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_TOUCHKEYS > 0
+ case TSL_OBJ_TOUCHKEY:
+ // Call the specific method
+ TSL_Globals.This_TKey->p_Methods->Process();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_TKey->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Update object group state mask
+ objgrp_state_mask |= TSL_Globals.This_TKey->p_SM[TSL_Globals.This_TKey->p_Data->StateId].StateMask;
+ break;
+#endif
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_TOUCHKEYS_B > 0
+ case TSL_OBJ_TOUCHKEYB:
+ // Call the default method
+ TSL_Params.p_TKeyMT->Process();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_TKey->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Get object state mask from state machine in TSL_Params
+ objgrp_state_mask |= TSL_Params.p_TKeySM[TSL_Globals.This_TKey->p_Data->StateId].StateMask;
+ break;
+#endif
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_LINROTS > 0
+ case TSL_OBJ_LINEAR:
+ case TSL_OBJ_ROTARY:
+ // Call the specific method
+ TSL_Globals.This_LinRot->p_Methods->Process();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_LinRot->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Update object group state mask
+ objgrp_state_mask |= TSL_Globals.This_LinRot->p_SM[TSL_Globals.This_LinRot->p_Data->StateId].StateMask;
+ break;
+#endif
+ //------------------------------------------------------------------------
+#if TSLPRM_TOTAL_LINROTS_B > 0
+ case TSL_OBJ_LINEARB:
+ case TSL_OBJ_ROTARYB:
+ // Call the default method
+ TSL_Params.p_LinRotMT->Process();
+ // Check if the object has changed of state
+ if (TSL_Globals.This_LinRot->p_Data->Change)
+ {
+ objgrp->Change = TSL_STATE_CHANGED;
+ }
+ // Get object state mask from state machine in TSL_Params
+ objgrp_state_mask |= TSL_Params.p_LinRotSM[TSL_Globals.This_LinRot->p_Data->StateId].StateMask;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ pobj++; // Next object
+ }
+
+ // Update the object group state mask
+ objgrp->StateMask = objgrp_state_mask;
+}
+
+
+/**
+ * @brief Set the global object variable
+ * @param[in] pobj Pointer to the object to process
+ * @retval None
+ */
+void TSL_obj_SetGlobalObj(CONST TSL_Object_T *pobj)
+{
+
+ TSL_Globals.This_Obj = pobj;
+
+ switch (pobj->Type)
+ {
+#if TSLPRM_TOTAL_TKEYS > 0
+ case TSL_OBJ_TOUCHKEY:
+ case TSL_OBJ_TOUCHKEYB:
+ TSL_Globals.This_TKey = (TSL_TouchKey_T *)pobj->Elmt;
+ break;
+#endif
+#if TSLPRM_TOTAL_LNRTS > 0
+ case TSL_OBJ_LINEAR:
+ case TSL_OBJ_LINEARB:
+ case TSL_OBJ_ROTARY:
+ case TSL_OBJ_ROTARYB:
+ TSL_Globals.This_LinRot = (TSL_LinRot_T *)pobj->Elmt;
+ break;
+#endif
+ default:
+ break;
+ }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_time.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time.c
new file mode 100644
index 0000000..d274575
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time.c
@@ -0,0 +1,174 @@
+/**
+ ******************************************************************************
+ * @file tsl_time.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the timings in general.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_time.h"
+#include "tsl_globals.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Management of the timing module interrupt service routine.
+ * @param None
+ * @retval None
+ */
+void TSL_tim_ProcessIT(void)
+{
+ static TSL_tTick_ms_T count_1s = 0;
+
+ // Count 1 global tick every xxx ms (defined by TSLPRM_TICK_FREQ parameter)
+ TSL_Globals.Tick_ms++;
+
+ // Check if 1 second has elapsed
+ count_1s++;
+ if (count_1s > (TSLPRM_TICK_FREQ - 1))
+ {
+ TSL_Globals.Tick_sec++; // 1 global tick every second
+ if (TSL_Globals.Tick_sec > 63) // Due to DTO counter on 6 bits...
+ {
+ TSL_Globals.Tick_sec = 0;
+ }
+ count_1s = 0;
+ }
+
+// Callback function
+#if TSLPRM_USE_TIMER_CALLBACK > 0
+ TSL_CallBack_TimerTick();
+#endif
+
+}
+
+
+/**
+ * @brief Check if a delay (in ms) has elapsed.
+ * This function must be called regularly due to counter Roll-over only managed one time.
+ * @param[in] delay_ms Delay in ms
+ * @param[in] last_tick Variable holding the last tick value
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_tim_CheckDelay_ms(TSL_tTick_ms_T delay_ms, __IO TSL_tTick_ms_T *last_tick)
+{
+ TSL_tTick_ms_T tick;
+ TSL_tTick_ms_T diff;
+
+ disableInterrupts();
+
+ tick = TSL_Globals.Tick_ms;
+
+ if (delay_ms == 0)
+ {
+ enableInterrupts();
+ return TSL_STATUS_ERROR;
+ }
+
+ // Counter Roll-over management
+ if (tick >= *last_tick)
+ {
+ diff = tick - *last_tick;
+ }
+ else
+ {
+ diff = (0xFFFF - *last_tick) + tick + 1;
+ }
+
+#if (TSLPRM_TICK_FREQ == 125)
+ if (diff >= (TSL_tTick_ms_T)(delay_ms >> 3)) // Divide by 8 for 8ms tick
+#endif
+#if (TSLPRM_TICK_FREQ == 250)
+ if (diff >= (TSL_tTick_ms_T)(delay_ms >> 2)) // Divide by 4 for 4ms tick
+#endif
+#if (TSLPRM_TICK_FREQ == 500)
+ if (diff >= (TSL_tTick_ms_T)(delay_ms >> 1)) // Divide by 2 for 2ms tick
+#endif
+#if (TSLPRM_TICK_FREQ == 1000)
+ if (diff >= (TSL_tTick_ms_T)delay_ms) // Direct value for 1ms tick
+#endif
+#if (TSLPRM_TICK_FREQ == 2000)
+ if (diff >= (TSL_tTick_ms_T)(delay_ms << 1)) // Multiply by 2 for 0.5ms tick
+#endif
+ {
+ // Save current time
+ *last_tick = tick;
+ enableInterrupts();
+ return TSL_STATUS_OK;
+ }
+
+ enableInterrupts();
+ return TSL_STATUS_BUSY;
+
+}
+
+
+/**
+ * @brief Check if a delay (in s) has elapsed.
+ * @param[in] delay_sec Delay in seconds
+ * @param[in] last_tick Variable holding the last tick value
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_tim_CheckDelay_sec(TSL_tTick_sec_T delay_sec, __IO TSL_tTick_sec_T *last_tick)
+{
+ TSL_tTick_sec_T tick;
+ TSL_tTick_sec_T diff;
+
+ disableInterrupts();
+
+ tick = TSL_Globals.Tick_sec;
+
+ if (delay_sec == 0)
+ {
+ enableInterrupts();
+ return TSL_STATUS_ERROR;
+ }
+
+ // Counter Roll-over management
+ if (tick >= *last_tick)
+ {
+ diff = (TSL_tTick_sec_T)(tick - *last_tick);
+ }
+ else
+ {
+ diff = (TSL_tTick_sec_T)((63 - *last_tick) + tick + 1); // DTO counter is on 6 bits
+ }
+
+ if (diff >= delay_sec)
+ {
+ // Save current time
+ *last_tick = tick;
+ enableInterrupts();
+ return TSL_STATUS_OK;
+ }
+
+ enableInterrupts();
+ return TSL_STATUS_BUSY;
+
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f0xx.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f0xx.c
new file mode 100644
index 0000000..c44bb34
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f0xx.c
@@ -0,0 +1,104 @@
+/**
+ ******************************************************************************
+ * @file tsl_time_stm32f0xx.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the timing with STM32F0xx products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_time_stm32f0xx.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Initialization of the timing module.
+ * @param None
+ * @retval Status Return TSL_STATUS_ERROR if the Systick configuration has failed.
+ */
+TSL_Status_enum_T TSL_tim_Init(void)
+{
+ // Program one systick interrupt every (1 / TSLPRM_TICK_FREQ) ms
+// if (SysTick_Config(SystemCoreClock / TSLPRM_TICK_FREQ))
+// {
+// return TSL_STATUS_ERROR;
+// }
+// else
+// {
+// return TSL_STATUS_OK;
+// }
+
+ NVIC_InitTypeDef NVIC_InitStructure;
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+
+ /* TouchSense_TIMx clock enable */
+ TS_RCC_APBxPeriphClockCmd ( TS_TIM_RCC, ENABLE );
+
+ /* Enable the TouchSense_TIMx gloabal Interrupt */
+ NVIC_InitStructure.NVIC_IRQChannel = TS_TIM_IRQx;
+ NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init ( &NVIC_InitStructure );
+
+ /* -----------------------------------------------------------------------
+ In this example TIM7 counter clock (TIM7CLK) is set to APB1 clock (PCLK1), since
+ APB1 prescaler is set to 1 and TIM7 prescaler is set to 0.
+
+ In this example TIM7 input clock (TIM7CLK) is set to APB1 clock (PCLK1),
+ since APB1 prescaler is set to 1.
+ TIM7CLK = PCLK1 = HCLK = SystemCoreClock
+
+ With Prescaler set to 479 and Period to 24999, the TIM7 counter is updated each 250 ms
+ (i.e. and interrupt is generated each 250 ms)
+ TIM7 counter clock = TIM7CLK /((Prescaler + 1)*(Period + 1))
+ = 48 MHz / ((25000)*(480))
+ = 4 Hz
+ ==> TIM7 counter period = 250 ms
+
+ Note:
+ SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f0xx.c file.
+ Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
+ function to update SystemCoreClock variable value. Otherwise, any configuration
+ based on this variable will be incorrect.
+ ----------------------------------------------------------------------- */
+
+ /* Time base configuration */
+ TIM_TimeBaseStructure.TIM_Period = 1000; // //24999
+ TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock/1000000)-1; //479;
+ TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
+ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
+ TIM_TimeBaseInit ( TS_TIMx, &TIM_TimeBaseStructure );
+
+ /* TouchSense_TIMx Interrupts enable */
+ TIM_ITConfig ( TS_TIMx, TIM_IT_Update, ENABLE );
+
+ /* TouchSense_TIMx enable counter */
+ TIM_Cmd ( TS_TIMx, ENABLE );
+
+ return TSL_STATUS_OK;
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f3xx.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f3xx.c
new file mode 100644
index 0000000..15135e7
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32f3xx.c
@@ -0,0 +1,55 @@
+/**
+ ******************************************************************************
+ * @file tsl_time_stm32f3xx.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the timing with STM32F3xx products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_time_stm32f3xx.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Initialization of the timing module.
+ * @param None
+ * @retval Status Return TSL_STATUS_ERROR if the Systick configuration has failed.
+ */
+TSL_Status_enum_T TSL_tim_Init(void)
+{
+ // Program one systick interrupt every (1 / TSLPRM_TICK_FREQ) ms
+ if (SysTick_Config(SystemCoreClock / TSLPRM_TICK_FREQ))
+ {
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ return TSL_STATUS_OK;
+ }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32l1xx.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32l1xx.c
new file mode 100644
index 0000000..6dfe699
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm32l1xx.c
@@ -0,0 +1,55 @@
+/**
+ ******************************************************************************
+ * @file tsl_time_stm32l1xx.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the timing with STM32L1xx products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_time_stm32l1xx.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Initialization of the timing module.
+ * @param None
+ * @retval Status Return TSL_STATUS_ERROR if the Systick configuration has failed.
+ */
+TSL_Status_enum_T TSL_tim_Init(void)
+{
+ // Program one systick interrupt every (1 / TSLPRM_TICK_FREQ) ms
+ if (SysTick_Config(SystemCoreClock / TSLPRM_TICK_FREQ))
+ {
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ return TSL_STATUS_OK;
+ }
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8l.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8l.c
new file mode 100644
index 0000000..06904eb
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8l.c
@@ -0,0 +1,108 @@
+/**
+ ******************************************************************************
+ * @file tsl_time_stm8l.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the timing with STM8L products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_time_stm8l.h"
+#include "tsl_time.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+
+/**
+ * @brief Initialization of the timing module.
+ * @param None
+ * @retval Status Return TSL_STATUS_ERROR if the clock divider is wrong
+ */
+TSL_Status_enum_T TSL_tim_Init(void)
+{
+ // Enable TIM4 clock
+#if defined(STM8L10X)
+ CLK->PCKENR |= CLK_PCKENR_TIM4;
+#else // STM8L15X
+ CLK->PCKENR1 |= CLK_PCKENR1_TIM4;
+#endif
+
+ if (CLK->CKDIVR != 0x00) // Warning: The CPU frequency must be equal to 16 MHz
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ TIM4->SR1 = 0; // Clear overflow flag
+
+#if (TSLPRM_TICK_FREQ == 2000)
+ TIM4->PSCR = 6; // 16 MHz / 64 = 4 us clock
+ TIM4->ARR = 124; // 125 * 4 us = 0.5 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 1000)
+ TIM4->PSCR = 6; // 16 MHz / 64 = 4 us clock
+ TIM4->ARR = 249; // 250 * 4 us = 1 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 500)
+ TIM4->PSCR = 8; // 16 MHz / 256 = 16 us clock
+ TIM4->ARR = 124; // 125 * 16 us = 2 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 250)
+ TIM4->PSCR = 8; // 16 MHz / 256 = 16 us clock
+ TIM4->ARR = 249; // 250 * 16 us = 4 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 125)
+ TIM4->PSCR = 10; // 16 MHz / 1024 = 64 us clock
+ TIM4->ARR = 124; // 125 * 64 us = 8 ms
+#endif
+
+ TIM4->IER = 0x01; // Enable interrupt
+ TIM4->CR1 = 0x01; // Start timer
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Interrupt handler for TIM4 dedicated to ECS
+ * @param None
+ * @retval None
+ */
+#if defined(_COSMIC_)
+// 'svlreg option' is added to force the saving of the virtual long register
+@svlreg INTERRUPT_HANDLER(TSL_Timer_ISR, 25)
+#else
+INTERRUPT_HANDLER(TSL_Timer_ISR, 25)
+#endif
+{
+ TIM4->SR1 &= (uint8_t)(~TIM4_SR1_UIF);
+ TSL_tim_ProcessIT();
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8tl5x.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8tl5x.c
new file mode 100644
index 0000000..143ba5d
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_time_stm8tl5x.c
@@ -0,0 +1,104 @@
+/**
+ ******************************************************************************
+ * @file tsl_time_stm8tl5x.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage the timing with STM8TL5x products.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_time_stm8tl5x.h"
+#include "tsl_time.h"
+#include "stm8tl5x_it.h"
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+/* Private macros ------------------------------------------------------------*/
+/* Private variables ---------------------------------------------------------*/
+/* Private functions prototype -----------------------------------------------*/
+
+/**
+ * @brief Initialization of the timing module to generate periodic interruptions
+ * @warning The CPU frequency must be equal to 16 MHz
+ * @param None
+ * @retval Status Return TSL_STATUS_ERROR if the CPU freq in uncorrect.
+ */
+TSL_Status_enum_T TSL_tim_Init(void)
+{
+ CLK->PCKENR1 |= CLK_PCKENR1_TIM4; // The peripheral clock are not enable by default
+
+ if (CLK->CKDIVR != 0x00) // The CPU frequency must be equal to 16 MHz
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ TIM4->SR1 = 0; // Clear overflow flag
+
+#if (TSLPRM_TICK_FREQ == 2000)
+ TIM4->PSCR = 6; // 16 MHz / 64 = 4 us clock
+ TIM4->ARR = 124; // 125 * 4 us = 0.5 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 1000)
+ TIM4->PSCR = 6; // 16 MHz / 64 = 4 us clock
+ TIM4->ARR = 249; // 250 * 4 us = 1 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 500)
+ TIM4->PSCR = 8; // 16 MHz / 256 = 16 us clock
+ TIM4->ARR = 124; // 125 * 16 us = 2 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 250)
+ TIM4->PSCR = 8; // 16 MHz / 256 = 16 us clock
+ TIM4->ARR = 249; // 250 * 16 us = 4 ms
+#endif
+
+#if (TSLPRM_TICK_FREQ == 125)
+ TIM4->PSCR = 10; // 16 MHz / 1024 = 64 us clock
+ TIM4->ARR = 124; // 125 * 64 us = 8 ms
+#endif
+
+ TIM4->IER = 0x01; // Enable interrupt
+ TIM4->CR1 = 0x01; // Start timer
+
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Interrupt handler for TIM4 dedicated to ECS
+ * @param None
+ * @retval None
+ */
+#if defined(_COSMIC_)
+// 'svlreg option' is added to force the saving of the virtual long register
+@svlreg INTERRUPT_HANDLER(TSL_Timer_ISR, 25)
+#else
+INTERRUPT_HANDLER(TSL_Timer_ISR, 25)
+#endif
+{
+ TIM4->SR1 &= (uint8_t)(~TIM4_SR1_UIF);
+ TSL_tim_ProcessIT();
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/Libraries/TouchSense/STMTouch_Driver/src/tsl_touchkey.c b/Libraries/TouchSense/STMTouch_Driver/src/tsl_touchkey.c
new file mode 100644
index 0000000..c419e7c
--- /dev/null
+++ b/Libraries/TouchSense/STMTouch_Driver/src/tsl_touchkey.c
@@ -0,0 +1,1089 @@
+/**
+ ******************************************************************************
+ * @file tsl_touchkey.c
+ * @author MCD Application Team
+ * @version V1.4.4
+ * @date 31-March-2014
+ * @brief This file contains all functions to manage TouchKey sensors.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_touchkey.h"
+#include "tsl_globals.h"
+
+#if TSLPRM_TOTAL_TKEYS > 0
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+
+#define THIS_MEAS TSL_Globals.This_TKey->p_ChD->Meas
+#define THIS_DELTA TSL_Globals.This_TKey->p_ChD->Delta
+#define THIS_REF TSL_Globals.This_TKey->p_ChD->Ref
+#define THIS_REFREST TSL_Globals.This_TKey->p_ChD->RefRest
+#define THIS_CHANNEL_DATA TSL_Globals.This_TKey->p_ChD
+#define THIS_ACQ_STATUS TSL_Globals.This_TKey->p_ChD->Flags.AcqStatus
+#define THIS_OBJ_STATUS TSL_Globals.This_TKey->p_ChD->Flags.ObjStatus
+#define THIS_DATA_READY TSL_Globals.This_TKey->p_ChD->Flags.DataReady
+
+#define THIS_STATEID TSL_Globals.This_TKey->p_Data->StateId
+#define THIS_CHANGE TSL_Globals.This_TKey->p_Data->Change
+#define THIS_COUNTER_DEB TSL_Globals.This_TKey->p_Data->CounterDebounce
+#define THIS_COUNTER_DTO TSL_Globals.This_TKey->p_Data->CounterDTO
+#define THIS_DXSLOCK TSL_Globals.This_TKey->p_Data->DxSLock
+
+#define THIS_PROXIN_TH TSL_Globals.This_TKey->p_Param->ProxInTh
+#define THIS_PROXOUT_TH TSL_Globals.This_TKey->p_Param->ProxOutTh
+#define THIS_DETECTIN_TH TSL_Globals.This_TKey->p_Param->DetectInTh
+#define THIS_DETECTOUT_TH TSL_Globals.This_TKey->p_Param->DetectOutTh
+#define THIS_CALIB_TH TSL_Globals.This_TKey->p_Param->CalibTh
+
+#define THIS_COUNTER_DEB_CALIB TSL_Globals.This_TKey->p_Param->CounterDebCalib
+#define THIS_COUNTER_DEB_PROX TSL_Globals.This_TKey->p_Param->CounterDebProx
+#define THIS_COUNTER_DEB_DETECT TSL_Globals.This_TKey->p_Param->CounterDebDetect
+#define THIS_COUNTER_DEB_RELEASE TSL_Globals.This_TKey->p_Param->CounterDebRelease
+#define THIS_COUNTER_DEB_ERROR TSL_Globals.This_TKey->p_Param->CounterDebError
+
+#if TSLPRM_DTO > 0
+#define DTO_GET_TIME {TSL_tkey_DTOGetTime();}
+#else
+#define DTO_GET_TIME
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+#define TEST_DELTA(OPER,TH) (THIS_DELTA OPER (uint16_t)((uint16_t)TH << TSLPRM_COEFF_TH))
+#define TEST_DELTA_N(OPER,TH) (THIS_DELTA OPER -((uint16_t)((uint16_t)TH << TSLPRM_COEFF_TH)))
+#define TEST_DELTA_NEGATIVE {if (THIS_DELTA < 0) {return;}}
+#else
+#define TEST_DELTA(OPER,TH) (THIS_DELTA OPER TH)
+#define TEST_DELTA_N(OPER,TH) (THIS_DELTA OPER -(TH))
+#define TEST_DELTA_NEGATIVE
+#endif
+
+/* Private variables ---------------------------------------------------------*/
+
+static TSL_tNb_T CalibDiv;
+
+/* Private functions prototype -----------------------------------------------*/
+
+void TSL_tkey_DTOGetTime(void);
+
+
+//==============================================================================
+// "Object methods" functions
+//==============================================================================
+
+/**
+ * @brief Init parameters with default values from configuration file
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_Init(void)
+{
+ // Thresholds
+#if TSLPRM_USE_PROX > 0
+ THIS_PROXIN_TH = TSLPRM_TKEY_PROX_IN_TH;
+ THIS_PROXOUT_TH = TSLPRM_TKEY_PROX_OUT_TH;
+#endif
+ THIS_DETECTIN_TH = TSLPRM_TKEY_DETECT_IN_TH;
+ THIS_DETECTOUT_TH = TSLPRM_TKEY_DETECT_OUT_TH;
+ THIS_CALIB_TH = TSLPRM_TKEY_CALIB_TH;
+
+ // Debounce counters
+ THIS_COUNTER_DEB_CALIB = TSLPRM_DEBOUNCE_CALIB;
+#if TSLPRM_USE_PROX > 0
+ THIS_COUNTER_DEB_PROX = TSLPRM_DEBOUNCE_PROX;
+#endif
+ THIS_COUNTER_DEB_DETECT = TSLPRM_DEBOUNCE_DETECT;
+ THIS_COUNTER_DEB_RELEASE = TSLPRM_DEBOUNCE_RELEASE;
+ THIS_COUNTER_DEB_ERROR = TSLPRM_DEBOUNCE_ERROR;
+
+ // Initial state
+ TSL_tkey_SetStateCalibration(TSLPRM_CALIB_DELAY);
+}
+
+
+/**
+ * @brief Process the State Machine
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_Process(void)
+{
+ TSL_StateId_enum_T prev_state_id;
+
+ if ((THIS_DATA_READY != 0) || (THIS_STATEID == TSL_STATEID_OFF))
+ {
+
+ THIS_DATA_READY = TSL_DATA_NOT_READY; // The new data is processed
+
+ prev_state_id = THIS_STATEID;
+
+#if TSLPRM_TOTAL_TOUCHKEYS > 0
+ if (TSL_Globals.This_Obj->Type == TSL_OBJ_TOUCHKEY)
+ {
+ // Launch the TKey state function
+ TSL_Globals.This_TKey->p_SM[THIS_STATEID].StateFunc();
+ }
+#endif
+
+#if TSLPRM_TOTAL_TOUCHKEYS_B > 0
+ if (TSL_Globals.This_Obj->Type == TSL_OBJ_TOUCHKEYB)
+ {
+ // Launch the TSL_Params state function
+ TSL_Params.p_TKeySM[THIS_STATEID].StateFunc();
+ }
+#endif
+
+ // Check if the new state has changed
+ if (THIS_STATEID == prev_state_id)
+ {
+ THIS_CHANGE = TSL_STATE_NOT_CHANGED;
+ }
+ else
+ {
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ }
+
+#if TSLPRM_USE_DXS > 0
+ if (THIS_STATEID != TSL_STATEID_DETECT)
+ {
+ THIS_DXSLOCK = TSL_FALSE;
+ }
+ if (THIS_STATEID == TSL_STATEID_TOUCH)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+#endif
+
+ }
+}
+
+
+//==============================================================================
+// Utility functions
+//==============================================================================
+
+/**
+ * @brief Go in Calibration state
+ * @param[in] delay Delay before calibration starts (stabilization of noise filter)
+ * @retval None
+ */
+void TSL_tkey_SetStateCalibration(TSL_tCounter_T delay)
+{
+ THIS_STATEID = TSL_STATEID_CALIB;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ THIS_OBJ_STATUS = TSL_OBJ_STATUS_ON;
+
+ switch (TSL_Params.NbCalibSamples)
+ {
+ case 4:
+ CalibDiv = 2;
+ break;
+ case 16:
+ CalibDiv = 4;
+ break;
+ default:
+ TSL_Params.NbCalibSamples = 8;
+ CalibDiv = 3;
+ break;
+ }
+
+ // If a noise filter is used, the counter must be initialized to a value
+ // different from 0 in order to stabilize the filter.
+ THIS_COUNTER_DEB = (TSL_tCounter_T)(delay + (TSL_tCounter_T)TSL_Params.NbCalibSamples);
+ THIS_REF = 0;
+}
+
+
+/**
+ * @brief Go in Off state with sensor "off"
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_SetStateOff(void)
+{
+ THIS_STATEID = TSL_STATEID_OFF;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ THIS_OBJ_STATUS = TSL_OBJ_STATUS_OFF;
+}
+
+
+#if !defined(TSLPRM_STM8TL5X) && !defined(STM8TL5X)
+/**
+ * @brief Go in Off state with sensor in "Burst mode only"
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_SetStateBurstOnly(void)
+{
+ THIS_STATEID = TSL_STATEID_OFF;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ THIS_OBJ_STATUS = TSL_OBJ_STATUS_BURST_ONLY;
+}
+#endif
+
+
+/**
+ * @brief Return the current state identifier
+ * @param None
+ * @retval State id
+ */
+TSL_StateId_enum_T TSL_tkey_GetStateId(void)
+{
+ return(THIS_STATEID);
+}
+
+
+/**
+ * @brief Return the current state mask
+ * @param None
+ * @retval State mask
+ */
+TSL_StateMask_enum_T TSL_tkey_GetStateMask(void)
+{
+ TSL_StateMask_enum_T state_mask = TSL_STATEMASK_UNKNOWN;
+
+#if TSLPRM_TOTAL_TOUCHKEYS > 0
+ if (TSL_Globals.This_Obj->Type == TSL_OBJ_TOUCHKEY)
+ {
+ state_mask = TSL_Globals.This_TKey->p_SM[THIS_STATEID].StateMask;
+ }
+#endif
+
+#if TSLPRM_TOTAL_TOUCHKEYS_B > 0
+ if (TSL_Globals.This_Obj->Type == TSL_OBJ_TOUCHKEYB)
+ {
+ state_mask = TSL_Params.p_TKeySM[THIS_STATEID].StateMask;
+ }
+#endif
+
+ return state_mask;
+}
+
+
+/**
+ * @brief Return the Change flag
+ * @param None
+ * @retval Change flag status
+ */
+TSL_tNb_T TSL_tkey_IsChanged(void)
+{
+ return(THIS_CHANGE);
+}
+
+
+//==============================================================================
+// State machine functions
+//==============================================================================
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Release processing (previous state = Proximity)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebReleaseProxStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_PROX; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ THIS_STATEID = TSL_STATEID_PROX; // Go back to the previous state
+ }
+ else
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+#endif // if TSLPRM_USE_PROX > 0
+
+
+/**
+ * @brief Debounce Release processing (previous state = Detect)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebReleaseDetectStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>, THIS_DETECTOUT_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ return;
+ }
+#endif
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+
+
+/**
+ * @brief Debounce Release processing (previous state = Touch)
+ * Same as Debounce Release Detect processing
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebReleaseTouchStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>, THIS_DETECTOUT_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ return;
+ }
+#endif
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+
+
+/**
+ * @brief Release state processing
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_ReleaseStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_RELEASE;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>=, THIS_DETECTIN_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (THIS_DELTA >= THIS_PROXIN_TH)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX;
+ }
+ return;
+ }
+#endif
+
+ // Check delta for re-calibration
+ // Warning: the threshold value is inverted in the macro
+ if TEST_DELTA_N(<=, THIS_CALIB_TH)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_CALIB;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ TSL_tkey_SetStateCalibration(0);
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_CALIB;
+ }
+ }
+ }
+}
+
+
+/**
+ * @brief Debounce Calibration processing (previous state = Release)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebCalibrationStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ // Still below recalibration threshold
+ // Warning: the threshold value is inverted in the macro
+ if TEST_DELTA_N(<=, THIS_CALIB_TH)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ TSL_tkey_SetStateCalibration(0);
+ }
+ // else stay in Debounce Calibration
+ }
+ else // Go back to previous state
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+
+
+/**
+ * @brief Calibration state processing
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_CalibrationStateProcess(void)
+{
+ TSL_tMeas_T new_meas;
+
+#if TSLPRM_CALIB_DELAY > 0
+ // Noise filter stabilization time
+ if (THIS_COUNTER_DEB > (TSL_tCounter_T)TSL_Params.NbCalibSamples)
+ {
+ THIS_COUNTER_DEB--;
+ return; // Skip the sample
+ }
+#endif
+
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_CALIB;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+
+ // Get the new measure or Calculate it
+#if TSLPRM_USE_MEAS > 0
+ new_meas = THIS_MEAS;
+#else // Calculate it
+ new_meas = TSL_acq_ComputeMeas(THIS_REF, THIS_DELTA);
+#endif
+
+ // Verify the first Reference value
+ if (THIS_COUNTER_DEB == (TSL_tCounter_T)TSL_Params.NbCalibSamples)
+ {
+ if (TSL_acq_TestFirstReferenceIsValid(THIS_CHANNEL_DATA, new_meas))
+ {
+ THIS_REF = new_meas;
+ }
+ else
+ {
+ THIS_REF = 0;
+ return;
+ }
+ }
+ else
+ {
+ // Add the measure in temporary Reference
+ THIS_REF += new_meas;
+
+ // Check reference overflow
+ if (THIS_REF < new_meas)
+ {
+ THIS_REF = 0; // Suppress the bad reference
+ THIS_STATEID = TSL_STATEID_ERROR;
+ return;
+ }
+ }
+
+ // Check that we have all the needed measurements
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ // Divide temporary Reference by the number of samples
+ THIS_REF >>= CalibDiv;
+ THIS_REFREST = 0;
+ THIS_DELTA = 0;
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Release)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebProxStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>=, THIS_DETECTIN_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+ if (THIS_DELTA >= THIS_PROXIN_TH)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Detect)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebProxDetectStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>, THIS_DETECTOUT_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_STATEID = TSL_STATEID_DETECT;
+ return;
+ }
+
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_DETECT;
+ }
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Touch)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebProxTouchStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>, THIS_DETECTOUT_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ return;
+ }
+
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_TOUCH;
+ }
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Proximity state processing
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_ProxStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_PROX;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>=, THIS_DETECTIN_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+ if (THIS_DELTA <= THIS_PROXOUT_TH)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_PROX;
+ }
+ return;
+ }
+
+ // Stay in Proximity state
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ //------------------------------------
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_tkey_SetStateCalibration(0);
+ }
+ }
+#endif
+
+ }
+}
+#endif
+
+
+/**
+ * @brief Debounce Detect processing (previous state = Release or Proximity)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebDetectStateProcess(void)
+{
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>=, THIS_DETECTIN_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Detect
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (THIS_DELTA >= THIS_PROXIN_TH)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX;
+ }
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+#else
+ THIS_STATEID = TSL_STATEID_RELEASE;
+#endif
+ }
+ }
+}
+
+
+/**
+ * @brief Detect state processing
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DetectStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_DETECT;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>, THIS_DETECTOUT_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ //------------------------------------
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_tkey_SetStateCalibration(0);
+ }
+ }
+#endif
+ return; // Normal operation, stay in Detect state
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX_DETECT;
+ }
+ return;
+ }
+#endif
+
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_DETECT;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Touch state processing
+ * Same as Detect state
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_TouchStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_TOUCH;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if TEST_DELTA(>, THIS_DETECTOUT_TH)
+ {
+ TEST_DELTA_NEGATIVE;
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ //------------------------------------
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_tkey_SetStateCalibration(0);
+ }
+ }
+#endif
+ return; // Normal operation, stay in Touch state
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (THIS_DELTA > THIS_PROXOUT_TH)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX_TOUCH;
+ }
+ return;
+ }
+#endif
+
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_TOUCH;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Debounce error state processing
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DebErrorStateProcess(void)
+{
+ volatile TSL_StateMask_enum_T mask;
+
+ if (THIS_ACQ_STATUS & TSL_ACQ_STATUS_ERROR_MASK) // Acquisition error (min or max)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ // Get state mask
+ mask = TSL_tkey_GetStateMask();
+ // Mask Error and Debounce bits
+#ifdef _RAISONANCE_
+ mask &= ~(TSL_STATE_DEBOUNCE_BIT_MASK | TSL_STATE_ERROR_BIT_MASK);
+#else
+ mask &= (TSL_StateMask_enum_T)(~(TSL_STATE_DEBOUNCE_BIT_MASK | TSL_STATE_ERROR_BIT_MASK));
+#endif
+ // Go back to the previous state
+ switch (mask)
+ {
+ case TSL_STATEMASK_RELEASE :
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ break;
+ case TSL_STATEMASK_PROX :
+ THIS_STATEID = TSL_STATEID_PROX;
+ break;
+ case TSL_STATEMASK_DETECT :
+ THIS_STATEID = TSL_STATEID_DETECT;
+ break;
+ case TSL_STATEMASK_TOUCH :
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ break;
+ default:
+ TSL_tkey_SetStateCalibration(0);
+ break;
+ }
+ }
+}
+
+
+//==============================================================================
+// Private functions
+//==============================================================================
+
+/**
+ * @brief Get the current time in second and affect it to the DTO counter (Private)
+ * @param None
+ * @retval None
+ */
+void TSL_tkey_DTOGetTime(void)
+{
+ disableInterrupts();
+ THIS_COUNTER_DTO = (TSL_tCounter_T)TSL_Globals.Tick_sec;
+ enableInterrupts();
+}
+
+#endif
+// #if TSLPRM_TOTAL_TKEYS > 0
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/