nt9856x/code/application/source/cardv/SrcCode/Gx/GxPower/GxTime.c
2023-03-28 15:07:53 +08:00

227 lines
5.8 KiB
C
Executable File

#include <stdio.h>
#include <string.h>
#include "kwrap/util.h"
#include "GxTime.h"
#include "DxPower.h"
#include "PowerDef.h"
#include "DxApi.h"
#include "Dx.h"
#include "DxType.h"
#include <time.h>
#define THIS_DBGLVL 2 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER
///////////////////////////////////////////////////////////////////////////////
#define __MODULE__ GxTm
#define __DBGLVL__ THIS_DBGLVL
//#define __DBGFLT__ "*" //*=All, [mark]=CustomClass
#define __DBGFLT__ "[charge]" //*=All, [mark]=CustomClass
#include "kwrap/debug.h"
extern DX_HANDLE power_obj;
//-----------------------------------------------------------------------------
// Date-Time util
//-----------------------------------------------------------------------------
static struct tm g_ctv_zero = {0};
void GxTime_GetTime(struct tm* p_ctv)
{
if (!p_ctv) return;
if (!power_obj) {
*(p_ctv) = g_ctv_zero;
return;
}
Dx_Control(power_obj, DRVPWR_CTRL_CURRENT_TIME, 1, (UINT32)p_ctv);//1=read
}
void GxTime_SetTime(struct tm ctv)
{
if (!power_obj) {
return;
}
Dx_Control(power_obj, DRVPWR_CTRL_CURRENT_TIME, 0, (UINT32)&ctv); //0=write
}
/**
RTC Date
*/
typedef union {
// Format conformed to RTC register
_PACKED_BEGIN struct {
UBITFIELD day: 5; ///< Day
UBITFIELD month: 4; ///< Month
UBITFIELD year: 12; ///< Year
} _PACKED_END s;
UINT32 value; ///< Date value all together Y:M:D
} RTC_DATE, *PRTC_DATE;
static const UINT8 uiRTCDayOfMonth[2][12] = {
// Not leap year
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
// Leap year
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
static const UINT32 uiRTCDayOfYear[2] = {365, 366};
// Base date
static RTC_DATE RTCBaseDate = {1, 1, 1900};
/**
Check if leap year
This function is used to check if the specified year is a leap year.
@param[in] uiYear The year you want to check (0~0xFFFFFFFF)
@return
- @b TRUE : Is a leap year
- @b FALSE : Isn't a leap year
*/
BOOL GxTime_IsLeapYear(UINT32 uiYear)
{
// New algorithm
return (BOOL)((((uiYear % 4) == 0) && (((uiYear % 100) != 0) || ((uiYear % 400) == 0))));
}
/**
Convert date to number of days to base date.
Convert date to number of days to base date.
@param[in] rtcDate Absolute date
@return Days from base date
*/
///////// -- Chris -- Buggy if base date is not yyyy/01/01
UINT32 GxTime_Time2Days(struct tm ctv)
{
UINT32 uiDays;
UINT32 i;
RTC_DATE rtcDate;
rtcDate.s.day = ctv.tm_mday; /* day of the month - [1,31] */
rtcDate.s.month = ctv.tm_mon; /* months since January - [0,11] */
rtcDate.s.year = ctv.tm_year; /* years since 2000 */
uiDays = 0;
// Year
for (i = RTCBaseDate.s.year; i < rtcDate.s.year; i++) {
uiDays += uiRTCDayOfYear[GxTime_IsLeapYear(i)];
}
// Month
for (i = RTCBaseDate.s.month; i < rtcDate.s.month; i++) {
uiDays += uiRTCDayOfMonth[GxTime_IsLeapYear(rtcDate.s.year)][i - 1];
}
uiDays += rtcDate.s.day - RTCBaseDate.s.day;
return uiDays;
}
/**
Convert days to date from base date.
This function is used to convert days to date from base date.
@param[in] uiDays Number of days from base date
@return Converted absolute date
*/
///////// -- Chris -- Buggy if base date is not yyyy/01/01
struct tm GxTime_Days2Time(UINT32 uiDays)
{
struct tm ctv = {0};
RTC_DATE Date;
UINT32 uiYear, uiMonth;
for (uiYear = RTCBaseDate.s.year; uiDays >= uiRTCDayOfYear[GxTime_IsLeapYear(uiYear)]; uiYear++) {
uiDays -= uiRTCDayOfYear[GxTime_IsLeapYear(uiYear)];
}
for (uiMonth = RTCBaseDate.s.month; uiDays >= uiRTCDayOfMonth[GxTime_IsLeapYear(uiYear)][uiMonth - 1]; uiMonth++) {
uiDays -= uiRTCDayOfMonth[GxTime_IsLeapYear(uiYear)][uiMonth - 1];
}
Date.value = 0;
Date.s.day = RTCBaseDate.s.day + uiDays;
Date.s.month = uiMonth;
Date.s.year = uiYear;
ctv.tm_mday = Date.s.day; /* day of the month - [1,31] */
ctv.tm_mon = Date.s.month; /* months since January - [0,11] */
ctv.tm_year = Date.s.year; /* years since 2000 */
ctv.tm_hour = 0;
ctv.tm_min = 0;
ctv.tm_sec = 0;
// NOT support the following function..
ctv.tm_isdst = 0;
ctv.tm_yday = 0;
ctv.tm_wday = 0;
return ctv;
}
INT32 GxTime_CalcMonthDays(INT32 year, INT32 month)
{
INT32 day = 31;
INT32 year_ext = 0;
if (GxTime_IsLeapYear(year) == TRUE) {
year_ext = 1;
}
if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
day = 30;
}
if (month == 2) {
day = 28 + year_ext;
}
return day;
}
struct tm GxTime_AddTime(struct tm ctv, struct tm diff)
{
INT32 maxday;
ctv.tm_sec += diff.tm_sec; /* seconds after the minute - [0,59] */
ctv.tm_min += diff.tm_min; /* minutes after the hour - [0,59] */
ctv.tm_hour += diff.tm_hour; /* hours since midnight - [0,23] */
ctv.tm_mday += diff.tm_mday; /* day of the month - [1,31] */
ctv.tm_mon += diff.tm_mon; /* months since January - [0,11] */
ctv.tm_year += diff.tm_year; /* years since 2000 */
if (ctv.tm_sec >= 60) {
ctv.tm_min += ctv.tm_sec / 60;
ctv.tm_sec = ctv.tm_sec % 60;
}
if (ctv.tm_min >= 60) {
ctv.tm_hour += ctv.tm_min / 60;
ctv.tm_min = ctv.tm_min % 60;
}
if (ctv.tm_hour >= 24) {
ctv.tm_mday += ctv.tm_hour / 24;
ctv.tm_hour = ctv.tm_hour % 24;
}
maxday = GxTime_CalcMonthDays(ctv.tm_year, ctv.tm_mon);
while (ctv.tm_mday > maxday) {
ctv.tm_mday -= maxday;
ctv.tm_mon ++;
//month range = [1,12]
if (ctv.tm_mon > 12) {
ctv.tm_year += (ctv.tm_mon - 1) / 12;
ctv.tm_mon = ((ctv.tm_mon - 1) % 12) + 1;
}
maxday = GxTime_CalcMonthDays(ctv.tm_year, ctv.tm_mon);
}
//month range = [1,12]
if (ctv.tm_mon > 12) {
ctv.tm_year += (ctv.tm_mon - 1) / 12;
ctv.tm_mon = ((ctv.tm_mon - 1) % 12) + 1;
}
return ctv;
}
//@}