/**
  ******************************************************************************
  * @file    RTC/Calendar/main.c
  * @author  IOT Development Team
  * @version V1.0.0
  * @date    10-January-2020
  * @brief   Main program body.
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "apm32f10x.h"
#include "platform_config.h"
#include <stdarg.h>
#include <stdio.h>
/** @addtogroup APM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup RTC_Calendar
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint32_t TimingDelay;
// ErrorStatus HSEStartUpStatus;
__IO uint32_t TimeDisplay = 0;
USART_ConfigStruct_T USART_configStruct;
/* Private function prototypes -----------------------------------------------*/
void SYSCLKConfig_STOP(void);
void EINT_Configuration(void);
void RTC_Configuration(void);
void NVIC_Configuration(void);
void SysTick_Configuration(void);
void Delay(__IO uint32_t nTime);
void Time_Adjust(void);
void Time_Show(void);
/* Private functions ---------------------------------------------------------*/

void Uartx_SendByte(USART_T* USARTx,int data)
{
    if (data=='\n')
    {
        while (!(USARTx->STS & (1<<6)));

        USARTx->DATA='\r';
    }

    while (!(USARTx->STS & (0x01<<6)));

    USARTx->DATA=data;
}

void Uartx_SendString(USART_T* USARTx,char *pt)
{
    while (*pt)
    {
        Uartx_SendByte(USARTx,*pt++);
    }
}


void Uartx_Printf(USART_T* USARTx,char *fmt,...)
{
    __va_list ap;
    char string[256];

    va_start(ap,fmt);
    vsprintf(string,fmt,ap);
    Uartx_SendString(USARTx,string);
    va_end(ap);
}


/**
  * @brief   Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
    /*!< At this stage the microcontroller clock setting is already configured,
         this is done through SystemInit() function which is called from startup
         file (startup_apm32f10x_xx.s) before to branch to application main.
         To reconfigure the default setting of SystemInit() function, refer to
         system_apm32f10x.c file
       */


    /* USARTx configured as follow:
          - BaudRate = 115200 baud
          - Word Length = 8 Bits
          - One Stop Bit
          - No parity
          - Hardware flow control disabled (RTS and CTS signals)
          - Receive and transmit enabled
    */
    USART_configStruct.baudRate = 115200;
    USART_configStruct.wordLength = USART_WORD_LEN_8B;
    USART_configStruct.stopBits = USART_STOP_BIT_1;
    USART_configStruct.parity = USART_PARITY_NONE;
    USART_configStruct.hardwareFlowCtrl = USART_FLOW_CTRL_NONE;
    USART_configStruct.mode = USART_MODE_TX_RX;

#if defined (APM32_MINI)
    /* Initialize LEDs and Key Button mounted on APM3210X-MINI board */
    APM_MINI_LEDInit(LED2);
    APM_MINI_LEDInit(LED3);
    APM_MINI_COMInit(COM1, &USART_configStruct);
#elif defined(APM32_DISCOVERY)
    /* Initialize Leds mounted on APM32-DISCOVERY board */
    APM_DISCOVERY_LEDInit(LED2);
    APM_DISCOVERY_LEDInit(LED3);
    APM_DISCOVERY_COMInit(COM1, &USART_InitStructure);
#elif defined(APM32F103V_EVAL)
    APM_EVAL_LEDInit(LED2);
    APM_EVAL_LEDInit(LED3);
    APM_EVAL_COMInit(COM1, &USART_InitStructure);
#endif

    /* Enable PMU and BAKR clock */
    RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU | RCM_APB1_PERIPH_BAKR);

//  /* Configure EINT Line to generate an interrupt on falling edge */
//  EINT_Configuration();

    /* Configure RTC clock source and prescaler */
    RTC_Configuration();

    /* NVIC configuration */
    NVIC_Configuration();

    /* Configure the SysTick to generate an interrupt each 1 millisecond */
//  SysTick_Configuration();
    /* Adjust time by values entered by the user on the hyperterminal */
    Time_Adjust();
    Time_Show();

    while (1)
    {

    }
}

void Time_Adjust(void)
{
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    /* Change the current time */
    RTC_WriteCounter(1);
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
}

/**
  * @brief  Displays the current time.
  * @param  TimeVar: RTC counter value.
  * @retval None
  */
void Time_Display(uint32_t TimeVar)
{
    uint32_t THH = 0, TMM = 0, TSS = 0;

    /* Reset RTC Counter when Time is 23:59:59 */

    /* Compute  hours */
    THH = TimeVar / 3600;
    /* Compute minutes */
    TMM = (TimeVar % 3600) / 60;
    /* Compute seconds */
    TSS = (TimeVar % 3600) % 60;
#if defined (APM32_MINI)
    Uartx_Printf(MINI_COM1,"Time: %0.2d:%0.2d:%0.2d\r\n", THH, TMM, TSS);
#elif defined(APM32_DISCOVERY)
    Uartx_Printf(DISCOVERY_COM1,"Time: %0.2d:%0.2d:%0.2d\r\n", THH, TMM, TSS);
#elif defined(APM32F103V_EVAL)
    Uartx_Printf(EVAL_COM1,"Time: %0.2d:%0.2d:%0.2d\r\n", THH, TMM, TSS);
#endif
}
/**
  * @brief  Shows the current time (HH:MM:SS) on the Hyperterminal.
  * @param  None
  * @retval None
  */
void Time_Show(void)
{
    uint16_t i;

#if defined (APM32_MINI)
    Uartx_Printf(MINI_COM1,"\n\r");
#elif defined(APM32_DISCOVERY)
    Uartx_Printf(DISCOVERY_COM1,"\n\r");
#elif defined(APM32F103V_EVAL)
    Uartx_Printf(EVAL_COM1,"\n\r");
#endif
    i=0;

    /* Infinite loop */
    while (1)
    {
        /* If 1s has been elapsed */
        if (TimeDisplay==1)
        {
            /* Display current time */
            Time_Display(RTC_ReadCounter());
            RTC_WaitForSynchor();
            //    Divider_Display();
            TimeDisplay = 0;
        }


    }
}
/**
  * @brief  Configures EINT Lines.
  * @param  None
  * @retval None
  */
void EINT_Configuration(void)
{
    EINT_ConfigStruct_T EINT_configStruct;

    /* Configure EINT Line17(RTC Alarm) to generate an interrupt on rising edge */
    EINT_ClearIntFlag(0x20000);
    EINT_configStruct.EINT_Line = 0x20000;
    EINT_configStruct.EINT_Mode = EINT_MODE_Interrupt;
    EINT_configStruct.EINT_Trigger = EINT_Trigger_Rising;
    EINT_configStruct.EINT_LineCmd = ENABLE;
    EINT_Config(&EINT_configStruct);
}

/**
  * @brief  Configures RTC clock source and prescaler.
  * @param  None
  * @retval None
  */
void RTC_Configuration(void)
{
    /* RTC clock source configuration ------------------------------------------*/
    /* Allow access to BAKR Domain */
    PMU_EnableBakrAccess();

    /* Reset Bakr Domain */
    BAKR_Reset();

    /* Enable the LXT OSC */
    RCM_ConfigLXT(RCM_LXT_OPEN);

    /* Wait till LXT is ready */
    while (RCM_ReadFlag(RCM_FLAG_LXTRDY) == RESET)
    {
    }

    /* Select the RTC Clock Source */
    RCM_ConfigRTCCLK(RCM_RTCCLK_SEL_LXT);

    /* Enable the RTC Clock */
    RCM_EnableRTCCLK();

    /* RTC configuration -------------------------------------------------------*/
    /* Wait for RTC APB registers synchronisation */
    RTC_WaitForSynchor();

    /* Set the RTC time base to 1s */
    RTC_SetPrescaler(32767);
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();

    /* Enable the RTC Alarm interrupt */
    RTC_EnableInterrupt(RTC_INT_SEC);
    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
}

/**
  * @brief  Configures NVIC and Vector Table base location.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
    /* Configure one bit for preemption priority */
    NVIC_ConfigPriorityGroup(NVIC_PRIORITY_GROUP_1);

    /* Enable the RTC Interrupt */

    NVIC_EnableIRQRequest(RTC_IRQn, 0x01, 0x00);
}

/**
  * @brief  Configures the SysTick to generate an interrupt each 1 millisecond.
  * @param  None
  * @retval None
  */
void SysTick_Configuration(void)
{
    /* Setup SysTick Timer for 1 msec interrupts  */
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        /* Capture error */
        while (1);
    }

    /* Set SysTick Priority to 3 */
    NVIC_SetPriority(SysTick_IRQn, 0x0C);
}

/**
  * @brief  Inserts a delay time.
  * @param  nTime: specifies the delay time length, in milliseconds.
  * @retval None
  */
void Delay(__IO uint32_t nTime)
{
    TimingDelay = nTime;

    while (TimingDelay != 0);

}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
    /* User can add his own implementation to report the file name and line number,
       ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

    /* Infinite loop */
    while (1)
    {
    }
}

#endif

/**
  * @}
  */

/**
  * @}
  */

