#include  "ACM32Fxx_HAL.h"
#include  "ac_common.h"
#include  "Tkey.h"


uint32_t idleStartTick;
extern volatile uint32_t gu32_SystemCount;

#define UART_BAUD_RATE  115200
UART_HandleTypeDef UART2_Handle;

#ifndef TKEY_WAVEFORM_OUTPUT
#define TKEY_LOWPOWER           //低功耗测试   
#endif

#define USER_LED_GPIO_PORT       GPIOD
#define USER_LED_GPIO_PIN        GPIO_PIN_3

#define BUZZER_GPIO_PORT        GPIOD
#define BUZZER_GPIO_PIN         GPIO_PIN_1

volatile uint32_t g_u32Exti_Irq_line;
#define EXTI_IRQ_CALLBACK_SIZE     24

/************************************************************************
 * function   : Uart_Init
 * Description: Uart Initiation. 
 ************************************************************************/ 
void Uart_Init(void) 
{
    UART2_Handle.Instance        = UART2;
    UART2_Handle.Init.BaudRate   = UART_BAUD_RATE; 
    UART2_Handle.Init.WordLength = UART_WORDLENGTH_8B;
    UART2_Handle.Init.StopBits   = UART_STOPBITS_1;
    UART2_Handle.Init.Parity     = UART_PARITY_NONE;
    UART2_Handle.Init.Mode       = UART_MODE_TX_RX_DEBUG;
    UART2_Handle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;

    HAL_UART_Init(&UART2_Handle);

}



static void (*EXTI_IRQCallbackList[EXTI_IRQ_CALLBACK_SIZE])(void) = { 0 };//GPIO中断回调函数数组
/*****************************************************************
@功能	EXTI 中断处理程序入口
@参数	无
@返回	无
******************************************************************/
void EXTI_IRQHandler(void)
{
	int i;
	uint32_t mis;
	g_u32Exti_Irq_line = 0;
	//查询并清除中断
	mis = EXTI->PDR;
	if(mis == 0)
		return;
	
	//回调中断处理函数
	for(i = 0; i < 24; i++)
	{
		if ((mis & 0x01) && (EXTI_IRQCallbackList[i] != 0))
		{
            if(EXTI_IRQCallbackList[i] != NULL)
            {
                (EXTI_IRQCallbackList[i])();
                
            }
            EXTI->PDR = 1 << i; 
			g_u32Exti_Irq_line = i;
		}
		mis >>= 1;
		if(mis == 0)
		{
			break;
		}			
	}
}

/*****************************************************************
@原型	void Internal_InitEXTI(uint8_t linex, uint8_t triggr, void (*EXTIxx_IRQCallback)(void))
@功能	初始化外部中断(内部模块的8根线) 
@参数	linex-(16~23：对应EXTI_LINE_16~EXTI_LINE_23)
@参数	triggr-触发类型设置，EXTI_TRIGGER_RISING，EXTI_TRIGGER_FALLING, EXTI_TRIGGER_RISING_FALLING
@参数	EXTIxx_IRQCallback-中断回调函数
@返回	无
******************************************************************/
void Internal_InitEXTI(uint8_t linex, uint8_t triggr, void (*EXTIxx_IRQCallback)(void))
{
    EXTI_HandleTypeDef EXTI_Line_Handle;
	uint32_t exti_index;

	System_Module_Enable(EN_EXTI);

    exti_index = 1 << linex;
    /* Config EXTI */
    EXTI_Line_Handle.u32_Line    = exti_index;
    EXTI_Line_Handle.u32_Mode    = EXTI_MODE_INTERRUPT;
    EXTI_Line_Handle.u32_Trigger = triggr;    

    HAL_EXTI_SetConfigLine(&EXTI_Line_Handle);
	
	EXTI_IRQCallbackList[linex] = EXTIxx_IRQCallback;
}

/*****************************************************************
@功能	EXTI唤醒配置
@参数	无
@返回	无
******************************************************************/
static void Stop_Exit_Wakeup_Config(void)
{
    g_u32Exti_Irq_line = 0;
    TKEY_Wakeup();    
}

void GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

	System_Module_Enable(EN_GPIOAB);
	NVIC_ClearPendingIRQ(GPIOAB_IRQn);
	NVIC_EnableIRQ(GPIOAB_IRQn);

	System_Module_Enable(EN_GPIOCD);
	NVIC_ClearPendingIRQ(GPIOCD_IRQn);
	NVIC_EnableIRQ(GPIOCD_IRQn);

    //User LED GPIO Init
    GPIO_InitStruct.Pin = USER_LED_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;
    
    HAL_GPIO_Init(USER_LED_GPIO_PORT,&GPIO_InitStruct);

    HAL_GPIO_WritePin(USER_LED_GPIO_PORT, USER_LED_GPIO_PIN, GPIO_PIN_CLEAR); 
    
    //Buzzer GPIO Init
    GPIO_InitStruct.Pin = BUZZER_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;
    
    HAL_GPIO_Init(BUZZER_GPIO_PORT,&GPIO_InitStruct);
    HAL_GPIO_WritePin(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN, GPIO_PIN_CLEAR);
}

/*********************************************************************************
* Function    : Led_On
* Description : 
* Input       : 
* Output      : 
**********************************************************************************/
void Led_On(void)
{
    HAL_GPIO_WritePin(USER_LED_GPIO_PORT, USER_LED_GPIO_PIN, GPIO_PIN_CLEAR); 
}

/*********************************************************************************
* Function    : Led_Off
* Description : 
* Input       : 
* Output      : 
**********************************************************************************/
void Led_Off(void)
{
    HAL_GPIO_WritePin(USER_LED_GPIO_PORT, USER_LED_GPIO_PIN, GPIO_PIN_SET); 
}

/*********************************************************************************
* Function    : Beep_On
* Description : 
* Input       : ms: keep time in ms.
* Output      : 
**********************************************************************************/
void Beep_On(int ms)
{
    HAL_GPIO_WritePin(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN, GPIO_PIN_SET);
    System_Delay_MS(ms);
    HAL_GPIO_WritePin(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN, GPIO_PIN_CLEAR);
}

/*****************************************************************
@功能	电源管理器进程函数，CPU将在该函数中暂停，并在恢复时返回
@参数	无
@返回	无
******************************************************************/  
void Suspend_Process(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    TouchKey_suspend();
        
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;
    
    /* 不用的IO配置位模拟 */
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_13 | GPIO_PIN_14;
    HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);  //PA0 PA13 PA14
    
    GPIO_InitStruct.Pin = GPIO_PIN_7;
    HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);  //PB7
    
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    HAL_GPIO_Init(GPIOD,&GPIO_InitStruct);  //PD5
    
    System_Clear_Stop_Wakeup();
    Stop_Exit_Wakeup_Config();
    gu32_SystemCount = 0;
    printfS("Enter_Stop_Ram \n");
    extern void Enter_Stop_Ram(void);

    Enter_Stop_Ram();

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_1;
    
    /* 不用的IO配置位模拟 */
    GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_13 | GPIO_PIN_14;
    HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);  //PA13 PA14
}

/*********************************************************************************
* Function    : main
* Description : 
* Input       : 
* Output      : 
**********************************************************************************/
int main(void)
{ 
    uint8_t  ucKey = 0xFF;
    uint8_t  ret;
    System_Init();
    SysTimer_Init();           
    GPIO_Init();
    Uart_Init();
    printfS("MCU is running on %s %s, HCLK = %dHz, PCLK = %dHz\n", __DATE__, __TIME__, System_Get_SystemClock(), System_Get_APBClock());  
    ret = TouchKey_Init();
    if(ret == 0)
    {
        printfS("TouchKey_Init Success \r\n");
    }
    else
    {
        printfS("TouchKey_Init Fail \r\n");
    }

    printfS("\r\nMCU is Running!!!\r\n");
    
    Led_Off();
    System_Delay_MS(500);
    Led_On();
    
    idleStartTick = get_ms_tick();
    while(1)
    {
        ucKey = TouchKey_TimerSacn_GetKeyVal();
        if(ucKey != 0xFF)
        {
        #ifndef TKEY_WAVEFORM_OUTPUT
            printfS("TK_%d\n", ucKey);
        #endif
            Beep_On(5);
            idleStartTick = get_ms_tick();
        }
        TKEY_Calibrate_Process();
#ifdef TKEY_LOWPOWER
        //空闲10s，进入STOP模式
        if(get_ms_delay(idleStartTick)> 10000)
        {                    
            printf("MCU Enter stop mode!\n");
            TouchKey_Switch_Clock_RC4M();
            Suspend_Process();
            Uart_Init();
            printfS("MCU WakeUp By EXITLine_%d\r\n",g_u32Exti_Irq_line);
            GPIO_Init();
            Led_On();
            idleStartTick = get_ms_tick();
            TouchKey_resume();
            TouchKey_Switch_Clock_PCLK();
            printfS("TKEY Test is Ready!!! \r\n");
        }  
#endif      
    }
}




