sc8-gat-stand/gat_stand_fw/user/periph/rtc.c

165 lines
3.3 KiB
C

/*
* rtc.c
*
* Created on: Oct 16, 2024
* Author: true
*/
#include <ch32v20x.h>
#include <stdint.h>
#include "periph/rtc.h"
#define RTC_INIT_PATTERN 0x1337
static const uint8_t days_per_mon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
uint8_t rtc_state;
void rtc_set_state(uint16_t state)
{
rtc_state = state;
}
/*
* @fn rtc_is_leapyear
* @brief Returns true if year is a leap year.
*
* @param year
*
* @return 1 - Yes
* 0 - No
*/
uint8_t rtc_is_leapyear(u16 year)
{
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 400 == 0) {
return 1;
} else {
return 0;
}
}
else return 1;
}
else return 0;
}
/*
* @fn rtc_set_clock
* @brief Set Time.
*
* @param Struct of RTClock
*
* @return 1 - error
* 0 - success
*/
int8_t rtc_set_clock(struct RTClock *c)
{
uint16_t x;
uint8_t m;
uint32_t count = 0;
if(c->year < 1970 || c->year > 2099)
return -1;
for(x = 1970; x < c->year; x++) {
if (rtc_is_leapyear(x))
count += 31622400;
else
count += 31536000;
}
m = c->mon - 1;
for(x = 0; x < m; x++){
count += (u32)days_per_mon[x] * 86400;
if(rtc_is_leapyear(c->year) && x == 1)
count += 86400;
}
count += (u32)(c->day - 1) * 86400;
count += (u32)c->h * 3600;
count += (u32)c->m * 60;
count += c->s;
PWR_BackupAccessCmd(ENABLE);
RTC_SetCounter(count);
RTC_WaitForLastTask();
return 0;
}
int8_t rtc_init()
{
uint32_t timeout;
static const struct RTClock clock = {
.year = 2024,
.mon = 11,
.day = 1,
.h = 8,
.m = 0,
.s = 0
};
// enable access to RTC registers
PWR_BackupAccessCmd(ENABLE);
// get RTC state
// if things aren't configured it'll be initialized in a moment
rtc_state = BKP_ReadBackupRegister(RTC_STATE_DR);
RTC_WaitForLastTask();
// is RTC already configured?
if (BKP_ReadBackupRegister(RTC_INIT_DR) != RTC_INIT_PATTERN) {
// must not be. initialize rtc
BKP_DeInit();
RCC_LSEConfig(RCC_LSE_ON);
timeout = SystemCoreClock / 2;
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET && timeout--);
// if crystal didn't start in time, let the application know
if (!timeout) return -1;
// use crystal for RTC and enable it
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForLastTask();
RTC_WaitForSynchro();
// RTC_ITConfig(RTC_IT_ALR, ENABLE);
// RTC_ITConfig(RTC_IT_SEC, ENABLE);
// RTC_WaitForLastTask();
RTC_EnterConfigMode();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
// set an initial time
rtc_set_clock((struct RTClock *)&clock);
RTC_ExitConfigMode();
rtc_state = RTC_STATE_CLOCK_NOT_SET;
BKP_WriteBackupRegister(RTC_STATE_DR, rtc_state);
RTC_WaitForLastTask();
BKP_WriteBackupRegister(RTC_INIT_DR, RTC_INIT_PATTERN);
// RTC_NVIC_Config();
// RTC_Get();
}
RTC_WaitForLastTask();
return 0;
}