#include "drv_rtc.h"
#include "drv_clk.h"

#include "bsp_task.h"

#include "kit_time.h"
#include "kit_data.h"
#include "kit_debug.h"

#define LSE_NOT_READY			0
#define RCC_BDCR_RTCEN_POS		KIT_CREAT_BIT(15)
#define RCC_BDCR_LSEDY_POS		((uint32_t)0x00000002)
#define RCC_BDCR_LSEON_POS		KIT_CREAT_BIT(0)


#define RCC_RTCCLKSource_LSE    KIT_CREAT_BIT(8)
#define RTC_FLAG_RTOFF       ((uint16_t)0x0020)  /*!< RTC Operation OFF flag */
/******************************************************************************************
1.写RTC寄存器前必须使能PWR_CR中的DBP,且必须等待操作完成才能清0 DBP
2.stm32f10x RTC 进行写操作前必须判断上一次操作是否完成(RTOFF)
3.写RTC_CNT、RTC_ALR或RTC_PRL寄存器时必须先置位CNF，写完后必须清0才会执行写操作
4.读RTC_CNT、RTC_ALR或RTC_PRL寄存器时前必须清0RSF，等其被硬件置位时表示同步完成，可以读取
5.低速时钟起振时间1-5s
******************************************************************************************/

#define RTC_INIT_MASK           ((uint32_t)0xFFFFFFFF)
bool drv_rtc_enable_init_mode(void)
{
    uint32_t dly = 0;

//	//对RTC寄存器操作前先要使能备份区
//	PWR->CR |= PWR_CR_DBP;
    //关闭RTC寄存器写保护
    RTC->WPR = 0xCA;
    RTC->WPR = 0x53;
    //进入RTC初始化模式
    if((RTC->ISR &= RTC_ISR_INITF) == 0)
    {
        RTC->ISR = RTC_INIT_MASK;
        //等待进入RTC初始化模式成功
        while(((RTC->ISR & RTC_ISR_INITF) == 0x00) && (dly++ < 100))
        {
            bsp_task_delay_ms(1);
        }
    }
    return (dly < 100);
}

void drv_rtc_disable_init_mode(void)
{
    RTC->ISR &= ~RTC_ISR_INIT; //退出RTC初始化模式
    RTC->WPR = 0xFF;			//使能RTC寄存器写保护
}


//由于低速时钟起振较慢，其他任务初始化后再初始化RTC
bool drv_rtc_init(void)
{
    bool res = false;
    uint32_t dly = 0;
    //if((RCC->BDCR & RCC_BDCR_RTCEN_POS) != RCC_BDCR_RTCEN_POS)
    {
        KIT_DEBUG_PRINTF("rtc init\r\n");
        RCC->APB1ENR |= RCC_APB1Periph_PWR;
        //使能允许写入RTC和后备寄存器
        PWR->CR |= PWR_CR_DBP;
        //开启LSE
        RCC->BDCR |= RCC_BDCR_LSEON_POS;
        while((RCC->BDCR & RCC_BDCR_LSEDY_POS) == LSE_NOT_READY)
        {
            bsp_task_delay_ms(10);
            if(dly++ > 500)
            {
                KIT_DEBUG_PRINTF("rtc fail \r\n");
                return res;
            }
        }
        KIT_DEBUG_PRINTF("rtc dly %d\r\n", dly);
        RCC->BDCR |= (RCC_RTCCLKSource_LSE | RCC_BDCR_RTCEN_POS);
        //RTC配置使用默认配置
        //设置同步分频系数和异步分频系数，默认为1Hz = 32768/(同步分频 + 1)/(异步分频 + 1)
        res = drv_rtc_enable_init_mode();
        if(res == true)
        {
            RTC->PRER = 0x001F03FF;
        }
        drv_rtc_disable_init_mode();

        //PWR->CR &= ~PWR_CR_DBP_POS;
    }
    return res;
}

//ampm:AM/PM,0=AM/24H,1=PM.
bool drv_rtc_set_time(uint8_t hour, uint8_t min, uint8_t sec)
{
    bool res;
    //关闭RTC寄存器写保护
    res = drv_rtc_enable_init_mode();
    if(res == true)
    {
        RTC->TR = ((uint32_t)kit_dec_to_bcd(hour) << 16) | ((uint32_t)kit_dec_to_bcd(min) << 8) | (kit_dec_to_bcd(sec));
    }
    drv_rtc_disable_init_mode();
    return res;
}

//year 20xx, month 1-12, day 1-31
bool drv_rtc_set_date(uint16_t year, uint8_t month, uint8_t day)
{
    bool res;
    //关闭RTC寄存器写保护
    res = drv_rtc_enable_init_mode();
    if((res == true) && (year >= 2000))
    {
        RTC->DR = ((uint32_t)kit_dec_to_bcd(year - 2000) << 16) | ((uint32_t)kit_dec_to_bcd(month) << 8) | (kit_dec_to_bcd(day));
    }
    drv_rtc_disable_init_mode();
    return res;
}

//Tan 20230911 减少retry次数，防止阻塞
bool drv_rtc_wait_sync(void)
{
    bool res = true;
    int32_t retry = 0;
    //关闭RTC寄存器写保护
    RTC->WPR = 0xCA;
    RTC->WPR = 0x53;
    RTC->ISR &= ~(1 << 5);		//清除RSF位
    while((retry++ < 0XFFFFF) && ((RTC->ISR & (1 << 5)) == 0x00)) //等待影子寄存器同步
    {}

    if(retry >= 0XFFFFF)
    {
        res = false;
    }

    RTC->WPR = 0xFF;			//使能RTC寄存器写保护

    return res;
}

bool drv_rtc_get_time(int32_t *hour, int32_t *min, int32_t *sec)
{
    uint32_t temp = 0;
    if(drv_rtc_wait_sync() == true)
    {
        temp = RTC->TR;
        *hour = kit_dcb_to_dec((temp >> 16) & 0x3F);
        *min = kit_dcb_to_dec((temp >> 8) & 0x7F);
        *sec = kit_dcb_to_dec(temp & 0x7F);
        return true;
    }
    else
    {
        *hour = *min = *sec = 0;
        return false;
    }
}

//year 20xx, month 1-12, day 1-31
bool drv_rtc_get_date(int32_t *year, int32_t *month, int32_t *day)
{
    uint32_t temp = 0;
    if(drv_rtc_wait_sync() == true)
    {
        temp = RTC->DR;
        *year = kit_dcb_to_dec((temp >> 16) & 0xFF) + 2000;
        *month = kit_dcb_to_dec((temp >> 8) & 0x1F);
        *day = kit_dcb_to_dec(temp & 0x3F);
        return true;
    }
    else
    {
        *year = 2000;
        *month = *day = 1;
        return false;
    }
}

uint32_t drv_rtc_get_tick(void)
{
    struct tm tmp;
    uint32_t res = 0;

    tmp.tm_year = 0;
    if((drv_rtc_get_time(&tmp.tm_hour, &tmp.tm_min, &tmp.tm_sec) == true)
            && (drv_rtc_get_date(&tmp.tm_year, &tmp.tm_mon, &tmp.tm_mday) == true))
    {
        tmp.tm_mon--;
        tmp.tm_year = (tmp.tm_year > 2018) ? (tmp.tm_year - 1900) : 119;
        res = kit_time_get_stamp(2019, &tmp);
    }

    return res;
}

bool drv_rtc_set_tick(uint32_t tick)
{
    struct tm *tmp;
    bool res = false;

    if(drv_rtc_get_tick() != tick)
    {
        tmp = kit_time_get_date(2019, tick);
        //标准库月0-11 ST月为1-12，ST年从2000开始只保留十位和各位
        if((tmp->tm_year >= 119) && (drv_rtc_set_time(tmp->tm_hour, tmp->tm_min, tmp->tm_sec) == true)
                && (drv_rtc_set_date((tmp->tm_year + 1900), tmp->tm_mon + 1, tmp->tm_mday) == true))
        {
            res = true;
        }
    }
    else
    {
        res = true;
    }

    return res;
}

uint16_t drv_rtc_get_ms(void)
{
    uint32_t tmp = 0;
    /* Get sub seconds values from the correspondent registers*/
    tmp = (uint32_t)(RTC->SSR);
    /* Read DR register to unfroze calendar registers */
    (void)(RTC->DR);
    tmp = (0x03FF - tmp) * 1000 / (0x03FF + 1);

    return tmp;
}

bool drv_rtc_set_ms(uint16_t ms)
{
    bool res = false;
    uint32_t cur_ms, cnt = 0;
    /* Disable the write protection for RTC registers */
    RTC->WPR = 0xCA;
    RTC->WPR = 0x53;

    cur_ms = drv_rtc_get_ms();
    if(ms != cur_ms)
    {
        RTC->WPR = 0xCA;
        RTC->WPR = 0x53;
        /* Check if a Shift is pending*/
        while(((RTC->ISR & RTC_ISR_SHPF) != RESET) && (cnt++ < 1000));
        /* Check if the Shift pending is completed or if there is no Shift operation at all*/
        if((RTC->ISR & RTC_ISR_SHPF) == RESET)
        {
            /* check if the reference clock detection is disabled */
            if((RTC->CR & RTC_CR_REFCKON) == RESET)
            {
                if(cur_ms > ms)
                {
                    cur_ms = (cur_ms - ms) * (0x3FF + 1) / 1000;
                }
                else
                {
                    cur_ms = (1000 - ms + cur_ms) * (0x3FF + 1) / 1000;
                }
                RTC->SHIFTR = cur_ms;
                res = drv_rtc_wait_sync();
            }
        }
        /* Enable the write protection for RTC registers */
        RTC->WPR = 0xFF;
    }
    return res;
}

#include "stdio.h"
char rtc_time_str[20];
//Tan 2023/07/28 增加简易时间
char *drv_rtc_get_time_string(void)
{
    struct tm tmp;

    drv_rtc_get_time(&tmp.tm_hour, &tmp.tm_min, &tmp.tm_sec);
    sprintf(rtc_time_str, "%2d:%2d:%2d", tmp.tm_hour, tmp.tm_min, tmp.tm_sec);

    return rtc_time_str;
}

