diff options
author | Alexander <trotsenkoa@gmail.com> | 2022-06-29 11:03:02 +0300 |
---|---|---|
committer | Alexander <trotsenkoa@gmail.com> | 2022-06-29 11:03:02 +0300 |
commit | 1702ce6ce430a66bb7af51644b91b7c196e719d9 (patch) | |
tree | 6039acbdf047873d32aaf55969286c5f0d55958f /Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c |
Создаю новый репозиторий. Программа для версии NixieClock_v2. Работает, часы тикают. Есть проблема, что скачет вторая сеносрная кнопка (она в другом канале). Поэтому на нее собираюсь сделать антидребезг.
Diffstat (limited to 'Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c')
-rw-r--r-- | Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c | 2103 |
1 files changed, 2103 insertions, 0 deletions
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****/ |