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

#include "app.h" 


bool gwakeTimerFlag = false;
bool gminuteFlag = false;
bool galarmFlag = false;
bool gtemperFlag1 = false;
bool gtemperFlag2 = false;

/******************************************************************************
* @brief : Set date and time.
* @param : None
* @return: None
******************************************************************************/
void Set_Date_Time(void)
{
    RTC_DateTypeDef  RTC_DateStruct;
    RTC_TimeTypeDef  RTC_TimeStruct;
    
    RTC_DateStructInit(&RTC_DateStruct);
    RTC_TimeStructInit(&RTC_TimeStruct);
    
    /* 日期：2023年2月14日，星期二 */
    RTC_DateStruct.Year = 23;
    RTC_DateStruct.Month = 2;
    RTC_DateStruct.Date = 14;
    RTC_DateStruct.WeekDay = 2;
    
    /* 时间：18时9分40秒 */
    RTC_TimeStruct.Hours = 18;
    RTC_TimeStruct.Minutes = 9;
    RTC_TimeStruct.Seconds = 40;
    
    /* 关闭RTC写保护 */
    RTC_WriteProtectionCmd(DISABLE);
    
    /* 设置日期 */
    RTC_SetDate(RTC_FORMAT_DECIMAL, &RTC_DateStruct);
    /* 设置时间 */
    RTC_SetTime(RTC_FORMAT_DECIMAL, &RTC_TimeStruct);
    
    /* 开启RTC写保护 */
    RTC_WriteProtectionCmd(ENABLE);
    
}

/******************************************************************************
* @brief : Get date and time.
* @param : None
* @return: None
******************************************************************************/
void Get_Date_Time(void)
{
    static uint32_t tmp_Seconds = 0;
    RTC_DateTypeDef  RTC_GetDateStruct;
    RTC_TimeTypeDef  RTC_GetTimeStruct;
    RTC_TimeTypeDef  RTC_GetTimeAgaginStruct;
    
    RTC_DateStructInit(&RTC_GetDateStruct);
    RTC_TimeStructInit(&RTC_GetTimeStruct);
    RTC_TimeStructInit(&RTC_GetTimeAgaginStruct);
    
    /* 获取日期与时间 */
    RTC_GetTime(RTC_FORMAT_DECIMAL, &RTC_GetTimeStruct);
    RTC_GetDate(RTC_FORMAT_DECIMAL, &RTC_GetDateStruct);
    RTC_GetTime(RTC_FORMAT_DECIMAL, &RTC_GetTimeAgaginStruct);
    
    if (RTC_GetTimeStruct.Seconds != RTC_GetTimeAgaginStruct.Seconds) 
    {
        return;   
    }
    if (tmp_Seconds != RTC_GetTimeStruct.Seconds) 
    {
        tmp_Seconds = RTC_GetTimeStruct.Seconds;
        
        printf("Date: 20%02d-%02d-%02d week:%d \n", RTC_GetDateStruct.Year, RTC_GetDateStruct.Month, RTC_GetDateStruct.Date, RTC_GetDateStruct.WeekDay);
        printf("Time: %02d:%02d:%02d \n", RTC_GetTimeStruct.Hours, RTC_GetTimeStruct.Minutes, RTC_GetTimeStruct.Seconds);
    }
}

/******************************************************************************
* @brief : set alarm.
* @param : None
* @return: None
******************************************************************************/
void Set_Alarm(void)
{
    RTC_AlarmTypeDef RTC_AlarmStruct;
    
    RTC_AlarmStructInit(&RTC_AlarmStruct);
    
    /* 闹钟使用星期模式，星期二，18时10分40秒 */
    RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;
    RTC_AlarmStruct.RTC_AlarmMask = RTC_ALARMMASK_NONE;
    RTC_AlarmStruct.RTC_AlarmDateWeekDay = 2;
    RTC_AlarmStruct.RTC_AlarmTime.Hours = 18;
    RTC_AlarmStruct.RTC_AlarmTime.Minutes = 10;
    RTC_AlarmStruct.RTC_AlarmTime.Seconds = 00;
    
    RTC_SetAlarm(RTC_FORMAT_DECIMAL, &RTC_AlarmStruct);
    
    /* 使能闹钟 */
    RTC_AlarmCmd(ENABLE);
    
    /* 清除闹钟中断标志 */
    RTC_ClearFlag(RTC_IT_FLAG_ALM);
    /* 开启闹钟中断 */
    RTC_ITConfig(RTC_IT_FLAG_ALM, ENABLE);
}


/******************************************************************************
* @brief : set Tamper.
* @param : None
* @return: None
******************************************************************************/
void Set_Tamper(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;
    __RCC_GPIOA_CLK_ENABLE();
    __RCC_GPIOC_CLK_ENABLE();
         
    /* PC13--RTC_TAMP1 */
    GPIO_InitStruct.Pin       = GPIO_PIN_13;
    GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull      = GPIO_NOPULL;
    GPIO_InitStruct.Drive     = GPIO_DRIVE_LEVEL3;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    /* Tamper1上升沿清除备份寄存器 */
    RTC_TamperTriggerConfig(RTC_TAMPER_1, RTC_TAMPERTRIGGER_RISING);
    RTC_TamperFilterClockConfig(RTC_TAMPERSAMPLINGCLOCK_RTCCLK);
    RTC_TamperFilterPeriodConfig(RTC_TAMPER_1, RTC_TAMPERFILTER_2SAMPLE);
    RTC_TamperRasingClearBackpConfig(RTC_TAMPER_1, RTC_TAMPERRASINGCLEAR_ENABLE);
    /* 使能Tamper1 */
    RTC_TamperCmd(RTC_TAMPER_1, ENABLE);
    
    /* 清除Tamper1上升沿中断标志 */
    RTC_ClearFlag(RTC_IT_FLAG_STP1R);
    /* 开启Tamper1上升沿中断 */
    RTC_ITConfig(RTC_IT_FLAG_STP1R, ENABLE);

    /* PA0--RTC_TAMP2 */
    GPIO_InitStruct.Pin       = GPIO_PIN_0;
    GPIO_InitStruct.Mode      = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull      = GPIO_NOPULL;
    GPIO_InitStruct.Drive     = GPIO_DRIVE_LEVEL3;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    /* Tamper2下降沿不清除备份寄存器 */
    RTC_TamperTriggerConfig(RTC_TAMPER_2, RTC_AMPERTRIGGER_FALLING);
    RTC_TamperFilterClockConfig(RTC_TAMPERSAMPLINGCLOCK_RTCCLK);
    RTC_TamperFilterPeriodConfig(RTC_TAMPER_2, RTC_TAMPERFILTER_4SAMPLE);
    RTC_TamperFallingClearBackpConfig(RTC_TAMPER_2, RTC_TAMPERFALLINGCLEAR_DISABLE);
    /* 使能Tamper2 */
    RTC_TamperCmd(RTC_TAMPER_2, ENABLE);
    
    /* 清除Tamper2下降沿中断标志 */
    RTC_ClearFlag(RTC_IT_FLAG_STP2F);
    /* 开启Tamper2下降沿中断 */
    RTC_ITConfig(RTC_IT_FLAG_STP2F, ENABLE);
}

/******************************************************************************
* @brief : set Wake Timer.
* @param : None
* @return: None
******************************************************************************/
void Set_Wake_Timer(void)
{
    /* 唤醒定时器时钟选择1HZ */
    RTC_WakeUpClockConfig(RTC_WAKEUPCLOCK_1HZ);
    /* 唤醒自动重载值 */
    RTC_SetWakeUpCounter(0x05);
    
    /* 使能唤醒定时器 */
    RTC_WakeUpCmd(ENABLE);
    
    /* 清除唤醒定时器标志中断标志 */
    RTC_ClearFlag(RTC_IT_FLAG_WUT);
    /* 开启唤醒定时器中断 */
    RTC_ITConfig(RTC_IT_FLAG_WUT, ENABLE);
       
}

/******************************************************************************
* @brief : Enter Standby.
* @param : None
* @return: None
******************************************************************************/
void Enter_Standby(void)
{
    /* 设置Standby唤醒等待时间 */
    PMU_SetSTANDBYWakeWaitTime(PMU_STANDBYWAKEWAIT_4RC32K);
    
    printfS("MCU enter standby mode \r\n");  
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;   // disable systick        
    __set_PRIMASK(1);    // disable interrupt 
    SCB->ICSR = BIT25;   // clear systick pending bit
    
    PMU_EnterSTANDBYMode(PMU_LOWPOWRENTRY_WFI);
    
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; /* Enable SysTick IRQ */               
    __set_PRIMASK(0);    // enable interrupt 
    
    printfS("MCU never run here \r\n");
    
}

/******************************************************************************
* @brief : RTC function test.
* @param : mode: Different function test options
* @return: None
******************************************************************************/
void APP_RTC_Test(RTC_TestMode_TypeDef mode)
{
    RTC_DeInit();
    /* RTC初始化 */
    RTC_Init(RTC_CLOCK_XTL);
    /* 开启时钟误差补偿 */
    RTC_CoarseCalibConfig(RTC_CALIBSIGN_POSITIVE, 0x05);
    
    NVIC_ClearPendingIRQ(RTC_IRQn);
    NVIC_SetPriority(RTC_IRQn, 0x05);
    NVIC_EnableIRQ(RTC_IRQn);
    
    Set_Date_Time();
    
    switch (mode)
    {
        /* RTC日期时间功能 */
        case RTC_TIME_DATE_TEST: 
        {
            printfS("RTC Date&Time Test.....\r\n");
            
            /* 清除分中断标志 */
            RTC_ClearFlag(RTC_IT_FLAG_MIN);
            /* 开启分中断 */
            RTC_ITConfig(RTC_IT_FLAG_MIN, ENABLE);

            while (1) 
            {
                Get_Date_Time();
                if(gminuteFlag) 
                {
                    printf("Minute interrupt has been triggered!!! \r\n");
                    gminuteFlag= false;
                }
                
            }
        }

        /* RTC闹钟功能 */
        case RTC_ALARM_TEST:
        {
            printfS("RTC ALARM Test.....\r\n");         

            Set_Alarm();                  
 
            while (1) 
            {
                Get_Date_Time();
                
                if(galarmFlag) 
                {
                    printf("Alarm interrupt has been triggered!!! \r\n");
                    galarmFlag= false;
                }
            }
        }

        case RTC_TAMPER_TEST:
        {
            printfS("RTC Tamper Test.....\r\n");           
            
            Set_Tamper();
			
            /* RTC模块写使能 */
            PMU_BackupAccessCmd(ENABLE);
            RTC_WriteBackupRegister(RTC_BKP_DR0, 0xAAAA5555);
            RTC_WriteBackupRegister(RTC_BKP_DR5, 0x5555AAAA);
            RTC_WriteBackupRegister(RTC_BKP_DR10, 0x3333CCCC);
            RTC_WriteBackupRegister(RTC_BKP_DR15, 0xCCCC3333);	

            while (1) 
            {

                Get_Date_Time();
                
                if (gtemperFlag1) 
                {
                    gtemperFlag1 = false;  
                    printf("Tamper1 interrupt has been triggered!!! \r\n");                    
                    printf("RTC CLKSTEMP1 Date: %08x, Time: %08x\r\n", RTC->CAL_STAMP1, RTC->CLK_STAMP1);
                    printf("backup0 = %08x, backup10 = %08x\r\n", RTC_ReadBackupRegister(RTC_BKP_DR0),RTC_ReadBackupRegister(RTC_BKP_DR10));
                    RTC_WriteBackupRegister(RTC_BKP_DR0, 0x55AA55AA);
                    RTC_WriteBackupRegister(RTC_BKP_DR5, 0xAA55AA55);
                    RTC_WriteBackupRegister(RTC_BKP_DR10, 0x33CC33CC);
                    RTC_WriteBackupRegister(RTC_BKP_DR15, 0xCC33CC33);
                }
                
                if (gtemperFlag2) 
                {
                    gtemperFlag2 = false;
                    printf("Tamper2 interrupt has been triggered!!! \r\n"); 
                    printf("RTC CLKSTEMP2 Date: %08x, Time: %08x\r\n", RTC->CAL_STAMP2, RTC->CLK_STAMP2);
                    printf("backup5 = %08x, backup15 = %08x\r\n", RTC_ReadBackupRegister(RTC_BKP_DR5),RTC_ReadBackupRegister(RTC_BKP_DR15));
                    RTC_WriteBackupRegister(RTC_BKP_DR5, 0xAA55AA55);
                    RTC_WriteBackupRegister(RTC_BKP_DR15, 0xCC33CC33);
                }
            }
        }
        
        case RTC_WAKETIMER_TEST:
        {
            printf("RTC Wake-Timer Test.....\r\n");
            
            if(SET == PMU_GetFlagStatus(PMU_FLAG_RTC))
            {
                printfS("WakeUp by RTC !!!\n");
                PMU_ClearFlag(PMU_FLAG_RTC);
            }
            
            PMU_ClearFlag(PMU_FLAG_ALL);
                      
            Set_Wake_Timer();
                    
            while(1)
            {
                Get_Date_Time();
                
                if(gwakeTimerFlag)
                {
                    gwakeTimerFlag = false;
                    printf("Wake-Timer interrupt has been triggered!!! \r\n");
                    Enter_Standby(); 
                }
            }
        }
        default: 
        printfS("The application is not supported\r\n");
        break; 
    }
    
}






