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

#include "app.h" 

void EnterStopMode(void);

/******************************************************************************
*@brief : app test
*@param : none
*@return: none
******************************************************************************/
void APP_Test(void)
{
    uint32_t timeout;
    uint32_t freq;
    GPIO_InitTypeDef  GPIO_InitStruct = {0};
    EXTI_InitTypeDef EXTI_InitStruct = {0};
    LPTIM_InitTypeDef LPTIM_InitStruct = {0};
    
	printfS("SPL LPTIM Demo: Timeout Wakeup.\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_XTLConfig(RCC_XTL_DRIVE3, DISABLE);
    RCC_XTLCmd(ENABLE);
    if (RCC_WaitForXTLStartUp() != SUCCESS)
    {
        printfS("RC32K failed.\r\n");
        while (1);
    }
    
    // Enable exti interrupt
    EXTI_InitStruct.Line      = EXTI_LINE_LPTIM1;
    EXTI_InitStruct.Mode      = EXTI_MODE_IT;
    EXTI_InitStruct.Trigger   = EXTI_TRIGGER_RISING;
    EXTI_InitStruct.Cmd       = ENABLE;
    
    EXTI_Init(&EXTI_InitStruct);
    
    // Enable LPTIM1 NVIC IRQ
    NVIC_ClearPendingIRQ(LPTIM1_IRQn);
    NVIC_SetPriority(LPTIM1_IRQn, 0x00);
    NVIC_EnableIRQ(LPTIM1_IRQn);
    
    // Config LPTIM1
    LPTIM_DeInit(LPTIM1);
    __RCC_LPTIM1_CLK_ENABLE();
    LPTIM_Reset(LPTIM1);
    
    LPTIM_InitStruct.ClockSource = LPTIM_CLOCKSOURCE_INTERNAL_RC32K;
    LPTIM_InitStruct.Prescaler = LPTIM_CLOCKPRESCALER_DIV4;
    LPTIM_InitStruct.Waveform = LPTIM_WAVEFORM_PWM_ONEPULSE;
    LPTIM_InitStruct.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
    
    LPTIM_Init(LPTIM1, &LPTIM_InitStruct);
    
    LPTIM_SelectSoftwareStart(LPTIM1);
    LPTIM_ConfigUpdate(LPTIM1, LPTIM_UPDATE_IMMEDIATE);
    LPTIM_SelectCounterMode(LPTIM1, DISABLE);
    
    LPTIM_ClearFlag(LPTIM1, LPTIM_FLAG_ARRM);
    LPTIM_ITConfig(LPTIM1, LPTIM_IT_ARRM, ENABLE);
    LPTIM_TimoutCmd(LPTIM1, ENABLE);
    
    LPTIM_Cmd(LPTIM1, ENABLE);
    
    timeout = 3000;
    freq = ((RCC_GetRC32KFreq() * timeout) / 4000) - 1;
    
    LPTIM_ClearFlag(LPTIM1, LPTIM_FLAG_CMPOK);
    LPTIM_SetCompareValue(LPTIM1, freq >> 1);
    while (LPTIM_GetFlagStatus(LPTIM1, LPTIM_FLAG_CMPOK) == RESET);
    
    LPTIM_ClearFlag(LPTIM1, LPTIM_FLAG_ARROK);
    LPTIM_SetAutoreloadValue(LPTIM1, freq);
    while (LPTIM_GetFlagStatus(LPTIM1, LPTIM_FLAG_ARROK) == RESET);
    
    LPTIM_SelectOperatingMode(LPTIM1, LPTIM_MODE_CONTINUOUS);
    
    printfS("Timeout: %u ms.\r\n", timeout);
    printfS("\r\n");
    
    while(1)
    {
        printfS("mcu enter stop mode.\r\n"); 
        printfS("Automatically exit the STOP mode after a timeout of %u ms. \r\n", timeout); 
        
        EXTI_ClearFlag(EXTI_LINE_LPTIM1);
        EnterStopMode();
        
		printfS("mcu has exited stop mode.\r\n");
		printfS("\r\n");
        
        BSP_LED_Toggle();
        DelayMs(500);
    };
}

void lptim1_irq_handle(void)
{
    if (LPTIM_GetITStatus(LPTIM1, LPTIM_IT_ARRM))
    {
        LPTIM_ClearFlag(LPTIM1, LPTIM_FLAG_ARRM);
    }
    if (LPTIM_GetITStatus(LPTIM1, LPTIM_IT_ARRM))
    {
        LPTIM_ClearFlag(LPTIM1, LPTIM_FLAG_ARRM);
    }
}


void EnterStopMode(void)
{
	volatile uint32_t i;
    uint32_t primask;
          
    primask = __get_PRIMASK();
    __set_PRIMASK(1);    // disable interrupt 
    SysTick_Suspend();
    SCB->ICSR = BIT25;   // clear systick pending bit 
    
    RCC_RC32KCmd(ENABLE);
    RCC_SYSCLKConfig(RCC_SYSCLKSOURCE_RC32K);
    
    PMU_EnterSTOPMode(PMU_STOP_2, PMU_LOWPOWRENTRY_WFI);
    
    SysTick_Resume();   
    
    __set_PRIMASK(primask);
    
    SystemClock_Config();    
    
    SystemCoreClockUpdate();
    
    BSP_UART_Init();  
	
}


