text: /**
    ******************************************************************************
    * @file    tsl_linrot.c
    * @author  MCD Application Team
    * @version V2.0.0
    * @date    22-April-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);
  }
  
  
  /**
    * @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);
  }
  
  
  /**
    * @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****/
  