
/******************************************************************************
*@file  : app.c
*@brief : application
******************************************************************************/

#include "app.h" 

void EnterStopMode(void);

/******************************************************************************
*@brief : app test
*@param : none
*@return: none
******************************************************************************/
void APP_Test(void)
{
    uint32_t i;
    uint32_t data;
    uint32_t top;
    uint32_t bot;
    GPIO_InitTypeDef  GPIO_InitStruct = {0};
    LPUART_InitTypeDef LPUART_InitStruct = {0};
    EXTI_InitTypeDef EXTI_InitStruct = {0};
    
	printfS("SPL LPUART1 Demo: Wakeup form STOP Mode.\r\n");
	printfS("\r\n");
    
	BSP_LED_Init();
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    BSP_LED_On();
    DelayMs(500);
    BSP_LED_Off();
    DelayMs(500);
    
    // RC32K
    RCC_RC32KCmd(ENABLE);
    if (RCC_WaitForRC32KStartUp() == ERROR)
    {
        printfS("RC32K stabilization timeout.\r\n");
        while (1);
    }
    
    // Init LPUART1
    __RCC_LPUART1_CLK_ENABLE();
    __RCC_LPUART1_RESET();
    
    // TX:PC1, RX:PC0
    __RCC_GPIOC_CLK_ENABLE();
    
    GPIO_InitStruct.Pin       = GPIO_PIN_1 | GPIO_PIN_0;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLUP;
    GPIO_InitStruct.Drive     = GPIO_DRIVE_LEVEL3;
    GPIO_InitStruct.Alternate = GPIO_FUNCTION_0;

    GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    LPUART_SetClockSource(LPUART1, LPUART_CLOCKSOURCE_RC32K);
    LPUART_SetWakeupMode(LPUART1, LPUART_WAKEUPMODE_ADDRNOCHECK);
    LPUART_SetWakeupAddr(LPUART1, '8');
    
    LPUART_InitStruct.BaudRate    = 9600;
    LPUART_InitStruct.WordLength  = LPUART_WORDLENGTH_8B;
    LPUART_InitStruct.StopBits    = LPUART_STOPBITS_1B;
    LPUART_InitStruct.Parity      = LPUART_PARITY_NONE;
    LPUART_InitStruct.Mode        = LPUART_MODE_RX;
    
    LPUART_Init(LPUART1, &LPUART_InitStruct);
    
    LPUART_ITConfig(LPUART1, LPUART_IT_RX, ENABLE);
    
    EXTI_InitStruct.Line      = EXTI_LINE_LPUART1;
    EXTI_InitStruct.Mode      = EXTI_MODE_IT;
    EXTI_InitStruct.Trigger   = EXTI_TRIGGER_RISING;
    EXTI_InitStruct.Cmd       = ENABLE;
    
    EXTI_Init(&EXTI_InitStruct);
    
    LPUART_ClearFlag(LPUART1, LPUART_FLAG_MATCHIF);
	EXTI_ClearITPendingBit(EXTI_LINE_LPUART1);
    
    // Enable NVIC IRQ
    NVIC_ClearPendingIRQ(LPUART1_IRQn);
    NVIC_SetPriority(LPUART1_IRQn, 0x00);
    NVIC_EnableIRQ(LPUART1_IRQn);
    
    printfS("LPUART1 : 9600, 8, 1, N.\r\n");
    printfS("LPUART1 receives data and sends back the received data.\r\n");
    printfS("\r\n");
    
    while (1)
    {
        printfS("mcu enter stop mode.\r\n"); 
        printfS("LPUART sends character 8 to wake up.\r\n"); 
        
        LPUART_ClearFlag(LPUART1, LPUART_FLAG_MATCHIF);
        EXTI_ClearITPendingBit(EXTI_LINE_LPUART1);
        
        EnterStopMode();
        
		printfS("mcu has exited stop mode.\r\n");
		printfS("\r\n");
        
        BSP_LED_Toggle();
		DelayMs(500);
    }
}

void lpuart1_irq_handle(void)
{
    volatile uint32_t data;
    
    if (LPUART_GetITStatus(LPUART1, LPUART_IT_RX))
    {
        data = LPUART_ReceiveData(LPUART1);
    }
}


void EnterStopMode(void)
{
	volatile uint32_t i;
    uint32_t save_irq;
          
    save_irq = EnterCritical();
    SysTick_Suspend();
    
    RCC_RC32KCmd(ENABLE);
    RCC_SYSCLKConfig(RCC_SYSCLKSOURCE_RC32K);
    
    PMU_EnterSTOPMode(PMU_STOP_2, PMU_LOWPOWRENTRY_WFI);
    
    SysTick_Resume();   
    
    ExitCritical(save_irq);
    
    SystemClock_Config();    
    
    SystemCoreClockUpdate();
    
    BSP_UART_Init();  
	
}


