/**
  ******************************************************************************
  * @brief After Touch Sensing acquisition, this function launch the data interpretation.
  * @param None
  * @retval None
  ******************************************************************************
  */
void TSL_SCKey_Process(void)
{

    TSL_SetStructPointer();

    TSL_DeltaCalculation();

    switch (pKeyStruct->State.whole)
    {

    case IDLE_STATE:
        if (TSL_SCKey_CheckErrorCondition())
        {
            TSL_SCKey_SetErrorState();
            break;
        }
        TSL_SCKey_IdleTreatment();
        TSL_SCKey_CheckDisabled();
        break;

    case PRE_DETECTED_STATE:
        TSL_SCKey_PreDetectTreatment();
        break;

    case DETECTED_STATE:
        if (TSL_SCKey_CheckErrorCondition())
        {
            TSL_SCKey_SetErrorState();
            break;
        }
        TSL_SCKey_DetectedTreatment();
        TSL_SCKey_CheckDisabled();
        break;

    case POST_DETECTED_STATE:
        TSL_SCKey_PostDetectTreatment();
        break;

    case PRE_CALIBRATION_STATE:
        TSL_SCKey_PreRecalibrationTreatment();
        break;

    case CALIBRATION_STATE:
        if (TSL_SCKey_CheckErrorCondition())
        {
            TSL_SCKey_SetErrorState();
            break;
        }
        TSL_SCKey_CalibrationTreatment();
        TSL_SCKey_CheckDisabled();
        break;

    case ERROR_STATE:
        TSL_SCKey_CheckDisabled();
        break;

    case DISABLED_STATE:
        TSL_SCKey_CheckEnabled();
        break;

    default:
        for (;;)
        {
            // Infinite loop.
        }

    }

    TSL_TempGlobalSetting.whole |= pKeyStruct->Setting.whole;
    TSL_TempGlobalState.whole |= pKeyStruct->State.whole;
    pKeyStruct->Setting.b.CHANGED = 0;

}
/**
  ******************************************************************************
  * @brief Considers all Key information to apply the Environmental Change System (ECS).
  * Uses an IIR Filter with order 1:
  * Y(n) = K x X(n) + (1-K) x Y(n-1)
  * Y is the reference and X is the acquisition value.
  * @par Parameters:
  * None
  * @retval void None
  * @par Required preconditions:
  * None
  ******************************************************************************
  */
void TSL_ECS(void)
{

  u8 K_Filter, K_Filter_Complement;
  s8 ECS_Fast_Direction, ECS_Fast_Enable;
  u32 IIR_Result;

  disableInterrupts();
  Local_TickECS10ms = TSL_TickCount_ECS_10ms;
  TSL_TickCount_ECS_10ms = 0;
  enableInterrupts();

  while ( Local_TickECS10ms-- )
  {
    ECSTimeStepCounter--;
    ECSTempoPrescaler--;
    if ( !ECSTempoPrescaler )
    {
      ECSTempoPrescaler = 10;
      if ( ECSTempoCounter )
        ECSTempoCounter--;
    }

    K_Filter = ECS_K_Slow;   // Default case !
    ECS_Fast_Enable = 1;
    ECS_Fast_Direction = 0;
    for ( KeyIndex = 0; KeyIndex < NUMBER_OF_SINGLE_CHANNEL_KEYS; KeyIndex++ )
    {
      TSL_SetStructPointer();
      // If any key is in DETECT state, ECS is disabled !
      if ( pKeyStruct->State.whole & DETECTED_STATE)
	  {
        ECSTempoCounter = ECSTemporization;    // Restart temporization counter ...
        break;           // Out from the for loop
      }
      if ( pKeyStruct->State.whole == IDLE_STATE )
      {
        TSL_DeltaCalculation();
        if ( Delta == 0 )  // No Fast ECS !
          ECS_Fast_Enable = 0;
        else
        {
          if ( Delta < 0 )
          {
            if ( ECS_Fast_Direction > 0 )  // No Fast ECS !
              ECS_Fast_Enable = 0;
            else
              ECS_Fast_Direction = -1;
          }
          else
          {
            if ( ECS_Fast_Direction < 0 )  // No Fast ECS !
              ECS_Fast_Enable = 0;
            else
              ECS_Fast_Direction = + 1;
          }
        }
      }
    }

#if NUMBER_OF_MULTI_CHANNEL_KEYS > 0
    for ( KeyIndex = 0; KeyIndex < NUMBER_OF_MULTI_CHANNEL_KEYS; KeyIndex++ )
    {
      TSL_MCKey_SetStructPointer();
      if ( pMCKeyStruct->State.whole & DETECTED_STATE )      	  
      {
        ECSTempoCounter = ECSTemporization;    // Restart temporization counter ...
        break;           // Out from the for loop
      }
      if ( pMCKeyStruct->State.whole == IDLE_STATE )
      {
        for ( ChannelIndex = 0; ChannelIndex < CHANNEL_PER_MCKEY; ChannelIndex++ )
        {
          TSL_MCKey_DeltaCalculation( ChannelIndex );
          Delta1 += Delta;
        }
        if ( Delta1 == 0 )
        {   // No Fast ECS !
          ECS_Fast_Enable = 0;
        }
        else
        {
          if ( Delta1 < 0 )
          {
            if ( ECS_Fast_Direction > 0 )
            {   // No Fast ECS !
              ECS_Fast_Enable = 0;
            }
            else
              ECS_Fast_Direction = -1;
          }
          else
          {
            if ( ECS_Fast_Direction < 0 )
            {   // No Fast ECS !
              ECS_Fast_Enable = 0;
            }
            else
              ECS_Fast_Direction = + 1;
          }
        }
      }
    }
#endif

    if ( !ECSTimeStepCounter && !ECSTempoCounter )
    {
      ECSTimeStepCounter = ECSTimeStep;

      if (ECS_Fast_Enable)
      {
        K_Filter = ECS_K_Fast;
      }

      K_Filter_Complement = (u8)((0xFF ^ K_Filter) + 1);

      if ( K_Filter )
      {
        // Apply filter to generate new reference value.
        for ( KeyIndex = 0; KeyIndex < NUMBER_OF_SINGLE_CHANNEL_KEYS; KeyIndex++ )
        {
          TSL_SetStructPointer();
          if ( pKeyStruct->State.whole == IDLE_STATE )
          {
            IIR_Result = ((u32)(pKeyStruct->Channel.Reference) << 8) + pKeyStruct->Channel.ECSRefRest;
            IIR_Result = K_Filter_Complement * IIR_Result;
            IIR_Result += K_Filter * ((u32)(pKeyStruct->Channel.LastMeas) << 8);
            pKeyStruct->Channel.Reference = (u16)(IIR_Result >> 16);
            pKeyStruct->Channel.ECSRefRest = (u8)(IIR_Result >> 8);
          }
        }
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 0
        for ( KeyIndex = 0; KeyIndex < NUMBER_OF_MULTI_CHANNEL_KEYS; KeyIndex++ )
        {
          TSL_MCKey_SetStructPointer();
          if ( pMCKeyStruct->State.whole == IDLE_STATE )
          {
            for ( ChannelIndex = 0; ChannelIndex < CHANNEL_PER_MCKEY; ChannelIndex++ )
            {
              IIR_Result = ((u32)(pMCKeyStruct->Channel[ChannelIndex].Reference) << 8) + pMCKeyStruct->Channel[ChannelIndex].ECSRefRest;
              IIR_Result = K_Filter_Complement * IIR_Result;
              IIR_Result += K_Filter * ((u32)(pMCKeyStruct->Channel[ChannelIndex].LastMeas) << 8);
              pMCKeyStruct->Channel[ChannelIndex].Reference = (u16)(IIR_Result >> 16);
              pMCKeyStruct->Channel[ChannelIndex].ECSRefRest = (u8)(IIR_Result >> 8);
            }
          }
        }
#endif
      }
    }