#include "drivers.h"
#include "tk_cfg.h"
const uint16_t FingerAreaConfirmTickCNT = FINGER_CONFIRM_TICK_CNT;
const uint16_t WaterAreaConfirmTickCNT = WATER_AREA_CONFIRM_TICK_CNT;
const uint16_t NoiseAreaConfirmTickCNT = NOISE_AREA_CONFIRM_TICK_CNT;
const uint16_t BottonAreaConfirmTickCNT = BOTTON_AREA_CONFIRM_TICK_CNT;
const uint16_t FingerReleaseConfirmTickCNT = FINGER_RELEASE_CONFIRM_TICK_CNT;
const int16_t NoiseTHD = NOISE_THD_DEFAULT;
const FilterCtr_TypeDef FilterCtr = {
    .AvgModCNT = COEFF,
    .releaseRate = RELEASE_RATE,
    .Coeff = 5,
    .CoeffCNT = 6,
};
const SyncSampling_TypeDef SyncSampling = {
    .Enable = SYNC_SENSITVITY,
    .Win = SYNC_SENSITVITY_WIN,
    .Coeff = SYNC_SENSITVITY_COEFF,
	.NoiserThd = SYNC_REF_NOISETHD,
};
#if APP_TK_ENABLE
#pragma pack(4)
typedef struct
{
    uint8_t TouchKeyChSeq[TK_CHMAX];
    TKArea_TypeDef TK_Area[TK_CHMAX];
    TKArea_TypeDef TK_AreaPending[TK_CHMAX];
    uint16_t RawData[TK_CHMAX];
    uint16_t FilteredDataDBG[TK_CHMAX];
    uint16_t BaseLineDataDBG[TK_CHMAX];
    uint16_t FilteredData[TK_CHMAX];
    uint16_t BaseLineData[TK_CHMAX];
    uint16_t AreaRawDataBase[TK_CHMAX];
    int16_t Differ[TK_CHMAX];
    uint16_t FingerTHD[TK_CHMAX];
    uint16_t TK_AreaConfirmTickCnt[TK_CHMAX];
    uint16_t TK_KeyOutTimeLimitCnt[TK_CHMAX];
    uint16_t RawDatasBuf[COEFF * TK_CHMAX];
    uint16_t FilteredCount[TK_CHMAX];
    uint32_t FilteredSum[TK_CHMAX];
#if WATER_PROOF_EN
    uint16_t SingleBaseLineData[TK_CHMAX];
    uint16_t SingleFilteredData[TK_CHMAX];
    uint16_t SingleAcqData[TK_CHMAX];
    uint16_t SingleAcqRawDatasBuf[COEFF * TK_CHMAX];
#endif
} TKMem_TypeDef;
#pragma pack()
const uint8_t KEY_CH_TAB[] = {
    CH_KEY0,  CH_KEY1,  CH_KEY2,  CH_KEY3,  CH_KEY4,  CH_KEY5,  CH_KEY6,  CH_KEY7,  CH_KEY8,
    CH_KEY9,  CH_KEY10, CH_KEY11, CH_KEY12, CH_KEY13, CH_KEY14, CH_KEY15, CH_KEY16, CH_KEY17,
    CH_KEY18, CH_KEY19, CH_KEY20, CH_KEY21, CH_KEY22, CH_KEY23, CH_KEY24, CH_KEY25,
};
const uint16_t KEY_THD_TAB[] = {
    KEY0_THD,  KEY1_THD,  KEY2_THD,  KEY3_THD,  KEY4_THD,  KEY5_THD,  KEY6_THD,  KEY7_THD,  KEY8_THD,
    KEY9_THD,  KEY10_THD, KEY11_THD, KEY12_THD, KEY13_THD, KEY14_THD, KEY15_THD, KEY16_THD, KEY17_THD,
    KEY18_THD, KEY19_THD, KEY20_THD, KEY21_THD, KEY22_THD, KEY23_THD, KEY24_THD, KEY25_THD,
};
#if (SLIDER_OR_WHEEL_CH_TOTAL > 0)
const uint8_t SLIDERORWHEEL_CH_TAB[SLIDER_MAX][8] = {
    {SLIDER_OR_WHEEL0_CH0, SLIDER_OR_WHEEL0_CH1, SLIDER_OR_WHEEL0_CH2, SLIDER_OR_WHEEL0_CH3, SLIDER_OR_WHEEL0_CH4,
     SLIDER_OR_WHEEL0_CH5, SLIDER_OR_WHEEL0_CH6, SLIDER_OR_WHEEL0_CH7},
    {SLIDER_OR_WHEEL1_CH0, SLIDER_OR_WHEEL1_CH1, SLIDER_OR_WHEEL1_CH2, SLIDER_OR_WHEEL1_CH3, SLIDER_OR_WHEEL1_CH4,
     SLIDER_OR_WHEEL1_CH5, SLIDER_OR_WHEEL1_CH6, SLIDER_OR_WHEEL1_CH7},
    {SLIDER_OR_WHEEL2_CH0, SLIDER_OR_WHEEL2_CH1, SLIDER_OR_WHEEL2_CH2, SLIDER_OR_WHEEL2_CH3, SLIDER_OR_WHEEL2_CH4,
     SLIDER_OR_WHEEL2_CH5, SLIDER_OR_WHEEL2_CH6, SLIDER_OR_WHEEL2_CH7},
    {SLIDER_OR_WHEEL3_CH0, SLIDER_OR_WHEEL3_CH1, SLIDER_OR_WHEEL3_CH2, SLIDER_OR_WHEEL3_CH3, SLIDER_OR_WHEEL3_CH4,
     SLIDER_OR_WHEEL3_CH5, SLIDER_OR_WHEEL3_CH6, SLIDER_OR_WHEEL3_CH7},
};
static uint8_t SLIDERORWHEEL_TYPE_TAB[SLIDER_MAX] = {SLIDER_OR_WHEEL0_TYPE, SLIDER_OR_WHEEL1_TYPE,
                                                     SLIDER_OR_WHEEL2_TYPE, SLIDER_OR_WHEEL3_TYPE};

static uint16_t SLIDERORWHEEL_RESOLUTION_TAB[SLIDER_MAX] = {SLIDER_OR_WHEEL0_RESOLUTION, SLIDER_OR_WHEEL1_RESOLUTION,
                                                            SLIDER_OR_WHEEL2_RESOLUTION, SLIDER_OR_WHEEL3_RESOLUTION};

const uint16_t SLIDERORWHEEL_THD_TAB[SLIDER_MAX] = {SLIDER_OR_WHEEL0_THD, SLIDER_OR_WHEEL1_THD, SLIDER_OR_WHEEL2_THD,
                                                    SLIDER_OR_WHEEL3_THD};
#endif
/**
 */
static TKMem_TypeDef TK_Mem;
#if (SLEEP_EN)
#if (RTC_ENABLE == 0)
#error "error! 触摸休眠需要RTC支持，需要在app_config.h内开启RTC模块"
#endif
#if STOP_DEBUG
static uint8_t sleepchs_idx;
#endif
#endif
#if DEBUG_ENABLE && (DEBUG_MODE == 0)
char log_string[64];
static uint8_t app_log_fifo[128];
/**
 * @brief  log_Init
 * @param  初始化打印
 * @retval
 */
#if DEBUG_ENABLE && (DEBUG_MODE == 0)
void log_init(void)
{
    app_log.base = app_log_fifo;
    app_log.front = app_log.rear = 0;
    app_log.sq_size = sizeof(app_log_fifo);
}
#endif
/**
 * @brief  log_putstr
 * @param  发送字符串
 * @retval
 */
void log_putstr(char *str)
{
    while (*str)
    {
        /*	队列已满	,等待发送	*/
        while (((app_log.rear + 1) % app_log.sq_size) == app_log.front)
        {
            if (app_log.app_connect == 0) // 等待超时
                return;
            __WFI();
        }
        app_log.base[app_log.rear] = *str++;
        app_log.rear = (app_log.rear + 1) % app_log.sq_size;
    }
}
#endif
/**
 * @brief  TK用户参数初始化
 * @param  None
 * @retval None
 */
void TK_UserParaInit(void)
{
    uint8_t offset;
#if (SLIDER_OR_WHEEL_CH_TOTAL > 0)
    uint8_t j, k, n;
#endif
#if KEY_OUT_MAX_TICK_CNT
    TKCtr.KeyOutTimeLimitEn = 1;
    TKCtr.KeyOutTimeLimitCNT = KEY_OUT_MAX_TICK_CNT; // 长按超时时间，单位5ms
#else
    TKCtr.KeyOutTimeLimitEn = 0;
#endif
    TKCtr.TK_Config = 0;
    /*	数据指针设置		*/
    TK_Info.pTouchKeyDatas->BaseLineData = TK_Mem.BaseLineData;
    TK_Info.pTouchKeyDatas->BaseLineDataDBG = TK_Mem.BaseLineDataDBG;
    TK_Info.pTouchKeyDatas->Differ = TK_Mem.Differ;
    TK_Info.pTouchKeyDatas->FilteredData = TK_Mem.FilteredData;
    TK_Info.pTouchKeyDatas->FilteredDataDBG = TK_Mem.FilteredDataDBG;
    TK_Info.pTouchKeyDatas->AreaRawDataBase = TK_Mem.AreaRawDataBase;
    TK_Info.pTouchKeyDatas->FingerTHD = TK_Mem.FingerTHD;
    TK_Info.pTouchKeyDatas->RawData = TK_Mem.RawData;
    TK_Info.pTouchKeyDatas->FilteredCount = TK_Mem.FilteredCount;
    TK_Info.pTouchKeyDatas->FilteredSum = TK_Mem.FilteredSum;
    TK_Info.pTouchKeyDatas->RawDatasBuf = TK_Mem.RawDatasBuf;
    TK_Info.pTouchKeyChInfor->TouchKeyChSeq = TK_Mem.TouchKeyChSeq;
    TK_Info.pTkAreaInfor->TK_Area = TK_Mem.TK_Area;
    TK_Info.pTkAreaInfor->TK_AreaPending = TK_Mem.TK_AreaPending;
    TK_Info.pTK_TickCouter->TK_AreaConfirmTickCnt = TK_Mem.TK_AreaConfirmTickCnt;
    TK_Info.pTK_TickCouter->TK_KeyOutTimeLimitCnt = TK_Mem.TK_KeyOutTimeLimitCnt;
#if WATER_PROOF_EN
    TK_Info.pTouchKeyDatas->SingleAcqData = TK_Mem.SingleAcqData;
    TK_Info.pTouchKeyDatas->SingleFilteredData = TK_Mem.SingleFilteredData;
    TK_Info.pTouchKeyDatas->SingleBaseLineData = TK_Mem.SingleBaseLineData;
    TK_Info.pTouchKeyDatas->SingleAcqRawDatasBuf = TK_Mem.SingleAcqRawDatasBuf;
#endif
	TK_Info.pTouchKeyDatas->SyncWindow = NULL;
    /*	初始化按键通道	*/
    TKCtr.TouchKeyChCnt = KEY_CH_TOTAL;
    for (offset = 0; offset < TKCtr.TouchKeyChCnt; offset++)
    {
        TK_Info.pTouchKeyChInfor->TouchKeyChSeq[offset] = KEY_CH_TAB[offset];
        TK_Info.pTouchKeyDatas->FingerTHD[offset] = KEY_THD_TAB[offset];
    }
#if (SLIDER_OR_WHEEL_CH_TOTAL > 0)
    /*	初始化滑轮通道	*/
    TK_Info.pSliderChInfor->SliderWheelType = SLIDERORWHEEL_TYPE_TAB;
    TK_Info.pSliderChInfor->SliderWheelResloution = SLIDERORWHEEL_RESOLUTION_TAB;
    for (k = 0; k < SLIDER_MAX; k++)
    {
        TKCtr.SliderOrWheelPosition[k] = -1;
        TK_Info.pSliderChInfor->SliderWheelxChCnt[k] = 0;
        if (SLIDERORWHEEL_TYPE_TAB[k] == TK_APP_WHEEL || SLIDERORWHEEL_TYPE_TAB[k] == TK_APP_SLIDER)
        {
            TK_Info.pSliderChInfor->SliderWheelxStartChIdx[k] = offset;
            for (j = 0; j < 8; j++)
            {
                if (SLIDERORWHEEL_CH_TAB[k][j] == TK_CH_NONE)
                {
                    break;
                }
                TK_Info.pSliderChInfor->SliderWheelxChCnt[k]++;
            }
            n = offset;
            for (j = 0; j < TK_Info.pSliderChInfor->SliderWheelxChCnt[k]; j++)
            {
                TK_Info.pTouchKeyChInfor->TouchKeyChSeq[offset] = SLIDERORWHEEL_CH_TAB[k][j];
                TK_Info.pTouchKeyDatas->FingerTHD[offset] = 0;
                offset += 1;
            }
            TK_Info.pTouchKeyDatas->FingerTHD[n] = SLIDERORWHEEL_THD_TAB[k];
        }
    }
#endif
    ShieldInfor.WaterProof_En = WATER_PROOF_EN;
#if WATER_PROOF_EN
    ShieldInfor.WaterProof_Chs = WATER_SHIELD_CH;
    ShieldInfor.DusterCloth_En = DUSTERCLOTH_EN;
    ShieldInfor.DusterCloth_THD = DUSTERCLOTH_THD;
    ShieldInfor.Noise = 5; // 保护通道数据变化量在 -NoiseTHD ~ +NoiseTHD范围之间认为数据平稳
    /*	设置通道		*/
    ShieldInfor.ShieldStartChIdx = offset;
    TK_Info.pTouchKeyChInfor->TouchKeyChSeq[offset] = SHIELD_CHS;
    TK_Info.pTouchKeyDatas->FingerTHD[offset] = DUSTERCLOTH_THD;
    offset += 1;
#endif
#if (REF_CH_EN)
    TKCtr.InsideOffset = offset;
    TK_Info.pTouchKeyChInfor->TouchKeyChSeq[offset] = EXTERNAL_CHS;
    TK_Info.pTouchKeyDatas->FingerTHD[offset] = REF_CH_THD;
    offset += 1;
#else
    TKCtr.InsideOffset = TK_CH_NONE;
#endif
    /*	触摸扫描总数量	*/
    TK_Info.pTouchKeyChInfor->TouchAcqChCnt = TK_CHMAX;
    TK_Info.pTouchKeyChInfor->TouchAcqChCntDbg = TK_CHMAX;
#if (SLEEP_EN && STOP_DEBUG)
    sleepchs_idx = offset;
    TK_Info.pTouchKeyChInfor->TouchKeyChSeq[offset] = SLEEP_CHS;
    TK_Info.pTouchKeyDatas->FingerTHD[offset] = LP_NORMRMALDELTA;
    offset += 1;
    TK_Info.pTouchKeyChInfor->TouchAcqChCnt -= 1;
#endif
}
/**
 * @brief  TK寄存器初始化
 * @param  None
 * @retval None
 */
void TK_RegisterCfg(void)
{
#define st_clk 2 // ST时钟为2M，则2个计数为1us
    /*	触摸基本配置初始化	*/
#if (HSI_FREQUENCE == 48000000l)
    TK_Handle.Init.Div = TK_DIV2;      // 48M/2 = 24M
    TK_Handle.Init.Stdiv = TK_STDIV24; // 48M/24 = 2M
#else
    TK_Handle.Init.Div = TK_DIV0;      // 24M/1 = 24M
    TK_Handle.Init.Stdiv = TK_STDIV12; // 24M/12 = 2M
#endif
    TK_Handle.Init.PwmM = SW_MODE;
    TK_Handle.Init.ExtCmod = EXTCMOD;
    TK_Handle.Init.CmphysEnable = ENABLE;
    TK_Handle.Init.Cft = TK_CFT0;
    TK_Handle.Init.Vcc1Cr = CONFIG_VCC1;
    TK_Handle.Init.CopaData = COPADATA_OUTPUT;
    TK_Handle.Init.CopaMode = COPA_ENABLE;
    TK_Handle.Init.CopaChs = TKCtr.TK_KeyEnable;
    TK_Handle.Init.Kenable = TKCtr.TK_KeyEnable;
#if (SW_MODE == TK_PWMM_PRS)
    TK_Handle.Init.Lfsrw = PWMM_PRS_LFSRW;
    TK_Handle.Init.prsseed = PWMM_PRS_SEED;
#endif
    TK_Handle.Init.Swdiv = SW_DIV;
    TK_Handle.Init.SetTime = 256;
    TK_Handle.Init.Win = CONFIG_WIN;
    TK_Handle.Init.ShortswNum = TK_SHORTSW_NUM_0;
    TK_Handle.Init.Vref = CONFIG_VREF;
    TK_Handle.Init.TrimEnable = CONFIG_IDAC0;
#if CONFIG_IDAC0
    TK_Handle.Init.TrimRatio[0] = 70;
    TK_Handle.Init.TrimRatio[1] = 75;
#else
    TK_Handle.Init.MidacStep = TK_MIDACSTEP_0_5UA;
    TK_Handle.Init.Midac = 200;
#endif
    /*	低功耗初始化	*/
#if (SLEEP_EN)
    TKCtr.SleepEn = 1; // 允许休眠
    TK_Handle.Lp.EnterStopTimer = ENTER_SLEEPTIME;
    TK_Handle.Lp.LpWin = CONFIG_LP_WIN;
    TK_Handle.Lp.LpKchs = TKCtr.TK_KeyEnable;
    TK_Handle.Lp.Lpwait = 50 * st_clk;
    TK_Handle.Lp.Vref = CONFIG_LPVREF;
#if ((RTC_IRQ_ENABLE == 0 || RTC_SEC_IRQ_ENABLE == 0) && STOP_DEBUG)
    /*##- Configure RTC NVIC */
    NVIC_SetPriority(RTC_IRQn, 3);
    NVIC_EnableIRQ(RTC_IRQn);
    /* Enable second interrupt */
    LL_RTC_EnableIT_SEC(RTC);
    /* Enable RTC EXTI interrupt */
    LL_EXTI_EnableIT(LL_EXTI_LINE_19);
#else
    /* Enable TK second interrupt */
    LL_RTC_EnableIT_TK_SEC(RTC);
#endif
    DBGMCU->CR &= ~(0X03 << 0);
#else
    TKCtr.SleepEn = 0; // 禁止休眠
#endif
    TKCtr.SleepTime = 0;
	/*	使用触摸进行LED扫描	*/
#if (TK_SMG_ENABLE && APP_SMG_ENABLE)	
	TKCtr.LED_Count = 0;
	TKCtr.LED_DIM = TK_SMG_DIM;
#endif
#if (TK_LED_ENABLE && APP_LED_ENABLE)	
	TKCtr.LED_Count = 0;
	TKCtr.LED_DIM = TK_LED_DIM;
#endif
}

#if (SLEEP_EN)
/**
 * @brief 进入休眠调用函数
 * @param  None
 * @retval None
 */
static void EnterStop_Callback(void)
{
    /* Disable SysTick Interrupt */
    CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
    EXTI_Flag = 0;
#if APP_ADC_ENABLE
    /*	等待序列转换完成*/
    while (LL_ADC_REG_IsConversionOngoing(ADC1) == 1)
    {
        ;
    }
    LL_ADC_Disable(ADC1);
#endif
#if (APP_TIM1_ENABLE || APP_TIM1_PWM_ENABLE)
    LL_TIM_DeInit(TIM1);
#endif
#if (APP_TIM14_ENABLE || APP_TIM14_PWM_ENABLE)
    LL_TIM_DeInit(TIM14);
#endif
#if APP_SMG_ENABLE
    SMG_Sleep();
#endif
}
/**
 * @brief 退出休眠调用函数
 * @param  None
 * @retval None
 */
static void ExitStop_Callback(void)
{
    /*	触摸唤醒		*/
    if (TK_Handle.Lp.WakeChs != 0)
    {
        TKCtr.SleepTime = 0;
    }
    /*	外部中断唤醒标志位	*/
    if (EXTI_Flag != 0)
    {
        TKCtr.SleepTime = 0;
    }
#if APP_SMG_ENABLE
    SMG_Wake();
#endif
#if APP_ADC_ENABLE
    ADC_Init();
#endif
#if APP_TIM1_ENABLE
    /*	定时器1初始化	*/
    TIM1_Init();
#elif APP_TIM1_PWM_ENABLE
    /*	定时器1用做PWM输出初始化	*/
    TIM1_PWM_Init();
#endif
#if APP_TIM14_ENABLE
    /*	定时器14初始化	*/
    TIM14_Init();
#elif APP_TIM14_PWM_ENABLE
    /*	定时器14用做PWM输出初始化	*/
    TIM14_PWM_Init();
#endif
    /* Enable SysTick Interrupt */
    SET_BIT(SysTick->CTRL, SysTick_CTRL_TICKINT_Msk);
}
/**
 * @brief 定时唤醒回调函数
 * @param  None
 * @retval None
 */
static void LoopStop_Callback(void)
{
#if APP_IWDG_ENABLE
    /* 喂看门狗 */
    LL_IWDG_ReloadCounter(IWDG);
#endif
    /*	外部中断唤醒标志位,退出休眠	*/
    if (EXTI_Flag != 0)
    {
        TKCtr.TK_state = TK_GO;
    }
}
/**
 * @brief 触摸配置休眠
 * @param  None
 * @retval None
 */
static uint8_t LpInit = 0;
static TK_Status TK_LpInit(void)
{
    if (READ_BIT(TK->CR2, TK_CR2_START))
        return TK_BUSY;
    /*	清空计数值	*/
    CLEAR_BIT(TK->CR2, TK_CR2_RSTB);
    while (READ_BIT(TK->CR2, TK_CR2_RSTB) != TK_CR2_RSTB)
    {
        ;
    }
    TK->CR1 &= ~TK_CR1_EN;
    TK->CSR = TK_Handle.Lp.LpKchs;
    if (LpInit == 0)
    {
        CLEAR_BIT(TK->CR1, TK_CR1_COPAMODE);
        MODIFY_REG(TK->CR2, TK_CR2_KVREF, TK_Handle.Lp.Vref << TK_CR2_KVREF_Pos);
        if (TK_Handle.Init.TrimEnable)
        {
            SET_BIT(TK->CR1, TK_CR1_MIDACSTEP);
            MODIFY_REG(TK->IDACR, TK_IDACR_MIDAC, TK_Handle.Lp.LpDac << TK_IDACR_MIDAC_Pos);
        }
        TK->WR = TK_Handle.Lp.LpWin;
        SET_BIT(TK->CR2, TK_CR2_LPABNORMAL);
        TK->LPTR = TK_Handle.Lp.Lpwait;
        TK->LPDR = TK_Handle.Lp.NormalDelta << TK_LPDR_ABNORMALDELTA_Pos | TK_Handle.Lp.NormalDelta
                                                                               << TK_LPDR_NORMALDELTA_Pos;
    }
    LpInit = 1;
    TK->CDR = TK_Handle.Lp.Baseline;
    SET_BIT(TK->CR2, TK_CR2_CTRLSOURCE);
    SET_BIT(TK->CR2, TK_CR2_LPEN);
    TK_Handle.Lp.LpIsr = 0;
    return TK_OK;
}
/**
 * @brief 触摸退出休眠
 * @param  None
 * @retval None
 */
static void TK_LpDeInit(void)
{
    LpInit = 0;
    TK->CR1 |= TK_CR1_EN;
    TK->WR = TK_Handle.Init.Win;
    MODIFY_REG(TK->CR2, TK_CR2_KVREF, TK_Handle.Init.Vref << TK_CR2_KVREF_Pos);
    TK->CSR = 0;
    if (TK_Handle.Init.CopaMode == 1)
        SET_BIT(TK->CR1, TK_CR1_COPAMODE);
    else
        CLEAR_BIT(TK->CR1, TK_CR1_COPAMODE);
    CLEAR_BIT(TK->CR2, TK_CR2_LPEN);
}
/*******************************************************************************
 * 函数名	: PWR_EnterStopMode
 * 描述	    : 执行STOP模式
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
static void PWR_EnterStopMode(void)
{
#if STOP_DEBUG
    /* Request Wait For Interrupt */
    __WFI();
#else
#define WakeUpHsiEnableTime LL_PWR_WAKEUP_HSION_IMMEDIATE
#define SramRetentionVolt LL_PWR_SRAM_RETENTION_VOLT_STOP
#define FlashDelay LL_PWR_WAKEUP_FLASH_DELAY_5US
    MODIFY_REG(PWR->CR1, (PWR_CR1_HSION_CTRL | PWR_CR1_SRAM_RETV_CTRL | PWR_CR1_FLS_SLPTIME),
               (WakeUpHsiEnableTime | SramRetentionVolt | FlashDelay));
    /* Config Regulator */
    MODIFY_REG(PWR->CR1, PWR_CR1_LPR, LL_PWR_LPR_MODE_LPR);
    /* Set SLEEPDEEP bit of Cortex System Control Register */
    SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
    /* Request Wait For Event */
    __SEV();
    __WFE();
    __WFE();
    /* Reset SLEEPDEEP bit of Cortex System Control Register */
    CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
#endif
}
#if (RTC_IRQ_ENABLE && RTC_SEC_IRQ_ENABLE || STOP_DEBUG)
/*******************************************************************************
 * 函数名	: void TK_SetSenseStart_LP(void)
 * 描述	    : 调试模式手动启动转换
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
static void TK_SetSenseStart_LP(void)
{
    TK->CR1 |= TK_CR1_EN;
    /*	正常转换		*/
    CLEAR_BIT(TK->CR2, TK_CR2_RSTB);
    while (READ_BIT(TK->CR2, TK_CR2_RSTB) != TK_CR2_RSTB)
    {
        ;
    }
    TK->WR = TK_Handle.Lp.LpWin;
    TK->CSR = TK_Handle.Lp.LpKchs;
    SET_BIT(TK->CR2, TK_CR2_CTRLSOURCE);
    SET_BIT(TK->CR2, TK_CR2_START);
    TK_Handle.Lp.LpIsr = 0;
    while (TK_Handle.Lp.LpIsr == 0)
    {
        /* Request Wait For Interrupt */
        __WFI();
    }
}
#endif
/**
 * @brief  获取唤醒通道
 * @param  none
 *
 * @retval
 */
static uint32_t TK_GetWakeChs(void)
{
    uint32_t WakeChs = 0;
    TK_Handle.Lp.WakeDelay = 1;
    TKCtr.TK_state = TK_EXITSLEEP;
    RawDatasAcquisitionState = STATE_IDLE;
    while (1)
    {
        /*	空闲状态启动转换		*/
        if (RawDatasAcquisitionState == STATE_IDLE)
        {
            TK_MultiChAcqStart();
        }
        /*	多通道转换完成		*/
        else if (RawDatasAcquisitionState == STATE_MULTI_CH_ACQ_DONE)
        {
            uint8_t i;
            uint16_t Differ;
            /*	比较通道数据，看下是哪个通道唤醒的	*/
            // 按键唤醒
            for (i = 0; i < TKCtr.TouchKeyChCnt; i++)
            {
                if (TK_Info.pTouchKeyDatas->RawData[i] >= TK_Info.pTouchKeyDatas->BaseLineData[i])
                    Differ = TK_Info.pTouchKeyDatas->RawData[i] - TK_Info.pTouchKeyDatas->BaseLineData[i];
                else
                    Differ = TK_Info.pTouchKeyDatas->BaseLineData[i] - TK_Info.pTouchKeyDatas->RawData[i];
                if (Differ >= (TK_Info.pTouchKeyDatas->FingerTHD[i] >> 1))
                {
                    WakeChs |= (1 << i);
                }
            }
#if (SLIDER_OR_WHEEL_CH_TOTAL > 0)
            // 滑条唤醒
            uint8_t n, Offset, max, max_l, max_r;
            uint16_t del_val[8] = {0};
            uint16_t max_val, sum;
            for (n = 0; n < SLIDER_MAX; n++)
            {
                if (TK_Info.pSliderChInfor->SliderWheelxChCnt[n] != 0)
                {
                    Offset = TK_Info.pSliderChInfor->SliderWheelxStartChIdx[n];
                    for (i = Offset, max = 0, max_val = 0; i < TK_Info.pSliderChInfor->SliderWheelxChCnt[n] + Offset;
                         i++)
                    {
                        if (TK_Info.pTouchKeyDatas->RawData[i] >= TK_Info.pTouchKeyDatas->BaseLineData[i])
                            Differ = TK_Info.pTouchKeyDatas->RawData[i] - TK_Info.pTouchKeyDatas->BaseLineData[i];
                        else
                            Differ = TK_Info.pTouchKeyDatas->BaseLineData[i] - TK_Info.pTouchKeyDatas->RawData[i];
                        if (Differ > 0)
                            del_val[i - Offset] = Differ;
                        else
                            del_val[i - Offset] = 0;
                        if (del_val[i - Offset] > max_val)
                        {
                            max = i - Offset;
                        }
                    }
                    if (max > 0)
                        max_l = max - 1;
                    else
                        max_l = TK_Info.pSliderChInfor->SliderWheelxChCnt[n] - 1;
                    if (max < (TK_Info.pSliderChInfor->SliderWheelxChCnt[n] - 1))
                        max_r = max + 1;
                    else
                        max_r = 0;
                    sum = del_val[max_r] + del_val[max] + del_val[max_l];
                    if (sum >= TK_Info.pTouchKeyDatas->FingerTHD[Offset])
                    {
                        WakeChs |= (1 << Offset);
                    }
                }
            }
#endif
            break;
        }
        /*	进入SLEEP模式，如果不进入休眠则需要添加volatile，不然RawDatasAcquisitionState访问会异常*/
        else
        {
            __WFI();
        }
    }
    TKCtr.TK_state = TK_ENTERSLEEP;
    return WakeChs;
}
/*******************************************************************************
 * 函数名	: TK_EnterStop
 * 描述	    : 进入低功耗模式
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
void TK_EnterStop(void)
{
    uint16_t Differ;
    /*	开始执行修眠	*/
    EnterStop_Callback();
    do
    {
        if (TK_Handle.Lp.LpCdr == 0)
        {
            TK_Handle.Lp.NormalDelta = 0;
        }
        else
        {
#if (RTC_IRQ_ENABLE && RTC_SEC_IRQ_ENABLE)
            TK_Handle.Lp.NormalDelta = 0;
#else
            TK_Handle.Lp.NormalDelta = LP_NORMRMALDELTA;
#endif
        }
        if (TK_LpInit() == TK_OK)
        {
            PWR_EnterStopMode();
#if ((RTC_IRQ_ENABLE && RTC_SEC_IRQ_ENABLE) || STOP_DEBUG)
            TK_SetSenseStart_LP();
#if STOP_DEBUG // 调试模式更新数据
            TK_Info.pTouchKeyDatas->FilteredDataDBG[sleepchs_idx] = TK_Handle.Lp.LpCdr;
            TK_Info.pTouchKeyDatas->BaseLineDataDBG[sleepchs_idx] = TK_Handle.Lp.Baseline;
            DebugDataUpdate();
#endif
#endif
            if (TK_Handle.Lp.LpIsr != 0) // 触摸唤醒
            {
                if (TK_Handle.Lp.LpCdr > TK_Handle.Lp.Baseline)
                    Differ = TK_Handle.Lp.LpCdr - TK_Handle.Lp.Baseline;
                else
                    Differ = TK_Handle.Lp.Baseline - TK_Handle.Lp.LpCdr;
                if (Differ >= LP_NORMRMALDELTA)
                {
                    TK_LpDeInit();
                    TK_Handle.Lp.Baseline = TK_Handle.Lp.LpCdr;
                    TK_Handle.Lp.WakeChs = TK_GetWakeChs();
                    if (TK_Handle.Lp.WakeChs != 0)
                    {
                        TKCtr.TK_state = TK_GO;
                    }
                }
                else
                {
                    if (TK_Handle.Lp.Baseline < TK_Handle.Lp.LpCdr)
                        TK_Handle.Lp.Baseline++;
                    else if (TK_Handle.Lp.Baseline > TK_Handle.Lp.LpCdr)
                        TK_Handle.Lp.Baseline--;
                }
            }
            LoopStop_Callback();
        }
        else
        {
            TKCtr.TK_state = TK_GO;
        }
    } while (TKCtr.TK_state != TK_GO);
    TK_LpDeInit();
    ExitStop_Callback();
}
#else
void TK_EnterStop(void)
{
	
}
#endif
#if (REF_CH_EN)
#define INSIDE_CNT 50
static uint16_t Inside_Raw[INSIDE_CNT];
static uint16_t Inside_Cnt;
#endif
/**
 * @brief 内部参考通道数据初始化
 * @param  None
 * @retval None
 */
void Inside_Init(uint16_t raw)
{
#if (REF_CH_EN)
    for (uint32_t i = 0; i < INSIDE_CNT; i++)
    {
        Inside_Raw[i] = raw;
    }
#endif
}
/**
 * @brief 内部参考通道入队
 * @param  None
 * @retval None
 */
void Inside_In(uint16_t raw)
{
#if (REF_CH_EN)
    Inside_Cnt++;
    if (Inside_Cnt >= INSIDE_CNT)
        Inside_Cnt = 0;
    Inside_Raw[Inside_Cnt] = raw;
#endif
}
/**
 * @brief 内部参考通道出队
 * @param  None
 * @retval None
 */
uint16_t Inside_Dif(uint16_t raw, uint16_t *base)
{
    uint32_t max = 0;
#if (REF_CH_EN)
    uint32_t del;
    for (uint32_t i = 0; i < INSIDE_CNT; i++)
    {
        if (raw > Inside_Raw[i])
            del = raw - Inside_Raw[i];
        else
            del = Inside_Raw[i] - raw;
        if (del > max)
        {
            max = del;
            *base = Inside_Raw[i];
        }
    }
#endif
    return max;
}
/**
 * @brief 内部参考通道差值比较
 * @param  None
 * @retval None
 */
void InsideTrigger(uint16_t InsideDif, uint16_t Thd)
{
#if (REF_CH_EN)
    if (InsideDif > Thd) // 数据变化量超过门限值
    {
        for (uint32_t i = 0; i < TKCtr.TouchKeyChCnt; i++)
        {
            if (TKCtr.KeyFlagsPending & (1 << i))
                TK_UpdatBaseLineData(i);
        }
    }
#endif
}
#if WATER_PROOF_EN
const uint16_t Ratio_Tbl[TK_CHMAX][2] = 
{
	{25, 70}, 
	{25, 70}, 
	{25, 70}, 
	{25, 70}, 
	{25, 70}, 
	{25, 70}, 
	{25, 70}, 
	{25, 70}, 
	{25, 70},
};
#endif
/**
 * @brief TK按键特殊处理
 * @param  None
 * @retval None
 */
uint32_t APP_TouchKeyFlagsMask(void)
{
#if (SLEEP_EN)
    TKCtr.SleepTime = 0; // 按键变化，计时清0
#endif
#if WATER_PROOF_EN
    static uint8_t last_key = TK_CH_NONE;
    static uint16_t last_Differ;
    uint32_t KeyFlags = 0;
    uint8_t now_key = TK_CH_NONE;
    int16_t Differ = 0;
    int16_t ratio;
#if MAX_TRIGGER_KEY_CNT
    uint32_t num = 0;
#endif
    for (uint32_t i = 0; i < TKCtr.TouchKeyChCnt; i++)
    {
        if (TKCtr.KeyFlagsPending & (0X01UL << i))
        {
			/*	获取变化量最大的通道	*/
            if (Differ < TK_Info.pTouchKeyDatas->Differ[i])
            {
                Differ = TK_Info.pTouchKeyDatas->Differ[i];
                now_key = i;
            }
#if MAX_TRIGGER_KEY_CNT
            num++;
#endif
        }
    }
    /*	按键触发		*/
    if (now_key != TK_CH_NONE)
    {
        if (last_key != now_key)
        {
            int16_t SingleAcqDif;
            SingleAcqDif = TK_Info.pTouchKeyDatas->SingleFilteredData[now_key] -
                           TK_Info.pTouchKeyDatas->SingleBaseLineData[now_key];
            ratio = SingleAcqDif * 100 / TK_Info.pTouchKeyDatas->Differ[now_key];
#if DUSTERCLOTH_EN
            if (TK_Info.pTouchKeyDatas->Differ[ShieldInfor.ShieldStartChIdx] > DUSTERCLOTH_THD)
            {
                ShieldInfor.WaterState = 3;
                ShieldInfor.WaterProof_Time = 500;
                return 0;
            }
#endif
            /*	水流	*/
            if (ratio > Ratio_Tbl[now_key][1])
            {
                ShieldInfor.WaterState = 2;
                log_printf("ratio type2:%d %d\r\n", now_key, ratio);
            }
            /*	覆水	*/
            else if (ratio < Ratio_Tbl[now_key][0])
            {
#if WATER_PROOF_MODE
                ShieldInfor.WaterState = 2;
#else
                ShieldInfor.WaterState = 1;
#endif
                log_printf("ratio type1:%d %d\r\n", now_key, ratio);
            }
            else
            {
                log_printf("ratio type0:%d %d\r\n", now_key, ratio);
#if MAX_TRIGGER_KEY_CNT
                /*	多按键同时触发更新环境值	*/
                if (num > MAX_TRIGGER_KEY_CNT)
                {
                    for (uint32_t i = 0; i < TKCtr.TouchKeyChCnt; i++)
                    {
                        if (TKCtr.KeyFlagsPending & (0X01UL << i))
                            TK_UpdatBaseLineData(i);
                    }
                }
#endif
#if (SIGLE_KEY_TRIGGER)
                ShieldInfor.WaterState = 1;
#endif
            }
        }
        /*	无水状态*/
        if (ShieldInfor.WaterState == 0)
        {
            KeyFlags = TKCtr.KeyFlagsPending;
            last_key = now_key;
        }
        /*	有水状态*/
        else if (ShieldInfor.WaterState == 1)
        {
            if (last_key == TK_CH_NONE)
            {
                last_Differ = TK_Info.pTouchKeyDatas->Differ[now_key];
                last_key = now_key;
                KeyFlags = 1 << now_key;
            }
            else
            {
                if (TKCtr.KeyFlagsPending & (0X01UL << last_key))
                {
                    Differ = last_Differ - TK_Info.pTouchKeyDatas->Differ[last_key];
                    if (Differ > 15)
                    {
                        last_Differ = TK_Info.pTouchKeyDatas->Differ[now_key];
                        last_key = now_key;
                        KeyFlags = 1 << now_key;
                    }
                    else
                    {
                        KeyFlags = 1 << last_key;
                    }
                }
                else
                {
                    KeyFlags = 1 << now_key;
                    last_key = now_key;
                }
            }
        }
        else
        {
            last_key = TK_CH_NONE;
        }
    }
    else
    {
        last_key = TK_CH_NONE;
    }
    return KeyFlags;
#else
#if MAX_TRIGGER_KEY_CNT
    uint32_t num = 0;
    for (uint32_t i = 0; i < TKCtr.TouchKeyChCnt; i++)
    {
        if (TKCtr.KeyFlagsPending & (0X01UL << i))
            num++;
    }
    /*	多按键同时触发更新环境值	*/
    if (num > MAX_TRIGGER_KEY_CNT)
    {
        for (uint32_t i = 0; i < TKCtr.TouchKeyChCnt; i++)
        {
            if (TKCtr.KeyFlagsPending & (0X01UL << i))
                TK_UpdatBaseLineData(i);
        }
    }
#endif
#if (SIGLE_KEY_TRIGGER)
    /*	单键触发		*/
    static uint8_t last_key = TK_CH_NONE;
	static uint16_t last_Differ;
    uint32_t KeyFlags = 0;
    uint8_t now_key = TK_CH_NONE;
    int16_t Differ = 0;
    for (uint32_t i = 0; i < TKCtr.TouchKeyChCnt; i++)
    {
        if (TKCtr.KeyFlagsPending & (0X01UL << i))
        {
            if (Differ < TK_Info.pTouchKeyDatas->Differ[i])
            {
                Differ = TK_Info.pTouchKeyDatas->Differ[i];
                now_key = i;
            }
        }
    }
    /*	按键触发		*/
    if (now_key != TK_CH_NONE)
    {
        if (last_key == TK_CH_NONE)
		{
			last_Differ = TK_Info.pTouchKeyDatas->Differ[now_key];
			last_key = now_key;
			KeyFlags = 1 << now_key;
		}
		else
		{
			if (TKCtr.KeyFlagsPending & (0X01UL << last_key))
			{
				Differ = last_Differ - TK_Info.pTouchKeyDatas->Differ[last_key];
				if (Differ > 15)
				{
					last_Differ = TK_Info.pTouchKeyDatas->Differ[now_key];
					last_key = now_key;
					KeyFlags = 1 << now_key;
				}
				else
				{
					KeyFlags = 1 << last_key;
				}
			}
			else
			{
				KeyFlags = 1 << now_key;
				last_key = now_key;
			}
		}
    }
    else
    {
        KeyFlags = 0;
    }
    return KeyFlags;
#else
    return TKCtr.KeyFlagsPending;
#endif
#endif
}
#if (SLIDER_OR_WHEEL_CH_TOTAL == 0)
/*******************************************************************************
 * 函数名	: uint8_t APP_TouchSliderOrWheelChs(uint8_t chs)
 * 描述	    : 占位，无需处理
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
uint8_t APP_TouchSliderOrWheelChs(uint8_t chs)
{
    return chs;
}
/*******************************************************************************
 * 函数名	: void APP_TouchSliderOrWheelProc(void)
 * 描述	    : 占位，无需处理
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
void APP_TouchSliderOrWheelProc(void)
{
	
}
#endif
#if (WATER_PROOF_EN == 0)
/*******************************************************************************
 * 函数名	: uint8_t WaterProof_Evt(uint8_t Evt,uint8_t chs)
 * 描述	    : 占位，无需处理
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
uint8_t WaterProof_Evt(uint8_t Evt,uint8_t chs)
{
	return 0;
}
/*******************************************************************************
 * 函数名	: uint8_t WaterProof_Isr(uint8_t Isr)
 * 描述	    : 占位，无需处理
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
uint8_t WaterProof_Isr(uint8_t Isr)
{
	return 0;
}
#endif
#if (SYNC_SENSITVITY == 0)
/*******************************************************************************
 * 函数名	: uint8_t SyncSamplingCallback(uint8_t *raw_cnt,uint16_t *raw_ref)
 * 描述	    : 占位，无需处理
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
uint8_t SyncSamplingCallback(uint8_t *raw_cnt,uint16_t *raw_ref)
{
	return 0;
}
#endif
/*******************************************************************************
 * 函数名	: void TK_LedCallback(uint8_t State)
 * 描述	    : LED扫描
 * 输入参数  : 无
 * 返回参数  : 无
 *******************************************************************************/
void TK_LedCallback(uint8_t State)
{
#if (TK_SMG_ENABLE && APP_SMG_ENABLE)
	TK_SMG_Scan(State);
#endif
#if (TK_LED_ENABLE && APP_LED_ENABLE)
	TK_LED_Scan(State);
#endif
}
#else
/**
 * @brief  TK用户参数初始化
 * @param  None
 * @retval None
 */
void TK_UserParaInit(void)
{

}
/**
 * @brief  TK寄存器初始化
 * @param  None
 * @retval None
 */
void TK_RegisterCfg(void)
{

}
/**
 * @brief TK按键特殊处理
 * @param  None
 * @retval None
 */
uint32_t APP_TouchKeyFlagsMask(void)
{
    return 0;
}
/**
 * @brief 内部参考通道数据初始化
 * @param  None
 * @retval None
 */
void Inside_Init(uint16_t raw)
{

}
/**
 * @brief 内部参考通道入队
 * @param  None
 * @retval None
 */
void Inside_In(uint16_t raw)
{

}
/**
 * @brief 内部参考通道出队
 * @param  None
 * @retval None
 */
uint16_t Inside_Dif(uint16_t raw, uint16_t *base)
{
    return 0;
}
/**
 * @brief 内部参考通道差值比较
 * @param  None
 * @retval None
 */
void InsideTrigger(uint16_t InsideDif, uint16_t Thd)
{

}

void TK_EnterStop(void)
{

}

void TK_LedCallback(uint8_t State)
{

}
#endif
