summaryrefslogtreecommitdiff
path: root/Libraries/TouchSense/STMTouch_Driver/src/tsl_linrot.c
diff options
context:
space:
mode:
authorAlexander <trotsenkoa@gmail.com>2022-06-29 11:03:02 +0300
committerAlexander <trotsenkoa@gmail.com>2022-06-29 11:03:02 +0300
commit1702ce6ce430a66bb7af51644b91b7c196e719d9 (patch)
tree6039acbdf047873d32aaf55969286c5f0d55958f /Libraries/TouchSense/STMTouch_Driver/src/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.c2103
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>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
+ *
+ * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.st.com/software_license_agreement_liberty_v2
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************
+ */
+
+/* Includes ------------------------------------------------------------------*/
+#include "tsl_linrot.h"
+#include "tsl_globals.h"
+
+#if TSLPRM_TOTAL_LNRTS > 0
+
+/* Private typedefs ----------------------------------------------------------*/
+/* Private defines -----------------------------------------------------------*/
+
+/* Private macros ------------------------------------------------------------*/
+
+#define THIS_OBJ_TYPE TSL_Globals.This_Obj->Type
+
+#define THIS_STATEID TSL_Globals.This_LinRot->p_Data->StateId
+#define THIS_RAW_POSITION TSL_Globals.This_LinRot->p_Data->RawPosition
+#define THIS_POSITION TSL_Globals.This_LinRot->p_Data->Position
+#define THIS_CHANGE TSL_Globals.This_LinRot->p_Data->Change
+#define THIS_POSCHANGE TSL_Globals.This_LinRot->p_Data->PosChange
+#define THIS_COUNTER_DEB TSL_Globals.This_LinRot->p_Data->CounterDebounce
+#define THIS_COUNTER_DIR TSL_Globals.This_LinRot->p_Data->CounterDirection
+#define THIS_COUNTER_DTO TSL_Globals.This_LinRot->p_Data->CounterDTO
+#define THIS_DXSLOCK TSL_Globals.This_LinRot->p_Data->DxSLock
+#define THIS_DIRECTION TSL_Globals.This_LinRot->p_Data->Direction
+
+#define THIS_PROXIN_TH TSL_Globals.This_LinRot->p_Param->ProxInTh
+#define THIS_PROXOUT_TH TSL_Globals.This_LinRot->p_Param->ProxOutTh
+#define THIS_DETECTIN_TH TSL_Globals.This_LinRot->p_Param->DetectInTh
+#define THIS_DETECTOUT_TH TSL_Globals.This_LinRot->p_Param->DetectOutTh
+#define THIS_CALIB_TH TSL_Globals.This_LinRot->p_Param->CalibTh
+
+#define THIS_RESOLUTION TSL_Globals.This_LinRot->p_Param->Resolution
+#define THIS_DIR_CHG_POS TSL_Globals.This_LinRot->p_Param->DirChangePos
+
+#define THIS_COUNTER_DEB_CALIB TSL_Globals.This_LinRot->p_Param->CounterDebCalib
+#define THIS_COUNTER_DEB_PROX TSL_Globals.This_LinRot->p_Param->CounterDebProx
+#define THIS_COUNTER_DEB_DETECT TSL_Globals.This_LinRot->p_Param->CounterDebDetect
+#define THIS_COUNTER_DEB_RELEASE TSL_Globals.This_LinRot->p_Param->CounterDebRelease
+#define THIS_COUNTER_DEB_ERROR TSL_Globals.This_LinRot->p_Param->CounterDebError
+#define THIS_COUNTER_DEB_DIRECTION TSL_Globals.This_LinRot->p_Param->CounterDebDirection
+
+#define THIS_NB_CHANNELS TSL_Globals.This_LinRot->NbChannels
+#define THIS_SCT_COMP TSL_Globals.This_LinRot->SctComp
+#define THIS_POS_CORR TSL_Globals.This_LinRot->PosCorr
+
+#if TSLPRM_DTO > 0
+#define DTO_GET_TIME {TSL_linrot_DTOGetTime();}
+#else
+#define DTO_GET_TIME
+#endif
+
+/* Private variables ---------------------------------------------------------*/
+
+//================================================================
+// See AN2869 for more details on Linear and Rotary sensors design
+//================================================================
+
+//==============================================================================
+// 3 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3
+//==============================================================================
+#if TSLPRM_USE_3CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_LIN_M1[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -96, 0 }, // maj = 1; i = 0
+ { 32, 0, -160 }, // maj = 2; i = 1
+ { 0, 96, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 3 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3
+//==============================================================================
+#if TSLPRM_USE_3CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_LIN_M2[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -192, 0 }, // maj = 1; i = 0
+ { 64, 0, -320 }, // maj = 2; i = 1
+ { 0, 192, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 3 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH1
+//==============================================================================
+#if TSLPRM_USE_3CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_LIN_H[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -96, 160 }, // maj = 1; i = 0
+ { 32, 0, -160 }, // maj = 2; i = 1
+ { -224, 96, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 3 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3
+//==============================================================================
+#if TSLPRM_USE_3CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_3CH_ROT_M[3][3] =
+{
+// sec = 1 2 3
+// j = 0 1 2
+ { 0, -64, 107 }, // maj = 1; i = 0
+ { 21, 0, -107 }, // maj = 2; i = 1
+ { -149, 64, 0 } // maj = 3; i = 2
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3 CH4
+//==============================================================================
+#if TSLPRM_USE_4CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_LIN_M1[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -64, 0, 0 }, // maj = 1; i = 0
+ { 21, 0, -107, 0 }, // maj = 2; i = 1
+ { 0, 64, 0, -149 }, // maj = 3; i = 2
+ { 0, 0, 107, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3 CH4
+//==============================================================================
+#if TSLPRM_USE_4CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_LIN_M2[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -96, 0, 0 }, // maj = 1; i = 0
+ { 32, 0, -160, 0 }, // maj = 2; i = 1
+ { 0, 96, 0, -224 }, // maj = 3; i = 2
+ { 0, 0, 160, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH4 CH1
+//==============================================================================
+#if TSLPRM_USE_4CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_LIN_H[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -64, 0, 149 }, // maj = 1; i = 0
+ { 21, 0, -107, 0 }, // maj = 2; i = 1
+ { 0, 64, 0, -149 }, // maj = 3; i = 2
+ { -192, 0, 107, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 4 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3 CH4
+//==============================================================================
+#if TSLPRM_USE_4CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_4CH_ROT_M[4][4] =
+{
+// sec = 1 2 3 4
+// j = 0 1 2 3
+ { 0, -48, 0, 112 }, // maj = 1; i = 0
+ { 16, 0, -80, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112 }, // maj = 3; i = 2
+ { -144, 0, 80, 0 } // maj = 4; i = 3
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3 CH4 CH5
+//==============================================================================
+#if TSLPRM_USE_5CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_LIN_M1[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -48, 0, 0, 0 }, // maj = 1; i = 0
+ { 16, 0, -80, 0, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112, 0 }, // maj = 3; i = 2
+ { 0, 0, 80, 0, -144 }, // maj = 4; i = 3
+ { 0, 0, 0, 112, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5
+//==============================================================================
+#if TSLPRM_USE_5CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_LIN_M2[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -64, 0, 0, 0 }, // maj = 1; i = 0
+ { 21, 0, -107, 0, 0 }, // maj = 2; i = 1
+ { 0, 64, 0, -149, 0 }, // maj = 3; i = 2
+ { 0, 0, 107, 0, -192 }, // maj = 4; i = 3
+ { 0, 0, 0, 149, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH4 CH5 CH1
+//==============================================================================
+#if TSLPRM_USE_5CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_LIN_H[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -48, 0, 0, 144 }, // maj = 1; i = 0
+ { 16, 0, -80, 0, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112, 0 }, // maj = 3; i = 2
+ { 0, 0, 80, 0, -144 }, // maj = 4; i = 3
+ { -176, 0, 0, 112, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5
+//==============================================================================
+#if TSLPRM_USE_5CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_ROT_M[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -38, 0, 0, 115 }, // maj = 1; i = 0
+ { 13, 0, -64, 0, 0 }, // maj = 2; i = 1
+ { 0, 38, 0, -90, 0 }, // maj = 3; i = 2
+ { 0, 0, 64, 0, -115 }, // maj = 4; i = 3
+ {-141, 0, 0, 90, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 5 CHANNELS - ROTARY - DUAL
+// i.e. CH1 CH2 CH3 CH4 CH5 CH1 CH3 CH5 CH2 CH4
+//==============================================================================
+#if TSLPRM_USE_5CH_ROT_D > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_5CH_ROT_D[5][5] =
+{
+// sec = 1 2 3 4 5
+// j = 0 1 2 3 4
+ { 0, -19, -83, 122, 58 }, // maj = 1; i = 0
+ { 6, 0, -32, -122, 96 }, // maj = 2; i = 1
+ { 70, 19, 0, -45, -96 }, // maj = 3; i = 2
+ {-134, 109, 32, 0, -58 }, // maj = 4; i = 3
+ { -70, -109, 83, 45, 0 } // maj = 5; i = 4
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - LINEAR - MONO - 0/255 at extremities
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6
+//==============================================================================
+#if TSLPRM_USE_6CH_LIN_M1 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_LIN_M1[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -38, 0, 0, 0, 0 }, // maj = 1; i = 0
+ { 13, 0, -64, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 38, 0, -90, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 64, 0, -115, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 90, 0, -141 }, // maj = 5; i = 4
+ { 0, 0, 0, 0, 115, 0 } // maj = 6; i = 5
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - LINEAR - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6
+//==============================================================================
+#if TSLPRM_USE_6CH_LIN_M2 > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_LIN_M2[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -48, 0, 0, 0, 0 }, // maj = 1; i = 0
+ { 16, 0, -80, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 48, 0, -112, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 80, 0, -144, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 112, 0, -176 }, // maj = 5; i = 4
+ { 0, 0, 0, 0, 144, 0 } // maj = 6; i = 5
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - LINEAR - HALF-ENDED
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6 CH1
+//==============================================================================
+#if TSLPRM_USE_6CH_LIN_H > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_LIN_H[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -38, 0, 0, 0, 141 }, // maj = 1; i = 0
+ { 13, 0, -64, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 38, 0, -90, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 64, 0, -115, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 90, 0, -141 }, // maj = 5; i = 4
+ {-166, 0, 0, 0, 115, 0 } // maj = 6; i = 5
+};
+#endif
+
+//==============================================================================
+// 6 CHANNELS - ROTARY - MONO
+// i.e. CH1 CH2 CH3 CH4 CH5 CH6
+//==============================================================================
+#if TSLPRM_USE_6CH_ROT_M > 0
+CONST TSL_tsignPosition_T TSL_POSOFF_6CH_ROT_M[6][6] =
+{
+// sec = 1 2 3 4 5 6
+// j = 0 1 2 3 4 5
+ { 0, -32, 0, 0, 0, 117 }, // maj = 1; i = 0
+ { 11, 0, -53, 0, 0, 0 }, // maj = 2; i = 1
+ { 0, 32, 0, -75, 0, 0 }, // maj = 3; i = 2
+ { 0, 0, 53, 0, -96, 0 }, // maj = 4; i = 3
+ { 0, 0, 0, 75, 0, -117 }, // maj = 5; i = 4
+ {-139, 0, 0, 0, 96, 0 } // maj = 6; i = 5
+};
+#endif
+
+//------------------
+// Common parameters
+//------------------
+
+#define DIRECTION_CHANGE_MAX_DISPLACEMENT (255)
+#define DIRECTION_CHANGE_TOTAL_STEPS (256)
+#define RESOLUTION_CALCULATION (8)
+
+static TSL_tNb_T CalibDiv;
+
+/* Private functions prototype -----------------------------------------------*/
+
+void TSL_linrot_DTOGetTime(void);
+void TSL_linrot_ProcessCh_All_SetStatus(TSL_ObjStatus_enum_T sts);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DataReady(void);
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_AcqStatus(TSL_AcqStatus_enum_T sts);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_AcqStatusError(void);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAboveEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAbove(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_DeltaBelowEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff);
+void TSL_linrot_ProcessCh_All_ClearRef(void);
+TSL_tDelta_T TSL_linrot_NormDelta(TSL_ChannelData_T *ch, TSL_tIndex_T idx);
+
+
+//==============================================================================
+// "Object methods" functions
+//==============================================================================
+
+/**
+ * @brief Init parameters with default values from configuration file
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_Init(void)
+{
+ // Thresholds
+#if TSLPRM_USE_PROX > 0
+ THIS_PROXIN_TH = TSLPRM_LINROT_PROX_IN_TH;
+ THIS_PROXOUT_TH = TSLPRM_LINROT_PROX_OUT_TH;
+#endif
+ THIS_DETECTIN_TH = TSLPRM_LINROT_DETECT_IN_TH;
+ THIS_DETECTOUT_TH = TSLPRM_LINROT_DETECT_OUT_TH;
+ THIS_CALIB_TH = TSLPRM_LINROT_CALIB_TH;
+
+ // Debounce counters
+ THIS_COUNTER_DEB_CALIB = TSLPRM_DEBOUNCE_CALIB;
+#if TSLPRM_USE_PROX > 0
+ THIS_COUNTER_DEB_PROX = TSLPRM_DEBOUNCE_PROX;
+#endif
+ THIS_COUNTER_DEB_DETECT = TSLPRM_DEBOUNCE_DETECT;
+ THIS_COUNTER_DEB_RELEASE = TSLPRM_DEBOUNCE_RELEASE;
+ THIS_COUNTER_DEB_ERROR = TSLPRM_DEBOUNCE_ERROR;
+
+ // Other parameters for linear/rotary only
+ THIS_RESOLUTION = TSLPRM_LINROT_RESOLUTION;
+ THIS_DIR_CHG_POS = TSLPRM_LINROT_DIR_CHG_POS;
+ THIS_COUNTER_DEB_DIRECTION = TSLPRM_LINROT_DIR_CHG_DEB;
+
+ // Initial state
+ TSL_linrot_SetStateCalibration(TSLPRM_CALIB_DELAY);
+}
+
+
+/**
+ * @brief Process the State Machine
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_Process(void)
+{
+ TSL_StateId_enum_T prev_state_id;
+
+ // Check if at least one channel has a data ready
+ if ((TSL_linrot_ProcessCh_One_DataReady() == TSL_STATUS_OK) || (THIS_STATEID == TSL_STATEID_OFF))
+ {
+
+ prev_state_id = THIS_STATEID;
+
+#if TSLPRM_TOTAL_LINROTS > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEAR) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARY))
+ {
+ // Launch the object state function
+ TSL_Globals.This_LinRot->p_SM[THIS_STATEID].StateFunc();
+ }
+#endif
+
+#if TSLPRM_TOTAL_LINROTS_B > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEARB) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARYB))
+ {
+ // Launch the TSL_Params state function
+ TSL_Params.p_LinRotSM[THIS_STATEID].StateFunc();
+ }
+#endif
+
+ // Check if the new state has changed
+ if (THIS_STATEID == prev_state_id)
+ {
+ THIS_CHANGE = TSL_STATE_NOT_CHANGED;
+ }
+ else
+ {
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ }
+
+#if TSLPRM_USE_DXS > 0
+ if (THIS_STATEID != TSL_STATEID_DETECT)
+ {
+ THIS_DXSLOCK = TSL_FALSE;
+ }
+ if (THIS_STATEID == TSL_STATEID_TOUCH)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+#endif
+
+ }
+}
+
+
+/**
+ * @brief Calculate the position
+ * @param None
+ * @retval Status Return OK if position calculation is correct
+ * @note The position is calculated only if the number of channels is greater than 2
+ */
+TSL_Status_enum_T TSL_linrot_CalcPos(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+ static TSL_tDelta_T delta1;
+ static TSL_tDelta_T delta2;
+ static TSL_tDelta_T delta3;
+ static TSL_tIndex_T index1;
+ static TSL_tIndex_T index2;
+ TSL_tNb_T minor;
+ TSL_tNb_T major;
+ TSL_tNb_T sector_computation = 0;
+ TSL_tNb_T position_correction = 0;
+ TSL_tsignPosition_T new_position = 0;
+ TSL_tPosition_T u_new_position = 0;
+
+ delta1 = 0;
+ delta2 = 0;
+ delta3 = 0;
+
+ index1 = 0;
+ index2 = 0;
+
+ // The position change flag will be set only if a new position is detected.
+ THIS_POSCHANGE = TSL_STATE_NOT_CHANGED;
+
+ // The position is calculated only if the number of channels is greater than 2
+ if (THIS_NB_CHANNELS < 3)
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ //--------------------------------------------------------------------------
+ // Sort the channels' delta
+ // - delta1 and index1 = biggest
+ // - delta2 and index2 = middle
+ // - delta3 and index3 = lowest
+ //--------------------------------------------------------------------------
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+ // The Delta must be positive only otherwise it is noise
+ if (norm_delta < 0) {norm_delta = 0;}
+
+ if (norm_delta > delta1)
+ {
+ delta3 = delta2;
+ delta2 = delta1;
+ delta1 = norm_delta;
+ index2 = index1;
+ index1 = idx;
+ }
+ else
+ {
+ if (norm_delta > delta2)
+ {
+ delta3 = delta2;
+ delta2 = norm_delta;
+ index2 = idx;
+ }
+ else
+ {
+ if (norm_delta > delta3)
+ {
+ delta3 = norm_delta;
+ }
+ }
+ }
+
+ p_Ch++; // Next channel
+
+ } // for all channels
+
+ // Noise filter: we need at least two significant Delta measurements
+ if (delta2 < ((TSL_tThreshold_T)(THIS_DETECTOUT_TH >> 1) - 1))
+ {
+ return TSL_STATUS_ERROR;
+ }
+
+ //----------------------------------------------------------------------------
+ // Position calculation...
+ //----------------------------------------------------------------------------
+
+ /*----------------------------------------------------------------------------
+ B = Biggest signal measured (Delta1/Index1)
+ M = Middle signal measured (Delta2/Index2)
+ S = Smallest signal measured (Delta3/Index3)
+
+ - The equation to find the position is:
+ Position = Offset +/- [ Sector_Size x ( Major / (Major + Minor) ) ]
+
+ - The Offset is the position of the middle of the Middle signal segment.
+ All the Offset values are stored in the ROM table Table_POSITION_OFFSET.
+
+ - Major = Biggest - Smallest signals
+ Minor = Middle - Smallest signals
+
+ - The Sector_Size depends of the number of channels used
+ ----------------------------------------------------------------------------*/
+
+ // Calculates the Major and Minor parameters
+ minor = (TSL_tNb_T)(delta2 - delta3); // Middle - Smallest signals
+ major = (TSL_tNb_T)(delta1 - delta3); // Biggest - Smallest signals
+
+ // Select the offset position in the position offset constant table
+ // Equal to: new_position = TABLE_POSITION_OFFSET_xCH_xxx[index1][index2];
+ new_position = *(TSL_Globals.This_LinRot->p_PosOff + (index1 * THIS_NB_CHANNELS) + index2);
+ sector_computation = THIS_SCT_COMP;
+ position_correction = THIS_POS_CORR;
+
+ // Calculates: [ Sector_Size x ( Major / (Major + Minor) ) ]
+ sector_computation = major * sector_computation;
+ sector_computation = sector_computation / (major + minor);
+
+ // Use the sign bit from position table to define the interpretation direction.
+ // The NewPosition is multiplied by 2 because the Offset stored in the ROM
+ // table is divided by 2...
+ if (new_position > 0) // Means Offset is > 0 in the position table
+ {
+ new_position = (TSL_tsignPosition_T)(new_position << 1);
+ new_position += sector_computation;
+ }
+ else // means Offset is <= 0 in the ROM table
+ {
+ new_position = (TSL_tsignPosition_T)((-new_position) << 1);
+ new_position -= sector_computation;
+ }
+
+ // Position is calculated differently if LINEAR or ROTARY sensor
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_LINEARB))
+ {
+
+ // First adjustment used to shift all the values to obtain the "zero"
+ if (new_position > 0)
+ {
+ new_position -= position_correction;
+ }
+ else
+ {
+ new_position = new_position + (256 - position_correction);
+ }
+
+ // Second adjustment used to clamp the values at both ends of sensor
+ if (new_position < 0)
+ {
+ new_position = 0;
+ }
+
+ if (new_position > 255)
+ {
+ new_position = 255;
+ }
+
+ }
+ else // ROTARY sensor: keep only the low byte
+ {
+ new_position = (TSL_tPosition_T)new_position;
+ }
+
+ //----------------------------------------------------------------------------
+ // Direction Change Process
+ //----------------------------------------------------------------------------
+
+ if (THIS_DIRECTION == TSL_TRUE) // Anticlockwise direction ...
+ {
+
+ // Check Direction changed and Position overflow from 0x00 to 0xFF not realized !
+ if (((TSL_tPosition_T)new_position > THIS_RAW_POSITION) && (((TSL_tPosition_T)new_position - THIS_RAW_POSITION) < DIRECTION_CHANGE_MAX_DISPLACEMENT))
+ {
+ if (new_position < (uint16_t)(THIS_RAW_POSITION + THIS_DIR_CHG_POS))
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_FALSE; // New direction accepted: clockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ // Check position overflow from 0xFF to 0x00 to be filtered !
+ if ((new_position + DIRECTION_CHANGE_MAX_DISPLACEMENT) < THIS_RAW_POSITION)
+ {
+ if ((new_position + DIRECTION_CHANGE_TOTAL_STEPS) < (uint16_t)(THIS_RAW_POSITION + THIS_DIR_CHG_POS))
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_FALSE; // New direction accepted: clockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ }
+ else // Clockwise direction... DEFAULT SETTING !
+ {
+
+ // Check Direction changed and Position overflow from 0xFF to 0x00 not realized !
+ if (((TSL_tPosition_T)new_position < THIS_RAW_POSITION) && ((THIS_RAW_POSITION - (TSL_tPosition_T)new_position) < DIRECTION_CHANGE_MAX_DISPLACEMENT))
+ {
+ if ((new_position + THIS_DIR_CHG_POS) > THIS_RAW_POSITION)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_TRUE; // New direction accepted: anticlockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ // Check position overflow from 0x00 to 0xFF to be filtered !
+ if (new_position > (uint16_t)(THIS_RAW_POSITION + DIRECTION_CHANGE_MAX_DISPLACEMENT))
+ {
+ if ((new_position + THIS_DIR_CHG_POS) > (uint16_t)(THIS_RAW_POSITION + DIRECTION_CHANGE_TOTAL_STEPS))
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_COUNTER_DIR--;
+ if (!THIS_COUNTER_DIR)
+ {
+ THIS_COUNTER_DIR = THIS_COUNTER_DEB_DIRECTION;
+ THIS_DIRECTION = TSL_TRUE; // New direction accepted: anticlockwise.
+ }
+ else
+ {
+ return TSL_STATUS_ERROR;
+ }
+ }
+ }
+
+ }
+
+ //----------------------------------------------------------------------------
+ // Final result...
+ //----------------------------------------------------------------------------
+
+ // The Raw Position is always updated
+ // The Position is updated only if different from the previous one
+
+ THIS_RAW_POSITION = (TSL_tPosition_T)new_position;
+
+ u_new_position = (TSL_tPosition_T)((TSL_tPosition_T)new_position >> (RESOLUTION_CALCULATION - THIS_RESOLUTION));
+
+ if (THIS_POSITION == u_new_position)
+ {
+ return TSL_STATUS_ERROR;
+ }
+ else
+ {
+ THIS_POSITION = u_new_position;
+ THIS_POSCHANGE = TSL_STATE_CHANGED;
+ return TSL_STATUS_OK;
+ }
+
+}
+
+
+//==============================================================================
+// Utility functions
+//==============================================================================
+
+/**
+ * @brief Go in Calibration state
+ * @param[in] delay Delay before calibration starts (stabilization of noise filter)
+ * @retval None
+ */
+void TSL_linrot_SetStateCalibration(TSL_tCounter_T delay)
+{
+ THIS_STATEID = TSL_STATEID_CALIB;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ TSL_linrot_ProcessCh_All_SetStatus(TSL_OBJ_STATUS_ON);
+
+ switch (TSL_Params.NbCalibSamples)
+ {
+ case 4:
+ CalibDiv = 2;
+ break;
+ case 16:
+ CalibDiv = 4;
+ break;
+ default:
+ TSL_Params.NbCalibSamples = 8;
+ CalibDiv = 3;
+ break;
+ }
+
+ // If a noise filter is used, the counter must be initialized to a value
+ // different from 0 in order to stabilize the filter.
+ THIS_COUNTER_DEB = (TSL_tCounter_T)(delay + (TSL_tCounter_T)TSL_Params.NbCalibSamples);
+ TSL_linrot_ProcessCh_All_ClearRef();
+}
+
+
+/**
+ * @brief Go in Off state with sensor "off"
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_SetStateOff(void)
+{
+ THIS_STATEID = TSL_STATEID_OFF;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ TSL_linrot_ProcessCh_All_SetStatus(TSL_OBJ_STATUS_OFF);
+}
+
+
+#if !defined(TSLPRM_STM8TL5X) && !defined(STM8TL5X)
+/**
+ * @brief Go in Off state with sensor in "Burst mode only"
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_SetStateBurstOnly(void)
+{
+ THIS_STATEID = TSL_STATEID_OFF;
+ THIS_CHANGE = TSL_STATE_CHANGED;
+ TSL_linrot_ProcessCh_All_SetStatus(TSL_OBJ_STATUS_BURST_ONLY);
+}
+#endif
+
+
+/**
+ * @brief Return the current state identifier
+ * @param None
+ * @retval State id
+ */
+TSL_StateId_enum_T TSL_linrot_GetStateId(void)
+{
+ return(THIS_STATEID);
+}
+
+
+/**
+ * @brief Return the current state mask
+ * @param None
+ * @retval State mask
+ */
+TSL_StateMask_enum_T TSL_linrot_GetStateMask(void)
+{
+ TSL_StateMask_enum_T state_mask = TSL_STATEMASK_UNKNOWN;
+
+#if TSLPRM_TOTAL_LINROTS > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEAR) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARY))
+ {
+ state_mask = TSL_Globals.This_LinRot->p_SM[THIS_STATEID].StateMask;
+ }
+#endif
+
+#if TSLPRM_TOTAL_LINROTS_B > 0
+ if ((TSL_Globals.This_Obj->Type == TSL_OBJ_LINEARB) ||
+ (TSL_Globals.This_Obj->Type == TSL_OBJ_ROTARYB))
+ {
+ state_mask = TSL_Params.p_LinRotSM[THIS_STATEID].StateMask;
+ }
+#endif
+
+ return state_mask;
+}
+
+
+/**
+ * @brief Return the Change flag
+ * @param None
+ * @retval Change flag status
+ */
+TSL_tNb_T TSL_linrot_IsChanged(void)
+{
+ return(THIS_CHANGE);
+}
+
+
+//==============================================================================
+// State machine functions
+//==============================================================================
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Release processing (previous state = Proximity)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebReleaseProxStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_PROX; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_PROX; // Go back to the previous state
+ }
+ else
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+#endif // if TSLPRM_USE_PROX > 0
+
+
+/**
+ * @brief Debounce Release processing (previous state = Detect)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebReleaseDetectStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ return;
+ }
+#endif
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+
+
+/**
+ * @brief Debounce Release processing (previous state = Touch)
+ * Same as Debounce Release Detect processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebReleaseTouchStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ return;
+ }
+#endif
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ // else stay in Debounce Release
+ }
+ }
+}
+
+
+/**
+ * @brief Release state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_ReleaseStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_RELEASE;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_PROXIN_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX;
+ }
+ return;
+ }
+#endif
+
+ // Check delta for re-calibration
+ if (TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(THIS_CALIB_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_CALIB;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_CALIB;
+ }
+ }
+ }
+}
+
+
+/**
+ * @brief Debounce Calibration processing (previous state = Release)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebCalibrationStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE; // Go back to the previous state
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(THIS_CALIB_TH, 1) == TSL_STATUS_OK) // Still below recalibration threshold
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ // else stay in Debounce Calibration
+ }
+ else // Go back to previous state
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+
+
+/**
+ * @brief Calibration state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_CalibrationStateProcess(void)
+{
+ TSL_tMeas_T new_meas;
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch;
+
+#if TSLPRM_CALIB_DELAY > 0
+ // Noise filter stabilization time
+ if (THIS_COUNTER_DEB > (TSL_tCounter_T)TSL_Params.NbCalibSamples)
+ {
+ THIS_COUNTER_DEB--;
+ return; // Skip the sample
+ }
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_CALIB;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ // Process all channels
+ p_Ch = TSL_Globals.This_LinRot->p_ChD;
+
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+ // Get the new measure or Calculate it
+#if TSLPRM_USE_MEAS > 0
+ new_meas = p_Ch->Meas;
+#else // Calculate it
+ new_meas = TSL_acq_ComputeMeas(p_Ch->Ref, p_Ch->Delta);
+#endif
+
+ // Verify the first Reference value
+ if (THIS_COUNTER_DEB == (TSL_tCounter_T)TSL_Params.NbCalibSamples)
+ {
+ if (TSL_acq_TestFirstReferenceIsValid(p_Ch, new_meas))
+ {
+ p_Ch->Ref = new_meas;
+ }
+ else
+ {
+ p_Ch->Ref = 0;
+ return;
+ }
+ }
+ else
+ {
+ // Add the measure in temporary Reference
+ p_Ch->Ref += new_meas;
+
+ // Check reference overflow
+ if (p_Ch->Ref < new_meas)
+ {
+ p_Ch->Ref = 0; // Suppress the bad reference
+ THIS_STATEID = TSL_STATEID_ERROR;
+ return;
+ }
+ }
+
+ p_Ch++; // Next channel
+ }
+
+ // Check that we have all the needed measurements
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ // Process all channels
+ p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ // Divide temporary Reference by the number of samples
+ p_Ch->Ref >>= CalibDiv;
+ p_Ch->RefRest = 0;
+ p_Ch->Delta = 0;
+ p_Ch++; // Next channel
+ }
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Release)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebProxStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_PROXIN_TH, 0) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Detect)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebProxDetectStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_DETECT;
+ }
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Debounce Proximity processing (previous state = Touch)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebProxTouchStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Proximity
+ }
+ else
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_TOUCH;
+ }
+ }
+ }
+}
+#endif
+
+
+#if TSLPRM_USE_PROX > 0
+/**
+ * @brief Proximity state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_ProxStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_PROX;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_DETECT;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_DETECT;
+ }
+ return;
+ }
+
+ if (TSL_linrot_ProcessCh_All_DeltaBelowEqu(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_PROX;
+ }
+ return;
+ }
+
+ // Stay in Proximity state
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ //------------------------------------
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ }
+#endif
+
+ }
+}
+#endif
+
+
+/**
+ * @brief Debounce Detect processing (previous state = Release or Proximity)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebDetectStateProcess(void)
+{
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_DETECTIN_TH, 1) == TSL_STATUS_OK)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_DETECT;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ // else stay in Debounce Detect
+ }
+ else
+ {
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAboveEqu(THIS_PROXIN_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX;
+ }
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+#else
+ THIS_STATEID = TSL_STATEID_RELEASE;
+#endif
+ }
+ }
+}
+
+
+/**
+ * @brief Detect state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DetectStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_Status_enum_T pos_sts;
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_DETECT;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ //-------------------
+ // Calculate position
+ //-------------------
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARY))
+ {
+ // Call the specific method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#else
+ TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#endif
+ }
+ else // TSL_OBJ_LINEARB or TSL_OBJ_ROTARYB
+ {
+ // Call the default method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Params.p_LinRotMT->CalcPosition();
+#else
+ TSL_Params.p_LinRotMT->CalcPosition();
+#endif
+ }
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ // Only if the Position has NOT changed
+ //-------------------------------------
+ if (pos_sts == TSL_STATUS_OK)
+ {
+ DTO_GET_TIME; // Take current time
+ }
+ else
+ {
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ }
+ }
+#endif
+ return; // Normal operation, stay in Detect state
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX_DETECT;
+ }
+ return;
+ }
+#endif
+
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_DETECT;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Touch state processing
+ * Same as Detect state
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_TouchStateProcess(void)
+{
+#if TSLPRM_DTO > 0
+ TSL_Status_enum_T pos_sts;
+ TSL_tTick_sec_T tick_detected;
+#endif
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_ERROR;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_ERROR_TOUCH;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_DETECTOUT_TH, 1) == TSL_STATUS_OK)
+ {
+ //-------------------
+ // Calculate position
+ //-------------------
+ if ((THIS_OBJ_TYPE == TSL_OBJ_LINEAR) || (THIS_OBJ_TYPE == TSL_OBJ_ROTARY))
+ {
+ // Call the specific method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#else
+ TSL_Globals.This_LinRot->p_Methods->CalcPosition();
+#endif
+ }
+ else // TSL_OBJ_LINEARB or TSL_OBJ_ROTARYB
+ {
+ // Call the default method
+#if TSLPRM_DTO > 0
+ pos_sts = TSL_Params.p_LinRotMT->CalcPosition();
+#else
+ TSL_Params.p_LinRotMT->CalcPosition();
+#endif
+ }
+#if TSLPRM_DTO > 0
+ //------------------------------------
+ // Detection Time Out (DTO) processing
+ // Only if the Position has NOT changed
+ //-------------------------------------
+ if (pos_sts == TSL_STATUS_OK)
+ {
+ DTO_GET_TIME; // Take current time
+ }
+ else
+ {
+ if ((TSL_Params.DTO > 1) && (TSL_Params.DTO < 64))
+ {
+ tick_detected = THIS_COUNTER_DTO; // Get the detected time previously saved
+ // Enter in calibration state if the DTO duration has elapsed
+ if (TSL_tim_CheckDelay_sec(TSL_Params.DTO, &tick_detected) == TSL_STATUS_OK)
+ {
+ TSL_linrot_SetStateCalibration(0);
+ }
+ }
+ }
+#endif
+ return; // Normal operation, stay in Touch state
+ }
+
+#if TSLPRM_USE_PROX > 0
+ if (TSL_linrot_ProcessCh_One_DeltaAbove(THIS_PROXOUT_TH, 0) == TSL_STATUS_OK)
+ {
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_PROX;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_PROX;
+ DTO_GET_TIME; // Take current time for DTO processing
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_PROX_TOUCH;
+ }
+ return;
+ }
+#endif
+
+ THIS_COUNTER_DEB = THIS_COUNTER_DEB_RELEASE;
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ }
+ else
+ {
+ THIS_STATEID = TSL_STATEID_DEB_RELEASE_TOUCH;
+ }
+
+ }
+}
+
+
+/**
+ * @brief Debounce error state processing
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DebErrorStateProcess(void)
+{
+ volatile TSL_StateMask_enum_T mask;
+
+ if (TSL_linrot_ProcessCh_One_AcqStatusError() == TSL_STATUS_OK) // Acquisition error (min or max)
+ {
+ if (THIS_COUNTER_DEB > 0) {THIS_COUNTER_DEB--;}
+ if (THIS_COUNTER_DEB == 0)
+ {
+ THIS_STATEID = TSL_STATEID_ERROR;
+ }
+ }
+ else // Acquisition is OK or has NOISE
+ {
+ // Get state mask
+ mask = TSL_linrot_GetStateMask();
+ // Mask Error and Debounce bits
+#ifdef _RAISONANCE_
+ mask &= ~(TSL_STATE_DEBOUNCE_BIT_MASK | TSL_STATE_ERROR_BIT_MASK);
+#else
+ mask &= (TSL_StateMask_enum_T)(~(TSL_STATE_DEBOUNCE_BIT_MASK | TSL_STATE_ERROR_BIT_MASK));
+#endif
+ // Go back to the previous state
+ switch (mask)
+ {
+ case TSL_STATEMASK_RELEASE :
+ THIS_STATEID = TSL_STATEID_RELEASE;
+ break;
+ case TSL_STATEMASK_PROX :
+ THIS_STATEID = TSL_STATEID_PROX;
+ break;
+ case TSL_STATEMASK_DETECT :
+ THIS_STATEID = TSL_STATEID_DETECT;
+ break;
+ case TSL_STATEMASK_TOUCH :
+ THIS_STATEID = TSL_STATEID_TOUCH;
+ break;
+ default:
+ TSL_linrot_SetStateCalibration(0);
+ break;
+ }
+ }
+}
+
+
+//==============================================================================
+// Private functions
+//==============================================================================
+
+/**
+ * @brief Get the current time in second and affect it to the DTO counter (Private)
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_DTOGetTime(void)
+{
+ disableInterrupts();
+ THIS_COUNTER_DTO = (TSL_tCounter_T)TSL_Globals.Tick_sec;
+ enableInterrupts();
+}
+
+
+/**
+ * @brief Set all channels status to ON, OFF or BURST ONLY
+ * @param sts Channel status
+ * @retval None
+ */
+void TSL_linrot_ProcessCh_All_SetStatus(TSL_ObjStatus_enum_T sts)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ // Init channels status
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ p_Ch->Flags.ObjStatus = sts;
+ p_Ch++;
+ }
+}
+
+
+/**
+ * @brief Check if at least one channel has a data ready
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DataReady(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_Status_enum_T retval = TSL_STATUS_ERROR;
+ // Return OK if at least one channel has a data ready
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ if (p_Ch->Flags.DataReady == TSL_DATA_READY)
+ {
+ p_Ch->Flags.DataReady = TSL_DATA_NOT_READY; // The new data is processed
+ retval = TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return retval;
+}
+
+
+/**
+ * @brief Check if all channels are equal to the status passed
+ * @param sts Status to be checked
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_AcqStatus(TSL_AcqStatus_enum_T sts)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ // Return OK if ALL channels have the correct acq status
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ if (p_Ch->Flags.AcqStatus != sts)
+ {
+ return TSL_STATUS_ERROR;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Check if at least one channel is in error
+ * @param None
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_AcqStatusError(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ // Return OK if at least one channel is in acquisition error min or max
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ if (p_Ch->Flags.AcqStatus & TSL_ACQ_STATUS_ERROR_MASK)
+ {
+ return TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if at least one channel is below or equal a threshold (inverted)
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaBelowEquMinus(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if at least one channel is below or equal the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta <= -lth) // Warning!!! The threshold is inverted
+#else
+ if (norm_delta <= -th) // Warning!!! The threshold is inverted
+#endif
+ {
+ return TSL_STATUS_OK;
+ }
+
+ p_Ch++;
+ }
+
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if at least one channel is above or equal a threshold
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAboveEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if at least one channel is above or equal the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta >= lth)
+#else
+ if (norm_delta >= th)
+#endif
+ {
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta < 0)
+ {
+ p_Ch++;
+ continue;
+ }
+#endif
+ return TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if at least one channel is stricly above a threshold
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_One_DeltaAbove(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if at least one channel is above the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta > lth)
+#else
+ if (norm_delta > th)
+#endif
+ {
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta < 0)
+ {
+ p_Ch++;
+ continue;
+ }
+#endif
+ return TSL_STATUS_OK;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_ERROR;
+}
+
+
+/**
+ * @brief Check if all channels are below or equal a threshold
+ * @param th Threshold
+ * @param coeff Enable or Disable the multiplier coefficient on threshold
+ * @retval Status
+ */
+TSL_Status_enum_T TSL_linrot_ProcessCh_All_DeltaBelowEqu(TSL_tThreshold_T th, TSL_tIndex_T coeff)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ TSL_tDelta_T norm_delta;
+
+#if TSLPRM_COEFF_TH > 0
+ uint16_t lth;
+ if (coeff)
+ {
+ lth = (uint16_t)((uint16_t)th << TSLPRM_COEFF_TH);
+ }
+ else
+ {
+ lth = th;
+ }
+#endif
+
+ // Return OK if ALL channels are below or equal the threshold
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+
+#if TSLPRM_LINROT_USE_NORMDELTA > 0
+ norm_delta = TSL_linrot_NormDelta(p_Ch, idx); // Normalize the Delta
+#else
+ norm_delta = p_Ch->Delta; // Take only the Delta
+#endif
+
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta > lth)
+#else
+ if (norm_delta > th)
+#endif
+ {
+#if TSLPRM_COEFF_TH > 0
+ if (norm_delta < 0)
+ {
+ p_Ch++;
+ continue;
+ }
+#endif
+ return TSL_STATUS_ERROR;
+ }
+ p_Ch++;
+ }
+ return TSL_STATUS_OK;
+}
+
+
+/**
+ * @brief Clear the Reference and ReferenceRest for all channels
+ * @param None
+ * @retval None
+ */
+void TSL_linrot_ProcessCh_All_ClearRef(void)
+{
+ TSL_tIndex_T idx;
+ TSL_ChannelData_T *p_Ch = TSL_Globals.This_LinRot->p_ChD;
+ for (idx = 0; idx < THIS_NB_CHANNELS; idx++)
+ {
+ p_Ch->Ref = 0;
+ p_Ch->RefRest = 0;
+ p_Ch++;
+ }
+}
+
+
+/**
+ * @brief Normalize a Delta value
+ * @param ch Pointer to the current channel
+ * @param idx Index of the channel
+ * @retval Normalized Delta value
+ */
+TSL_tDelta_T TSL_linrot_NormDelta(TSL_ChannelData_T *ch, TSL_tIndex_T idx)
+{
+ uint32_t tmpdelta = ch->Delta;
+
+ // Apply coefficient
+ if (TSL_Globals.This_LinRot->p_DeltaCoeff[idx] != 0x0100)
+ {
+ tmpdelta = (uint32_t)(tmpdelta * TSL_Globals.This_LinRot->p_DeltaCoeff[idx]);
+ tmpdelta = tmpdelta >> (uint8_t)8;
+ }
+
+ return (TSL_tDelta_T)tmpdelta;
+}
+
+#endif
+// #if TSLPRM_TOTAL_LNRTS > 0
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/