Rtc_Flagchip_FC7240/Src/RtcFC7240.c

448 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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;
}
*/
static void RTC_TimeDate_To_Second(RTC_TimeDate * const pTimeDate, uint32_t u32Second)
{
uint32_t u32CountDays;
uint32_t u32TempCount;
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;
// Вычисляем год
uint32_t u32DaysInYear = DAYS_COM_YEAR;
while (u32CountDays >= u32DaysInYear)
{
pTimeDate->u16Year++;
u32CountDays -= u32DaysInYear;
u32DaysInYear = RTC_IsLeapYear(pTimeDate->u16Year) ? DAYS_LEAP_YEAR : DAYS_COM_YEAR;
}
// u32CountDays теперь содержит день года (0-364/365)
// Преобразуем в месяц и день
const uint8_t* pMonthDays = RTC_IsLeapYear(pTimeDate->u16Year) ? LeapYear : ComYear;
uint32_t u32DayOfYear = u32CountDays + 1; // День года (1-366)
for (uint8_t u8TempMonth = 1; u8TempMonth <= 12; u8TempMonth++)
{
uint32_t u32DaysInMonth = pMonthDays[u8TempMonth];
if (u32DayOfYear <= u32DaysInMonth)
{
pTimeDate->u8Month = u8TempMonth;
pTimeDate->u8Day = (uint8_t)u32DayOfYear;
break;
}
else
{
u32DayOfYear -= u32DaysInMonth;
}
}
}
static uint32_t RTC_Second_To_TimeDate(const RTC_TimeDate * const pTimeDate)
{
uint32_t u32Second = 0;
// Считаем дни за полные годы с 1970
for (uint16_t u16Year = START_YEAR; u16Year < pTimeDate->u16Year; u16Year++)
{
u32Second += RTC_IsLeapYear(u16Year) ? DAYS_LEAP_YEAR * SECONDS_DAY : DAYS_COM_YEAR * SECONDS_DAY;
}
// Считаем дни за полные месяцы в текущем году
const uint8_t* pMonthDays = RTC_IsLeapYear(pTimeDate->u16Year) ? LeapYear : ComYear;
for (uint8_t u8Month = 1; u8Month < pTimeDate->u8Month; u8Month++)
{
u32Second += pMonthDays[u8Month] * SECONDS_DAY;
}
// Считаем дни, часы, минуты, секунды
u32Second += ((uint32_t)(pTimeDate->u8Day - 1) * SECONDS_DAY) +
((uint32_t)pTimeDate->u8Hour * SECONDS_HOUR) +
((uint32_t)pTimeDate->u8Minute * SECONDS_MINUTE) +
((uint32_t)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;
}