Rtc_Flagchip_FC7240/Src/RtcFC7240.c

375 lines
9.0 KiB
C

//
// Created by cfif on 17.11.22.
//
#include "RtcFC7240.h"
#include <SystemDelayInterface.h>
#include <time.h>
#include <string.h>
#include "fc7xxx_driver_csc.h"
#include "fc7xxx_driver_scg.h"
#include "fc7xxx_driver_rtc.h"
#define SECONDS_DAY 86400UL
#define SECONDS_HOUR 3600UL
#define SECONDS_MINUTE 60UL
#define MINUTES_HOUR 60UL
#define HOURS_DAY 24UL
#define DAYS_LEAP_YEAR 366UL
#define DAYS_COM_YEAR 365UL
#define START_YEAR 1970UL
#define END_YEAR 2099UL
typedef struct
{
uint16_t u16Year; /**< Year */
uint8_t u8Month; /**< Month */
uint8_t u8Day; /**< Day */
uint8_t u8Hour; /**< Hour */
uint8_t u8Minute; /**< Minute */
uint8_t u8Second; /**< Second */
} RTC_TimeDate;
/* Table of month length (in days) for the Common-year*/
static const uint8_t ComYear[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
/* Table of month length (in days) for the Leap-year*/
static const uint8_t LeapYear[] = {0U, 31U, 29U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
static bool RTC_IsLeapYear(uint16_t u16Year)
{
bool bYearLeap = false;
if ((u16Year % 4U) > 0U)
{
bYearLeap = false;
}
else if ((u16Year % 100U) > 0U)
{
bYearLeap = true;
}
else if ((u16Year % 400U) > 0U)
{
bYearLeap = false;
}
else
{
bYearLeap = true;
}
/* Return the exit code */
return bYearLeap;
}
static bool RTC_CheckTimeDate(const RTC_TimeDate * const pTimeDate)
{
bool bCheckReturn = true;
const uint8_t * pMonth;
pMonth = RTC_IsLeapYear(pTimeDate->u16Year) ? LeapYear : ComYear;
if (pTimeDate->u16Year < START_YEAR || pTimeDate->u16Year > END_YEAR
|| pTimeDate->u8Month < 1U || pTimeDate->u8Month > 12U
|| pTimeDate->u8Day < 1U || pTimeDate->u8Day > pMonth[pTimeDate->u8Month]
|| pTimeDate->u8Hour >= 24
|| pTimeDate->u8Minute >= 60
|| pTimeDate->u8Second >= 60)
{
bCheckReturn = false;
}
return bCheckReturn;
}
static void RTC_TimeDate_To_Second(RTC_TimeDate * const pTimeDate, uint32_t u32Second)
{
uint32_t u32CountDays;
uint32_t u32TempCount;
uint32_t u32TempDays;
u32CountDays = u32Second / SECONDS_DAY;
u32TempCount = u32Second % SECONDS_DAY;
pTimeDate->u8Hour = (uint8_t)(u32TempCount / SECONDS_HOUR);
u32TempCount = u32TempCount % SECONDS_HOUR;
pTimeDate->u8Minute = (uint8_t)(u32TempCount / SECONDS_MINUTE);
pTimeDate->u8Second = (uint8_t)(u32TempCount % SECONDS_MINUTE);
pTimeDate->u16Year = (uint16_t)START_YEAR;
u32TempDays = DAYS_COM_YEAR;
while (u32CountDays >= u32TempDays)
{
pTimeDate->u16Year++;
u32CountDays -= u32TempDays;
u32TempDays = (RTC_IsLeapYear(pTimeDate->u16Year)) ? DAYS_LEAP_YEAR : DAYS_COM_YEAR;
}
u32TempDays += 1;
for (uint8_t u8TempMonth = 1; u8TempMonth <= 12; u8TempMonth++)
{
u32TempCount = (RTC_IsLeapYear(pTimeDate->u16Year)) ? (uint32_t)LeapYear[u8TempMonth] : (uint32_t)ComYear[u8TempMonth];
if (u32TempDays <= u32TempCount)
{
pTimeDate->u8Month = (uint8_t)u8TempMonth;
pTimeDate->u8Day = (uint8_t)u32TempDays;
break;
}
else
{
u32TempDays -= u32TempCount;
}
}
}
static uint32_t RTC_Second_To_TimeDate(const RTC_TimeDate * const pTimeDate)
{
uint32_t u32Second;
uint32_t u32TempDay;
u32Second = (pTimeDate->u16Year - START_YEAR) * SECONDS_DAY * DAYS_COM_YEAR;
for (uint32_t u32TempYear = START_YEAR; u32TempYear < pTimeDate->u16Year; u32TempYear++)
{
if (RTC_IsLeapYear((uint16_t)u32TempYear))
{
u32Second += SECONDS_DAY;
}
}
for (uint8_t u8TempMonth = 1; u8TempMonth < pTimeDate->u8Month; u8TempMonth++)
{
u32TempDay = (RTC_IsLeapYear(pTimeDate->u16Year)) ? (uint32_t)LeapYear[u8TempMonth] : (uint32_t)ComYear[u8TempMonth];
u32Second += (u32TempDay * SECONDS_DAY);
}
u32Second += ((uint32_t)((pTimeDate->u8Day - 1U) * SECONDS_DAY) + \
pTimeDate->u8Hour * SECONDS_HOUR + \
pTimeDate->u8Minute * SECONDS_MINUTE + \
pTimeDate->u8Second);
return u32Second;
}
/**
* @brief Set time and date
*
* @param pRtcHandle the RTC instance
* @param pTimeDate the structure of time and date
*/
static void RTC_SetTimeDate(const RTC_TimeDate *const pTimeDate) {
uint32_t u32Second;
if (true == RTC_CheckTimeDate(pTimeDate)) {
u32Second = RTC_Second_To_TimeDate(pTimeDate);
RTC_SetSecondCounterValue(u32Second);
}
}
/**
* @brief Get time and date
*
* @param pRtcHandle the RTC instance
* @param pTimeDate the structure of time and date
*/
void RTC_GetTimeDate(RTC_TimeDate * const pTimeDate)
{
uint32_t u32Second;
u32Second = RTC_GetTime();
RTC_TimeDate_To_Second(pTimeDate, u32Second);
}
tRtcFlagchip vRtcInit() {
tRtcFlagchip rtcFlagchip;
RtcFlagchip_Init(&rtcFlagchip);
return rtcFlagchip;
}
void RtcFlagchip_Init(tRtcFlagchip *env) {
// enable SIRC32K clock source
SCG_Sirc32kType tSIRC32KStruct =
{
.bLock = true
};
SCG_EnableSIRC32K(&tSIRC32KStruct);
// set RTC clock source is SIRC32K clock
CSC0_AONCLKSRType tAONCLKStruct;
tAONCLKStruct.eRtcSel = CSC0_RTC_SIRC32K_CLK;
tAONCLKStruct.eAon32KSel = CSC0_AON32K_SIRCDIV_32K_CLK;
tAONCLKStruct.eAonSel = CSC0_AON_SIRCDIV_128K_CLK;
CSC0_SetAonClkSrc(&tAONCLKStruct, true);
RTC_InitType tInitStruct = {0};
tInitStruct.eSecIntAndClkoutFreq = RTC_FREQ_1HZ; // set interrupt frequency to 1HZ
RTC_Init(&tInitStruct);
RTC_Start();
#ifdef ACCESS_RTC
*env = (tRtcFlagchip) {
.access = osMutexNew(NULL)
};
#else
*env = (tRtcFlagchip) {
};
#endif
}
static uint16_t vRtcSet(tRtcFlagchip *env, time_t *timestamp) {
struct tm dateTime;
RTC_TimeDate tTimeDate;
localtime_r(timestamp, &dateTime);
tTimeDate.u16Year = dateTime.tm_year + 1900;
tTimeDate.u8Month = dateTime.tm_mon + 1;
tTimeDate.u8Day = dateTime.tm_mday;
tTimeDate.u8Hour = dateTime.tm_hour;
tTimeDate.u8Minute = dateTime.tm_min;
tTimeDate.u8Second = dateTime.tm_sec;
#ifdef ACCESS_RTC
if (osMutexAcquire(env->access, 1000) == osOK) {
RTC_SetTimeDate(&tTimeDate);
osMutexRelease(env->access);
} else {
RTC_SetTimeDate(&tTimeDate);
}
#else
RTC_SetTimeDate(&tTimeDate);
#endif
return 0;
}
static uint16_t vRtcSetTM(tRtcFlagchip *env, struct tm *timestampTM) {
RTC_TimeDate tTimeDate;
tTimeDate.u16Year = timestampTM->tm_year + 1900;
tTimeDate.u8Month = timestampTM->tm_mon + 1;
tTimeDate.u8Day = timestampTM->tm_mday;
tTimeDate.u8Hour = timestampTM->tm_hour;
tTimeDate.u8Minute = timestampTM->tm_min;
tTimeDate.u8Second = timestampTM->tm_sec;
#ifdef ACCESS_RTC
if (osMutexAcquire(env->access, 1000) == osOK) {
RTC_SetTimeDate(&tTimeDate);
osMutexRelease(env->access);
} else {
RTC_SetTimeDate(&tTimeDate);
}
#else
RTC_SetTimeDate(&tTimeDate);
#endif
return 0;
}
static void v_RtcGet(time_t *timestamp) {
RTC_TimeDate tTimeDate;
RTC_GetTimeDate(&tTimeDate);
struct tm dateTime;
memset(&dateTime, 0, sizeof(dateTime));
dateTime.tm_year = tTimeDate.u16Year - 1900;
dateTime.tm_mon = tTimeDate.u8Month - 1;
dateTime.tm_mday = tTimeDate.u8Day;
dateTime.tm_hour = tTimeDate.u8Hour;
dateTime.tm_min = tTimeDate.u8Minute;
dateTime.tm_sec = tTimeDate.u8Second;
*timestamp = mktime(&dateTime);
*timestamp &= 0xFFFFFFFF;
}
static uint16_t vRtcGet(tRtcFlagchip *env, time_t *timestamp) {
#ifdef ACCESS_RTC
if (osMutexAcquire(env->access, 1000) == osOK) {
memset(timestamp, 0, sizeof(time_t));
v_RtcGet(timestamp);
osMutexRelease(env->access);
} else {
v_RtcGet(timestamp);
}
#else
v_RtcGet(timestamp);
#endif
return 0;
}
static void v_RtcGetTM(struct tm *timestampTM) {
RTC_TimeDate tTimeDate;
RTC_GetTimeDate(&tTimeDate);
memset(timestampTM, 0, sizeof(struct tm));
timestampTM->tm_year = tTimeDate.u16Year - 1900;
timestampTM->tm_mon = tTimeDate.u8Month - 1;
timestampTM->tm_mday = tTimeDate.u8Day;
timestampTM->tm_hour = tTimeDate.u8Hour;
timestampTM->tm_min = tTimeDate.u8Minute;
timestampTM->tm_sec = tTimeDate.u8Second;
}
static uint16_t vRtcGetTM(tRtcFlagchip *env, struct tm *timestampTM) {
#ifdef ACCESS_RTC
if (osMutexAcquire(env->access, 1000) == osOK) {
v_RtcGetTM(timestampTM);
osMutexRelease(env->access);
} else {
v_RtcGetTM(timestampTM);
}
#else
v_RtcGetTM(timestampTM);
#endif
return 0;
}
tRtcIO RtcFlagchip_GetIo(tRtcFlagchip *env) {
tRtcIO io = {
.env = env,
.get = (RtcIOTransaction) vRtcGet,
.set = (RtcIOTransaction) vRtcSet,
.getTM = (RtcIOTransactionTM) vRtcGetTM,
.setTM = (RtcIOTransactionTM) vRtcSetTM
};
return io;
}