stm8_tsl_services.c
来自「STM8s」· C语言 代码 · 共 1,010 行 · 第 1/2 页
C
1,010 行
/**
******************************************************************************
* @file stm8_tsl_services.c
* @author MCD Application Team
* @version V2.3.1
* @date 14-February-2011
* @brief STM8 Touch Sensing Library - This file provides a set of internal
* for all STM8 devices.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
*/
/* Includes ------------------------------------------------------------------*/
#include "stm8_tsl_api.h"
#include "stm8_tsl_services.h"
/* Memory section ------------------------------------------------------------*/
#if defined(_COSMIC_) && defined(USE_PRAGMA_SECTION)
#pragma section [TSL_RAM]
#pragma section @tiny [TSL_RAM0]
#pragma section (TSL_CODE)
#pragma section const {TSL_CONST}
#endif
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
******************************************************************************
* @brief Update pointer to current Key Structure.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
#if NUMBER_OF_SINGLE_CHANNEL_KEYS > 0
void TSL_SetStructPointer(void)
{
pKeyStruct = &sSCKeyInfo[KeyIndex];
}
/**
******************************************************************************
* @brief Delta calculation for the current Key structure.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_DeltaCalculation(void)
{
/*
Note that the delta calculation depends of the technology used:
- With the RC technology, the measured value for a "touch" is higher than
the reference value.
- With the Charge Transfer technology, the measured value for a "touch"
is lower than the reference value.
*/
#ifdef CHARGE_TRANSFER
/* Delta calculation for Charge transfer technology */
Delta = (s16)(pKeyStruct->Channel.Reference - pKeyStruct->Channel.LastMeas);
#else
/* Delta calculation for RC technology */
Delta = (s16)(pKeyStruct->Channel.LastMeas - pKeyStruct->Channel.Reference);
#endif
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the IDLE state.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetIdleState(void)
{
pKeyStruct->Setting.b.CHANGED = 1;
TSL_SCKey_BackToIdleState();
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to return to the IDLE state and reset appropriate flags.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_BackToIdleState(void)
{
pKeyStruct->State.whole = IDLE_STATE;
pKeyStruct->Setting.b.DETECTED = 0;
pKeyStruct->Setting.b.LOCKED = 0;
pKeyStruct->Setting.b.ERROR = 0;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the PRE_DETECTED state and init integrator counter.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetPreDetectState(void)
{
pKeyStruct->State.whole = PRE_DETECTED_STATE;
pKeyStruct->Channel.IntegratorCounter = DetectionIntegrator;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the DETECTED state and init detection timeout + flags.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetDetectedState(void)
{
pKeyStruct->State.whole = DETECTED_STATE;
pKeyStruct->Setting.b.DETECTED = 1;
pKeyStruct->Setting.b.CHANGED = 1;
pKeyStruct->Counter = DetectionTimeout;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the POST_DETECTED state and init end integrator counter.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetPostDetectState(void)
{
pKeyStruct->State.whole = POST_DETECTED_STATE;
pKeyStruct->Channel.IntegratorCounter = EndDetectionIntegrator;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go back to the DETECTED state
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_BackToDetectedState(void)
{
pKeyStruct->State.whole = DETECTED_STATE;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the PRE_CALIBRATION state and init integrator counter.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetPreRecalibrationState(void)
{
pKeyStruct->State.whole = PRE_CALIBRATION_STATE;
pKeyStruct->Channel.IntegratorCounter = RecalibrationIntegrator;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the CALIBRATION state and init appropriate flags.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetCalibrationState(void)
{
pKeyStruct->State.whole = CALIBRATION_STATE;
pKeyStruct->Setting.b.DETECTED = 0;
pKeyStruct->Setting.b.CHANGED = 1;
pKeyStruct->Setting.b.LOCKED = 0;
pKeyStruct->Setting.b.ERROR = 0;
pKeyStruct->Counter = SCKEY_CALIBRATION_COUNT_DEFAULT;
pKeyStruct->Channel.Reference = 0;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the ERROR state and init appropriate flags.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetErrorState(void)
{
pKeyStruct->State.whole = ERROR_STATE;
pKeyStruct->Setting.b.DETECTED = 0;
pKeyStruct->Setting.b.CHANGED = 1;
pKeyStruct->Setting.b.LOCKED = 0;
pKeyStruct->Setting.b.ERROR = 1;
}
/**
******************************************************************************
* @brief Short local routine to setup SCKey internal state machine.
* Used to go to the DISABLE state and init appropriate flags.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_SetDisabledState(void)
{
pKeyStruct->State.whole = DISABLED_STATE;
pKeyStruct->Setting.b.DETECTED = 0;
pKeyStruct->Setting.b.CHANGED = 1;
pKeyStruct->Setting.b.LOCKED = 0;
pKeyStruct->Setting.b.ERROR = 0;
}
#endif
/**
******************************************************************************
* @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;
#if NUMBER_OF_SINGLE_CHANNEL_KEYS > 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 == PRE_DETECTED_STATE) || (pKeyStruct->State.whole == DETECTED_STATE) || (pKeyStruct->State.whole == POST_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;
}
}
}
}
#endif
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 0
for (KeyIndex = 0; KeyIndex < NUMBER_OF_MULTI_CHANNEL_KEYS; KeyIndex++)
{
TSL_MCKey_SetStructPointer();
if ((pMCKeyStruct->State.whole == PRE_DETECTED_STATE) || (pMCKeyStruct->State.whole == DETECTED_STATE) || (pMCKeyStruct->State.whole == POST_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)
{
#if NUMBER_OF_SINGLE_CHANNEL_KEYS > 0
// 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);
}
}
#endif
#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
}
}
}
}
#if NUMBER_OF_SINGLE_CHANNEL_KEYS > 0
/**
******************************************************************************
* @brief Apply Detection exclusion System algorithm (DxS).
* This function modify the LOCKED bit of current Key structure only.
* @par Parameters:
* None
* @retval void None
* @par Required preconditions:
* None
******************************************************************************
*/
void TSL_SCKey_DxS(void)
{
u8 DxSGroupMask, KeyToCheck;
if (pKeyStruct->Setting.b.LOCKED)
return;
DxSGroupMask = pKeyStruct->DxSGroup;
for (KeyToCheck = 0; KeyToCheck < NUMBER_OF_SINGLE_CHANNEL_KEYS; KeyToCheck++)
{
if (KeyToCheck != KeyIndex)
{
// KeyToCheck and current key are in same group ?
if (sSCKeyInfo[KeyToCheck].DxSGroup & DxSGroupMask)
{
if (sSCKeyInfo[KeyToCheck].Setting.b.LOCKED)
{
goto ExitToIdle;
}
}
}
}
#if NUMBER_OF_MULTI_CHANNEL_KEYS > 0
for (KeyToCheck = 0; KeyToCheck < NUMBER_OF_MULTI_CHANNEL_KEYS; KeyToCheck++)
{
// KeyToCheck and current key are in same group ?
if (sMCKeyInfo[KeyToCheck].DxSGroup & DxSGroupMask)
{
if (sMCKeyInfo[KeyToCheck].Setting.b.LOCKED)
{
goto ExitToIdle;
}
}
}
#endif
pKeyStruct->Setting.b.LOCKED = 1;
return;
ExitToIdle: // The DxS is verified at PRE DETECT state only !
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?