diff options
Diffstat (limited to 'Libraries/TouchSense/STMTouch_Driver/src')
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>© 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>© 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>© 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: ~ 53µs + * val = 1000: ~106µs + * val = 2000: ~210µs + */ +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>© 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: ~ 63µs + * val = 1000: ~126µs + * val = 2000: ~251µs + */ +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>© 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 = ~1µs, 50 = ~14µs, 100 = ~25µs, 200 = ~50µs + * @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>© 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); // ~14µs 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 = ~1µs, 50 = ~14µs, 100 = ~25µs, 200 = ~50µs + * @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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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****/ |