


/**
 ******************************************************************************
 *
 * @file      BSP_TouchKey.c
 * @brief     The file is Touch key C code. 
 *
 * @par       Project
 *            MG32
 * @version   V1.00
 * @date      2022/08/01
 * @author    Megawin Software Center
 * @copyright Copyright (c) 2017 MegaWin Technology Co., Ltd.
 *            All rights reserved.
 * 
 ******************************************************************************* 
 * @par Disclaimer
 * The Demo software is provided "AS IS" without any warranty, either
 * expressed or implied, including, but not limited to, the implied warranties
 * of merchantability and fitness for a particular purpose. The author will
 * not be liable for any special, incidental, consequential or indirect
 * damages due to loss of data or any other reason.
 * These statements agree with the world wide and local dictated laws about
 * authorship and violence against these laws.
 *******************************************************************************
 *******************************************************************************
 */
/*==============================================================================
                                 User NOTES
How To use this function: 
   + Decide to detect which touch line by setting TK_CONF.Scan_Key = Scan_PAD0 or Scan_PAD1.
   + Charge touch key (use API_TouchKeyCharge_Cmd function ) before get touch key status. 
   + Use API_TouchKey_GetStatus function to get touch key status.
   + After getting Touch key status to stop charge touch key.

Driver & middleware architecture:
--------------------
   + MG32_GPIO_DRV
   + MG32_ADC_MID
   + MG32_TM_DRV

==============================================================================*/
 
 
/* Includes ------------------------------------------------------------------*/
#include "BSP_TouchKey.h"

/* Wizard menu ---------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
Touch_ConfigTypeDef TK_CONF;

static uint8_t TK_DAT_CNT;

/* Private function prototypes -----------------------------------------------*/
static void API_Touchkey_GetData(void);
static uint16_t API_TouchKey_GetChannelxDefaultData(uint8_t TKGet_Chx);

/* Exported variables --------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/* External variables --------------------------------------------------------*/
 

/**
 *******************************************************************************
 * @brief	  BSP touch key initial. 
 * @details   
 * @return    
 * @exception No
 * @note      Becase ADC share with SARADC key, ADC initial in BSP_Common_MG04_06.c                    
 *******************************************************************************
 */
void BSP_TouchKey_Init(void)
{
    TM_TimeBaseInitTypeDef TM_TimeBase_InitStruct;    
//    ADC_InitTypeDef        ADC_BastInitTmp;
    
    /*GPIO Initial.*/
    BSP_GPIO_PinConfig(TOUCHKEY_PWM0_IOM,Data_DIR_OUT_PP,TOUCHKEY_PWM0_AFS);
    BSP_GPIO_PinConfig(TOUCHKEY_PWM1_IOM,Data_DIR_OUT_PP,TOUCHKEY_PWM1_AFS);
    
    BSP_GPIO_PinConfig(TOUCHKEY_AIN0_IOM,Analog_Mode,0);
    BSP_GPIO_PinConfig(TOUCHKEY_AIN1_IOM,Analog_Mode,0);
    
    
    /*TP_KEY0 & TP_KEY1 PWM Init( use TM36)*/
    TM_DeInit(TM36);
    TM_TimeBaseStruct_Init(&TM_TimeBase_InitStruct);
    
    TM_TimeBase_InitStruct.TM_MainClockDirection = TM_UpCount;
    TM_TimeBase_InitStruct.TM_Prescaler          = 1 - 1;
    TM_TimeBase_InitStruct.TM_Period             = 480 - 1; 
    TM_TimeBase_InitStruct.TM_CounterMode        = Cascade;
    TM_TimeBase_Init(TM36, &TM_TimeBase_InitStruct);         // PWM Frequence.
    
    TM_CH0Function_Config(TM36, TM_16bitPWM);
    TM_CH1Function_Config(TM36, TM_16bitPWM);
    
    //TP_KEY0 PWM
    TM_OC00Output_Cmd(TM36,DISABLE);  
    TM_InverseOC0z_Cmd(TM36, DISABLE);
    TM_OC0zOutputState_Init(TM36, CLR);
    
    TM_SetCC0A(TM36,240);                         
    TM_SetCC0B(TM36,240);		                 // reload value when overflow ( H level)
    TM_AlignmentMode_Select(TM36, TM_EdgeAlign);
    
    //TP_KEY1_PWM
    TM_OC10Output_Cmd(TM36,DISABLE);    
    TM_InverseOC1z_Cmd(TM36, DISABLE);
    TM_OC1zOutputState_Init(TM36, CLR);
    
    TM_SetCC1A(TM36,240);        
    TM_SetCC1B(TM36,240);		                 // reload value when overflow ( H level)
    
    //Timer Enable
    TM_Timer_Cmd(TM36,ENABLE);
    
    /* 2. Config ADC base parameter.
      ADC common use for the other peripherals, so ADC Initial in common C file.
    */
//    /*Configure ADC base parameter*/
//    ADC_BastInitTmp.ADCMainClockSelect   = ADC_CKADC;
//    ADC_BastInitTmp.ADC_IntCK_Div        = ADC_IntDIV2;
//    ADC_BastInitTmp.ADC_CKPLL_Div        = ADC_PLLDIV2;
//    ADC_BastInitTmp.ADC_DataAlign        = ADC_RightJustified;
//    ADC_BastInitTmp.ADC_ResolutionSel    = ADC_12BitData;
//    ADC_BastInitTmp.ADC_DataOverrunEvent = ADC_DataOverWritten;
//    
//    ADC_Base_Init(MG04_06_ADC, &ADC_BastInitTmp);
//    
//    /*Enable ADC*/
//    ADC_Cmd(MG04_06_ADC,ENABLE);
//    
//    /*Configure ADC mode*/
//    //One-shot 
//    ADC_ConversionMode_Select(MG04_06_ADC, ADCMode); 
//    //Single mode.
//    ADC_SingleDifferentMode_Select(MG04_06_ADC, ADC_SingleMode);
//    
//    /*Clear all flag*/
//    ADC_ClearFlag(MG04_06_ADC, 0xFFFFFFFF);
//    
//    /*Start calibration*/
//    ADC_StartCalibration(MG04_06_ADC, ENABLE);
//    
//    /*Input channel Mux is external channel.*/
//    ADC_ChannelMUX_Select( MG04_06_ADC, ADC_ExternalChannel);
//    
//    /*Trigger source select*/
//    ADC_TriggerSource_Select(MG04_06_ADC, ADC_START);
     
    /*Parameter Initial*/
    TK_CONF.Scan_Key  = Scan_PAD0;
    TK_DAT_CNT        = 0;
}
/**
 *******************************************************************************
 * @brief	  To control whether charging for touch key or not.
 * @details   Use Timer PWM to charge.
 * @return    
 * @exception No
 * @note                          
 *******************************************************************************
 */
void API_TouchKeyCharge_Cmd(FunctionalState Charge_Cmd)
{
    if( TK_CONF.Scan_Key == Scan_PAD0)
    {
        TM_OC00Output_Cmd(TM36,Charge_Cmd);
        
        if( Charge_Cmd == DISABLE)
        {
            TM_OC0zOutputState_Init(TM36, CLR);
        }
    }
    else
    {
        TM_OC10Output_Cmd(TM36,Charge_Cmd);

        if( Charge_Cmd == DISABLE) 
        {
            TM_OC1zOutputState_Init(TM36, CLR);
        }
    }
}
/**
 *******************************************************************************
 * @brief	   To get touch key status.
 * @details     
 * @return      
 * @exception  No 
 * @note                        
 *******************************************************************************
 */
uint16_t API_TouchKey_GetStatus(void)
{
    uint16_t TouchKey_GetStatusTmp;
    
    API_Touchkey_GetData();

    TouchKey_GetStatusTmp = API_TouchKey_GetChannelxDefaultData(0);
    
    if(TK_CONF.TK_ADCx_DAT[0]>(TouchKey_GetStatusTmp-TK_HappenMIN)&&
       TK_CONF.TK_ADCx_DAT[0]<(TouchKey_GetStatusTmp-TK_HappenMAX))
    {
        switch(TK_CONF.Scan_Key)
        {
            case Scan_PAD0:
                            TK_CONF.KEY_STA |= TK_KEY0F;
                            break;
            case Scan_PAD1:
                            TK_CONF.KEY_STA |= TK_KEY2F;
                            break;
            default:
                            break;
        }
    }
    else
    {
        switch(TK_CONF.Scan_Key)
        {
            case Scan_PAD0:
                            TK_CONF.KEY_STA &= ~TK_KEY0F;
                            break;
            case Scan_PAD1:
                            TK_CONF.KEY_STA &= ~TK_KEY2F;
                            break;
            default:
                            break;
        }
    }
    
    TouchKey_GetStatusTmp = API_TouchKey_GetChannelxDefaultData(1);
    
    if(TK_CONF.TK_ADCx_DAT[1]>(TouchKey_GetStatusTmp-TK_HappenMIN)&&
       TK_CONF.TK_ADCx_DAT[1]<(TouchKey_GetStatusTmp-TK_HappenMAX))
    {
        switch(TK_CONF.Scan_Key)
        {
            case Scan_PAD0:
                            TK_CONF.KEY_STA |= TK_KEY1F;
                            break;
            case Scan_PAD1:
                            TK_CONF.KEY_STA |= TK_KEY3F;
                            break;
            default:
                            break;
        }
    }
    else
    {
        switch(TK_CONF.Scan_Key)
        {
            case Scan_PAD0:
                            TK_CONF.KEY_STA &= ~TK_KEY1F;
                            break;
            case Scan_PAD1:
                            TK_CONF.KEY_STA &= ~TK_KEY3F;
                            break;
            default:
                            break;
        }
    }
    
    return TK_CONF.KEY_STA;
}
/**
 *******************************************************************************
 * @brief	   SPI interface initial for Flash. 
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
__WEAK void BSP_TouchKey_InitCallback(void)
{    
    //=========================================================
    //NOTE : This function should not be modifyed, when the 
    //       callback is needed, the MID_URT_RxCpltCallback 
    //       can be implemented in the user file.
}
/**
 *******************************************************************************
 * @brief	   SPI interface initial for Flash. 
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static void API_Touchkey_GetData(void)
{
    uint16_t   TK_ADCx_GetData_cnt;
    uint32_t   TK_ADCx_CAL_CH2;
    uint32_t   TK_ADCx_CAL_CH3;
    
    TK_ADCx_CAL_CH2 = 0;
    TK_ADCx_CAL_CH3 = 0;
    
    for(TK_ADCx_GetData_cnt=0;TK_ADCx_GetData_cnt<ADCx_SMP_CNT;TK_ADCx_GetData_cnt++)
    {
        ADC0->START.MBIT.CH_MUX = TOUCHKEY_AIN0_Channel;
        while(ADC0->STA.MBIT.CNV_CH!=TOUCHKEY_AIN0_Channel);
        ADC0->START.MBIT.START = ENABLE;
        while(ADC0->STA.MBIT.E1CNVF==0);
        TK_ADCx_CAL_CH2 += ADC0->DAT0.MBIT.DAT0;
        ADC0->STA.W = ADC_STA_E1CNVF_mask_w;
        
        ADC0->START.MBIT.CH_MUX = TOUCHKEY_AIN1_Channel;
        while(ADC0->STA.MBIT.CNV_CH!=TOUCHKEY_AIN1_Channel);
        ADC0->START.MBIT.START = ENABLE;
        while(ADC0->STA.MBIT.E1CNVF==0);
        TK_ADCx_CAL_CH3 += ADC0->DAT0.MBIT.DAT0;
        ADC0->STA.W = ADC_STA_E1CNVF_mask_w; 
    }

    TK_ADCx_CAL_CH2 = TK_ADCx_CAL_CH2/(ADCx_SMP_CNT);
    TK_CONF.TK_ADCx_DAT[0] = (uint16_t)TK_ADCx_CAL_CH2;
    
    TK_ADCx_CAL_CH3 = TK_ADCx_CAL_CH3/(ADCx_SMP_CNT);
    TK_CONF.TK_ADCx_DAT[1] = (uint16_t)TK_ADCx_CAL_CH3;
    
    // Default data check and update.
    if(TK_CONF.TK_ADCx_DAT[0]>TK_Basic_Default)
        TK_CONF.Touch_Basic_Data0[TK_DAT_CNT] = TK_CONF.TK_ADCx_DAT[0];
    
    if(TK_CONF.TK_ADCx_DAT[1]>TK_Basic_Default)
        TK_CONF.Touch_Basic_Data1[TK_DAT_CNT] = TK_CONF.TK_ADCx_DAT[1];
    
    TK_DAT_CNT++;
    if(TK_DAT_CNT>=ADCx_SMP_CNT)
        TK_DAT_CNT = 0;
}
/**
 *******************************************************************************
 * @brief	    
 * @details     
 * @return      
 * @exception   
 * @note        
 *******************************************************************************
 */
static uint16_t API_TouchKey_GetChannelxDefaultData(uint8_t TKGet_Chx)
{
    uint8_t  ifun_DAT_CNT;
    uint16_t ifun_DEF_DAT;
    uint32_t ifun_DAT_CAL;
    uint16_t *TK_BasicData;
    
    if(TKGet_Chx==0)
    {
        TK_BasicData = TK_CONF.Touch_Basic_Data0;
    }
    else
    {
        TK_BasicData = TK_CONF.Touch_Basic_Data1;
    }
    
    ifun_DAT_CAL = 0;
    
    for(ifun_DAT_CNT=0;ifun_DAT_CNT<ADCx_SMP_CNT;ifun_DAT_CNT++)
    {
        ifun_DAT_CAL += TK_BasicData[ifun_DAT_CNT]; 
    }
    ifun_DAT_CAL = ifun_DAT_CAL /(ADCx_SMP_CNT);
    ifun_DEF_DAT = (uint16_t)ifun_DAT_CAL;
    
    return ifun_DEF_DAT;

}






