Advanced Distributed Systems module at HSLU
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
ADIS_Projects/McuLib/src/McuTimeDate.c

1609 lines
59 KiB

/* ###################################################################
** This component module is generated by Processor Expert. Do not modify it.
** Filename : McuTimeDate.h
** Project : FRDM-K64F_Generator
** Processor : MK64FN1M0VLL12
** Component : GenericTimeDate
** Version : Component 01.064, Driver 01.00, CPU db: 3.00.000
** Compiler : GNU C Compiler
** Date/Time : 2020-08-10, 19:29, # CodeGen: 671
** Abstract :
** Software date/time module.
** Settings :
** Component name : McuTimeDate
** Software RTC : Enabled
** Tick Time (ms) : 10
** RTOS : Enabled
** RTOS : McuRTOS
** Hardware RTC : Enabled
** Internal : Disabled
** External RTC : Disabled
** Set Time and Date :
** Software RTC : yes
** Internal RTC : no
** External RTC : yes
** Get Time and Date : Software RTC
** Init() :
** Defaults :
** Time : 17:51:31
** Date : 2019-08-01
** Call Init() in startup : yes
** Software RTC Initialization : Init from Defaults
** System :
** Critical Section : McuCriticalSection
** SDK : McuLib
** Shell : Enabled
** Utility : McuUtility
** Shell : McuShell
** Contents :
** AddTick - void McuTimeDate_AddTick(void);
** AddTicks - void McuTimeDate_AddTicks(uint16_t nofTicks);
** TicksToTime - uint8_t McuTimeDate_TicksToTime(uint32_t ticks, TIMEREC *time);
** TimeToTicks - uint8_t McuTimeDate_TimeToTicks(TIMEREC *time, uint32_t *ticks);
** CalculateDayOfWeek - uint8_t McuTimeDate_CalculateDayOfWeek(uint16_t Year, uint8_t Month, uint8_t...
** SetTime - uint8_t McuTimeDate_SetTime(uint8_t Hour, uint8_t Min, uint8_t Sec, uint8_t...
** GetTime - uint8_t McuTimeDate_GetTime(TIMEREC *time);
** SetDate - uint8_t McuTimeDate_SetDate(uint16_t Year, uint8_t Month, uint8_t Day);
** GetDate - uint8_t McuTimeDate_GetDate(DATEREC *date);
** SetTimeDate - uint8_t McuTimeDate_SetTimeDate(TIMEREC *time, DATEREC *date);
** GetTimeDate - uint8_t McuTimeDate_GetTimeDate(TIMEREC *time, DATEREC *date);
** SetSWTimeDate - uint8_t McuTimeDate_SetSWTimeDate(TIMEREC *time, DATEREC *date);
** GetSWTimeDate - uint8_t McuTimeDate_GetSWTimeDate(TIMEREC *time, DATEREC *date);
** SetInternalRTCTimeDate - uint8_t McuTimeDate_SetInternalRTCTimeDate(TIMEREC *time, DATEREC *date);
** GetInternalRTCTimeDate - uint8_t McuTimeDate_GetInternalRTCTimeDate(TIMEREC *time, DATEREC *date);
** SyncWithInternalRTC - uint8_t McuTimeDate_SyncWithInternalRTC(void);
** SyncSWtimeToInternalRTCsec - uint8_t McuTimeDate_SyncSWtimeToInternalRTCsec(void);
** SetExternalRTCTimeDate - uint8_t McuTimeDate_SetExternalRTCTimeDate(TIMEREC *time, DATEREC *date);
** GetExternalRTCTimeDate - uint8_t McuTimeDate_GetExternalRTCTimeDate(TIMEREC *time, DATEREC *date);
** SyncWithExternalRTC - uint8_t McuTimeDate_SyncWithExternalRTC(void);
** UnixSecondsToTimeDateCustom - void McuTimeDate_UnixSecondsToTimeDateCustom(int32_t seconds, int8_t...
** UnixSecondsToTimeDate - void McuTimeDate_UnixSecondsToTimeDate(int32_t seconds, int8_t offset_hours,...
** TimeDateToUnixSecondsCustom - int32_t McuTimeDate_TimeDateToUnixSecondsCustom(TIMEREC *time, DATEREC *date,...
** TimeDateToUnixSeconds - int32_t McuTimeDate_TimeDateToUnixSeconds(TIMEREC *time, DATEREC *date,...
** AddDateString - uint8_t McuTimeDate_AddDateString(uint8_t *buf, size_t bufSize, DATEREC...
** AddTimeString - uint8_t McuTimeDate_AddTimeString(uint8_t *buf, size_t bufSize, TIMEREC...
** ParseCommand - uint8_t McuTimeDate_ParseCommand(const unsigned char *cmd, bool *handled,...
** DeInit - void McuTimeDate_DeInit(void);
** Init - uint8_t McuTimeDate_Init(void);
**
** * Copyright (c) 2011-2020, Erich Styger
** * Web: https://mcuoneclipse.com
** * SourceForge: https://sourceforge.net/projects/mcuoneclipse
** * Git: https://github.com/ErichStyger/McuOnEclipse_PEx
** * All rights reserved.
** *
** * Redistribution and use in source and binary forms, with or without modification,
** * are permitted provided that the following conditions are met:
** *
** * - Redistributions of source code must retain the above copyright notice, this list
** * of conditions and the following disclaimer.
** *
** * - Redistributions in binary form must reproduce the above copyright notice, this
** * list of conditions and the following disclaimer in the documentation and/or
** * other materials provided with the distribution.
** *
** * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
** * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
** * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** ###################################################################*/
/*!
** @file McuTimeDate.h
** @version 01.00
** @brief
** Software date/time module.
*/
/*!
** @addtogroup McuTimeDate_module McuTimeDate module documentation
** @{
*/
/* MODULE McuTimeDate. */
#include "McuTimeDate.h"
#include <stdlib.h> /* for NULL */
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC
#include "McuExtRTC.h"
#endif
#if McuTimeDate_TICK_TIME_MS==0
#error "Tick period cannot be zero!"
#endif
#define McuTimeDate_TICKS_PER_S (1000/McuTimeDate_TICK_TIME_MS) /* number of timer ticks per second */
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC
/* counters used by software RTC */
static uint8_t CntDay; /* Day counter */
static uint8_t CntMonth; /* Month counter */
static uint16_t CntYear; /* Year Counter */
static uint32_t tickCntr; /* Software tick counter (1 tick = McuTimeDate_TICK_TIME_MS ms) */
#endif
/* Table of month length (in days) */
static const uint8_t ULY[12] = {31U,28U,31U,30U,31U,30U,31U,31U,30U,31U,30U,31U}; /* Un-leap-year */
static const uint8_t LY[12] = {31U,29U,31U,30U,31U,30U,31U,31U,30U,31U,30U,31U}; /* Leap-year */
static uint8_t AddDateToBuf(uint8_t *buf, uint16_t bufSize, DATEREC *tdate) {
McuUtility_strcatNum16uFormatted(buf, bufSize, tdate->Day, '0', 2);
McuUtility_chcat(buf, bufSize, '.');
McuUtility_strcatNum16uFormatted(buf, bufSize, tdate->Month, '0', 2);
McuUtility_chcat(buf, bufSize, '.');
McuUtility_strcatNum16uFormatted(buf, bufSize, (uint16_t)tdate->Year, '0', 2);
return ERR_OK;
}
static uint8_t AddTimeToBuf(uint8_t *buf, uint16_t bufSize, TIMEREC *ttime) {
McuUtility_strcatNum16sFormatted(buf, bufSize, ttime->Hour, '0', 2);
McuUtility_chcat(buf, bufSize, ':');
McuUtility_strcatNum16sFormatted(buf, bufSize, ttime->Min, '0', 2);
McuUtility_chcat(buf, bufSize, ':');
McuUtility_strcatNum16sFormatted(buf, bufSize, ttime->Sec, '0', 2);
McuUtility_chcat(buf, bufSize, ',');
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
McuUtility_strcatNum16sFormatted(buf, bufSize, ttime->Sec100, '0', 2);
#else
McuUtility_strcatNum16sFormatted(buf, bufSize, 0, '0', 2);
#endif
return ERR_OK;
}
static uint8_t AddDate(uint8_t *buf, uint16_t bufSize, uint8_t (*GetTimeDateFn)(TIMEREC*, DATEREC*)) {
DATEREC tdate;
if (GetTimeDateFn(NULL, &tdate)!=ERR_OK) {
return ERR_FAILED;
}
return AddDateToBuf(buf, bufSize, &tdate);
}
static uint8_t AddTime(uint8_t *buf, uint16_t bufSize, uint8_t (*GetTimeDateFn)(TIMEREC*, DATEREC*)) {
TIMEREC ttime;
if (GetTimeDateFn(&ttime, NULL)!=ERR_OK) {
return ERR_FAILED;
}
return AddTimeToBuf(buf, bufSize, &ttime);
}
static uint8_t DateCmd(const unsigned char *cmd, McuShell_ConstStdIOType *io) {
/* precondition: cmd points to "McuTimeDate date" */
uint8_t day, month;
uint16_t year;
const unsigned char *p;
uint8_t res = ERR_OK;
p = cmd + sizeof("McuTimeDate date")-1;
if (*p==' ') { /* ok, have an argument */
if (McuUtility_ScanDate(&p, &day, &month, &year) == ERR_OK) { /* ok, format fine */
/* update software real time clock */
res = McuTimeDate_SetDate(year, month, day);
if (res != ERR_OK) {
McuShell_SendStr((unsigned char*)"*** Failure setting date\r\n", io->stdErr);
res = ERR_FAILED;
}
} else {
McuShell_SendStr((unsigned char*)"*** error while reading command! ***", io->stdErr);
McuShell_SendStr((void *)cmd, io->stdErr);
McuShell_SendStr((unsigned char*)"\r\n", io->stdErr);
res = ERR_FAILED;
}
} /* has an argument */
/* print now current date */
if (res==ERR_OK) {
unsigned char buf[sizeof("RTC: Wednesday dd:mm:yyyy\\r\\n")];
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"RTC: ");
if (AddDate(buf, sizeof(buf), McuTimeDate_GetTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get date\r\n", io->stdErr);
res = ERR_FAILED;
} else {
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStr(buf, io->stdOut);
}
}
return res;
}
static uint8_t TimeCmd(const unsigned char *cmd, McuShell_ConstStdIOType *io) {
uint8_t hour, minute, second, hSecond;
const unsigned char *p;
uint8_t res = ERR_OK;
p = cmd + sizeof("McuTimeDate time")-1;
if (*p==' ') { /* has an argument */
if (McuUtility_ScanTime(&p, &hour, &minute, &second, &hSecond)==ERR_OK) { /* format fine */
/* set SW RTC time */
res = McuTimeDate_SetTime(hour, minute, second, hSecond);
if (res != ERR_OK) {
McuShell_SendStr((unsigned char*)"*** Failure setting time\r\n", io->stdErr);
res = ERR_FAILED;
}
} else {
McuShell_SendStr((unsigned char*)"*** Error while reading command: ", io->stdErr);
McuShell_SendStr(cmd, io->stdErr);
McuShell_SendStr((unsigned char*)"\r\n", io->stdErr);
res = ERR_FAILED;
}
}
/* print now current time */
if (res==ERR_OK) {
unsigned char buf[sizeof("RTC: hh:mm:ss.hh\\r\\n")+5];
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)"RTC: ");
if (AddTime(buf, sizeof(buf), McuTimeDate_GetTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get time\r\n", io->stdErr);
res = ERR_FAILED;
} else {
McuUtility_strcat(buf, sizeof(buf), (unsigned char*)"\r\n");
McuShell_SendStr(buf, io->stdOut);
}
}
return res;
}
static uint8_t PrintStatus(McuShell_ConstStdIOType *io) {
uint8_t buf[24];
McuShell_SendStatusStr((unsigned char*)"McuTimeDate", (const unsigned char*)"Date and time information\r\n", io->stdOut);
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC
McuShell_SendStatusStr((unsigned char*)" SW RTC", (const unsigned char*)"", io->stdOut);
buf[0] = '\0';
if (AddDate(buf, sizeof(buf), McuTimeDate_GetSWTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get date!\r\n", io->stdErr);
return ERR_FAILED;
}
McuShell_SendStr(buf, io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)", ");
if (AddTime(buf, sizeof(buf), McuTimeDate_GetSWTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get time!\r\n", io->stdErr);
return ERR_FAILED;
} else {
McuShell_SendStr(buf, io->stdOut);
}
McuShell_SendStr((unsigned char*)"\r\n", io->stdOut);
#endif
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_LDD || McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_BEAN
McuShell_SendStatusStr((unsigned char*)" HW RTC", (const unsigned char*)"", io->stdOut);
buf[0] = '\0';
if (AddDate(buf, sizeof(buf), McuTimeDate_GetInternalRTCTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get internal RTC date!\r\n", io->stdErr);
return ERR_FAILED;
}
McuShell_SendStr(buf, io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)", ");
if (AddTime(buf, sizeof(buf), McuTimeDate_GetInternalRTCTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get internal RTC time!\r\n", io->stdErr);
return ERR_FAILED;
} else {
McuShell_SendStr(buf, io->stdOut);
}
McuShell_SendStr((unsigned char*)"\r\n", io->stdOut);
#endif
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC
McuShell_SendStatusStr((unsigned char*)" Ext. RTC", (const unsigned char*)"", io->stdOut);
buf[0] = '\0';
if (AddDate(buf, sizeof(buf), McuTimeDate_GetExternalRTCTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get external RTC date!\r\n", io->stdErr);
return ERR_FAILED;
}
McuShell_SendStr(buf, io->stdOut);
McuUtility_strcpy(buf, sizeof(buf), (unsigned char*)", ");
if (AddTime(buf, sizeof(buf), McuTimeDate_GetExternalRTCTimeDate)!=ERR_OK) {
McuShell_SendStr((unsigned char*)"***Failed to get external RTC time!\r\n", io->stdErr);
return ERR_FAILED;
} else {
McuShell_SendStr(buf, io->stdOut);
}
McuShell_SendStr((unsigned char*)"\r\n", io->stdOut);
#endif
return ERR_OK;
}
/*
** ===================================================================
** Method : AddTick (component GenericTimeDate)
**
** Description :
** Increments the tick counter of the software RTC. Needs to be
** called periodically by the application to increase the time
** tick count.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
void McuTimeDate_AddTick(void)
{
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC
const uint8_t *ptr; /* Pointer to ULY/LY table */
McuCriticalSection_CriticalVariable()
McuCriticalSection_EnterCritical(); /* need exclusive access to tick counter */
tickCntr++; /* Software timer counter increment by timer period */
McuCriticalSection_ExitCritical(); /* end of critical section */
if (tickCntr >= 24*3600UL*McuTimeDate_TICKS_PER_S) { /* Does the counter reach 24 hours? */
tickCntr -= 24*3600UL*McuTimeDate_TICKS_PER_S; /* If yes then reset it by subtracting exactly 24 hours */
McuCriticalSection_EnterCritical();
CntDay++; /* Increment day counter */
McuCriticalSection_ExitCritical();
if (CntYear & 0x03U) { /* Is this year un-leap-one? */
ptr = ULY; /* Set pointer to un-leap-year day table */
} else { /* Is this year leap-one? */
ptr = LY; /* Set pointer to leap-year day table */
}
ptr--; /* Decrement the pointer */
if (CntDay > ptr[CntMonth]) { /* Day counter overflow? */
CntDay = 1U; /* Set day counter on 1 */
McuCriticalSection_EnterCritical();
CntMonth++; /* Increment month counter */
McuCriticalSection_ExitCritical();
if (CntMonth > 12U) { /* Month counter overflow? */
CntMonth = 1U; /* Set month counter on 1 */
McuCriticalSection_EnterCritical();
CntYear++; /* Increment year counter */
McuCriticalSection_ExitCritical();
}
}
}
#endif
}
/*
** ===================================================================
** Method : AddTicks (component GenericTimeDate)
**
** Description :
** Same as AddTick(), but multiple ticks can be added in one
** step.
** Parameters :
** NAME - DESCRIPTION
** nofTicks - Number of ticks to be added
** Returns : Nothing
** ===================================================================
*/
void McuTimeDate_AddTicks(uint16_t nofTicks)
{
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC
while(nofTicks>0) {
McuTimeDate_AddTick();
nofTicks--;
}
#else
(void)nofTicks; /* not used */
#endif
}
/*
** ===================================================================
** Method : SetSWTimeDate (component GenericTimeDate)
**
** Description :
** This method sets a new actual time and date of the software
** RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to struct which contains the
** time to be set. Can be NULL if time shall
** not be set.
** * date - Pointer to struct which contains the
** date information to be set. Can be NULL if
** date shall not be set.
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SetSWTimeDate(TIMEREC *time, DATEREC *date)
{
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC
uint8_t res;
uint32_t nofTicks;
bool failed = FALSE;
McuCriticalSection_CriticalVariable()
if (time!=NULL) {
res = McuTimeDate_TimeToTicks(time, &nofTicks);
if (res!=ERR_OK) {
failed = TRUE;
}
if (res==ERR_OK) {
McuCriticalSection_EnterCritical();
tickCntr = nofTicks;
McuCriticalSection_ExitCritical();
}
}
if (date!=NULL) {
McuCriticalSection_EnterCritical();
CntDay = date->Day;
CntMonth = date->Month;
CntYear = date->Year;
McuCriticalSection_ExitCritical();
}
if (failed) {
return ERR_FAILED;
}
return ERR_OK;
#else
return ERR_FAILED;
#endif
}
/*
** ===================================================================
** Method : GetSWTimeDate (component GenericTimeDate)
**
** Description :
** This method returns current time and date from the software
** RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to the structure to return the
** time. Can be NULL.
** * date - Pointer to structure which returns the
** date information. Can be NULL
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_GetSWTimeDate(TIMEREC *time, DATEREC *date)
{
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC
uint8_t res;
uint32_t ticks;
bool failed = FALSE;
McuCriticalSection_CriticalVariable()
if (time!=NULL) {
McuCriticalSection_EnterCritical();
ticks = tickCntr;
McuCriticalSection_ExitCritical();
res = McuTimeDate_TicksToTime(ticks, time);
if (res!=ERR_OK) {
failed = TRUE;
}
}
if (date!=NULL) {
McuCriticalSection_EnterCritical();
date->Year = CntYear;
date->Month = CntMonth;
date->Day = CntDay;
McuCriticalSection_ExitCritical();
}
if (failed) {
return ERR_FAILED;
}
return ERR_OK;
#else
return ERR_FAILED;
#endif
}
/*
** ===================================================================
** Method : SetTime (component GenericTimeDate)
**
** Description :
** This method sets a new actual time of the software RTC.
** Parameters :
** NAME - DESCRIPTION
** Hour - Hours (0 - 23)
** Min - Minutes (0 - 59)
** Sec - Seconds (0 - 59)
** Sec100 - Hundredth of seconds (0 - 99)
** Returns :
** --- - Error code
** ===================================================================
*/
#ifdef __HIWARE__
#pragma MESSAGE DISABLE C5905 /* multiplication with one (happens if McuTimeDate_TICKS_PER_S is 100) */
#endif
uint8_t McuTimeDate_SetTime(uint8_t Hour, uint8_t Min, uint8_t Sec, uint8_t Sec100)
{
uint8_t res = ERR_FAILED;
TIMEREC time;
bool failed = FALSE;
if ((Sec100>99U) || (Sec>59U) || (Min>59U) || (Hour>23U)) {
return ERR_RANGE;
}
time.Hour = Hour;
time.Min = Min;
time.Sec = Sec;
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
time.Sec100 = Sec100;
#endif
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_SOFTWARE_RTC
res = McuTimeDate_SetSWTimeDate(&time, NULL);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_INTERNAL_RTC
res = McuTimeDate_SetInternalRTCTimeDate(&time, NULL);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_EXTERNAL_RTC
res = McuTimeDate_SetExternalRTCTimeDate(&time, NULL);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_ON_TIME_SET_EVENT
McuTimeDate_ON_TIME_SET_EVENT_NAME(Hour, Min, Sec, Sec100); /* call user event */
#endif
if (failed) {
res = ERR_FAILED;
}
return res;
}
#ifdef __HIWARE__
#pragma MESSAGE DEFAULT C5905 /* multiplication with one */
#endif
/*
** ===================================================================
** Method : GetTime (component GenericTimeDate)
**
** Description :
** This method returns current time from the software RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to the structure TIMEREC. It
** contains actual number of hours, minutes,
** seconds and hundredth of seconds.
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_GetTime(TIMEREC *time)
{
uint8_t res;
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_SOFTWARE_RTC
res = McuTimeDate_GetSWTimeDate(time, NULL);
#elif McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_INTERNAL_RTC
res = McuTimeDate_GetInternalRTCTimeDate(time, NULL);
#elif McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_EXTERNAL_RTC
res = McuTimeDate_GetExternalRTCTimeDate(time, NULL);
#else
#error "invalid configuration!"
res = ERR_FAILED;
#endif
/* call user event */
#if McuTimeDate_ON_TIME_GET_EVENT
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
McuTimeDate_ON_TIME_GET_EVENT_NAME(&time->Hour, &time->Min, &time->Sec, &time->Sec100);
#else
McuTimeDate_ON_TIME_GET_EVENT_NAME(&time->Hour, &time->Min, &time->Sec, 0);
#endif
#endif
return res;
}
/*
** ===================================================================
** Method : SetDate (component GenericTimeDate)
**
** Description :
** This method sets a new actual date of the software RTC.
** Parameters :
** NAME - DESCRIPTION
** Year - Years (16-bit unsigned integer)
** Month - Months (8-bit unsigned integer)
** Day - Days (8-bit unsigned integer)
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SetDate(uint16_t Year, uint8_t Month, uint8_t Day)
{
const uint8_t* ptr; /* Pointer to ULY/LY table */
uint8_t res = ERR_FAILED;
bool failed = FALSE;
DATEREC date;
if ((Year < 1998U) || (Year > 2099U) || (Month > 12U) || (Month == 0U) || (Day > 31U) || (Day == 0U)) {
return ERR_RANGE;
}
ptr = (((Year&0x03U)!=0U)?ULY:LY); /* Set pointer to leap-year or un-leap-year day table */
if (ptr[Month - 1U] < Day) { /* Does the obtained number of days exceed number of days in the appropriate month & year? */
return ERR_RANGE;
}
date.Year = Year;
date.Month = Month;
date.Day = Day;
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_SOFTWARE_RTC
res = McuTimeDate_SetSWTimeDate(NULL, &date);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_INTERNAL_RTC
res = McuTimeDate_SetInternalRTCTimeDate(NULL, &date);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_EXTERNAL_RTC
res = McuTimeDate_SetExternalRTCTimeDate(NULL, &date);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_ON_DATE_SET_EVENT
McuTimeDate_ON_DATE_SET_EVENT_NAME(Day, Month, Year); /* call user event */
#endif
if (failed) {
res = ERR_FAILED;
}
return res;
}
/*
** ===================================================================
** Method : GetDate (component GenericTimeDate)
**
** Description :
** This method returns current date from the software RTC.
** Parameters :
** NAME - DESCRIPTION
** * date - Pointer to DATEREC
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_GetDate(DATEREC *date)
{
uint8_t res;
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_SOFTWARE_RTC
res = McuTimeDate_GetSWTimeDate(NULL, date);
#elif McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_INTERNAL_RTC
res = McuTimeDate_GetInternalRTCTimeDate(NULL, date);
#elif McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_EXTERNAL_RTC
res = McuTimeDate_GetExternalRTCTimeDate(NULL, date);
#else
#error "invalid configuration!"
res = ERR_FAILED;
#endif
#if McuTimeDate_ON_DATE_GET_EVENT && McuTimeDate_CONFIG_USE_SOFTWARE_RTC
McuTimeDate_ON_DATE_GET_EVENT_NAME(&CntDay, &CntMonth, &CntYear); /* call user event */
#endif
return res;
}
/*
** ===================================================================
** Method : Init (component GenericTimeDate)
**
** Description :
** Initialization method
** Parameters : None
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_Init(void)
{
/* initialize software RTC time and date */
#if McuTimeDate_CONFIG_INIT_SOFTWARE_RTC_METHOD==McuTimeDate_INIT_SOFTWARE_RTC_FROM_DEFAULTS
/* default time/date values */
TIMEREC McuTimeDate_DefaultTime = {
McuTimeDate_CONFIG_DEFAULT_INITIAL_TIME_HOUR, /* hour */
McuTimeDate_CONFIG_DEFAULT_INITIAL_TIME_MIN, /* minute */
McuTimeDate_CONFIG_DEFAULT_INITIAL_TIME_SEC, /* second */
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
0 /* h-second */
#endif
};
DATEREC McuTimeDate_DefaultDate = {
McuTimeDate_CONFIG_DEFAULT_INITIAL_DATE_YEAR, /* year */
McuTimeDate_CONFIG_DEFAULT_INITIAL_DATE_MONTH, /* month */
McuTimeDate_CONFIG_DEFAULT_INITIAL_DATE_DAY /* day */
};
return McuTimeDate_SetSWTimeDate((TIMEREC*)&McuTimeDate_DefaultTime, (DATEREC*)&McuTimeDate_DefaultDate);
#elif McuTimeDate_CONFIG_INIT_SOFTWARE_RTC_METHOD==McuTimeDate_INIT_SOFTWARE_RTC_FROM_INTERNAL_RTC
return McuTimeDate_SyncWithInternalRTC();
#elif McuTimeDate_CONFIG_INIT_SOFTWARE_RTC_METHOD==McuTimeDate_INIT_SOFTWARE_RTC_FROM_EXTERNAL_RTC
return McuTimeDate_SyncWithExternalRTC();
#else
return ERR_FAILED; /* wrong or no init specified? */
#endif
}
/*
** ===================================================================
** Method : ParseCommand (component GenericTimeDate)
**
** Description :
** Shell Command Line parser
** Parameters :
** NAME - DESCRIPTION
** * cmd - Pointer to command line
** * handled - Pointer to variable which tells if
** the command has been handled or not
** * io - Pointer to I/O structure
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_ParseCommand(const unsigned char *cmd, bool *handled, const McuShell_StdIOType *io)
{
const uint8_t *p;
uint8_t hour, minute, second, hsec;
uint8_t month, day;
uint16_t year;
TIMEREC time;
DATEREC date;
int32_t unixSecs;
uint8_t buf[16];
if (McuUtility_strcmp((char*)cmd, McuShell_CMD_HELP)==0 || McuUtility_strcmp((char*)cmd, "McuTimeDate help")==0) {
McuShell_SendHelpStr((unsigned char*)"McuTimeDate", (const unsigned char*)"Group of McuTimeDate commands\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" help|status", (const unsigned char*)"Print help or status information\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" time [hh:mm:ss[,z]]", (const unsigned char*)"Set the current time. Prints the current time if no argument\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" date [dd.mm.yyyy]", (const unsigned char*)"Set the current date. Prints the current date if no argument\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" dateToSec <datetime>", (const unsigned char*)"Convert date/time int UNIX timestamp (seconds after 1970)\r\n", io->stdOut);
McuShell_SendHelpStr((unsigned char*)" secToDate <secs>", (const unsigned char*)"Convert UNIX timestamp to date/time\r\n", io->stdOut);
*handled = TRUE;
return ERR_OK;
} else if ((McuUtility_strcmp((char*)cmd, McuShell_CMD_STATUS)==0) || (McuUtility_strcmp((char*)cmd, "McuTimeDate status")==0)) {
*handled = TRUE;
return PrintStatus(io);
} else if (McuUtility_strncmp((char*)cmd, "McuTimeDate secToDate ", sizeof("McuTimeDate secToDate ")-1)==0) {
*handled = TRUE;
p = cmd+sizeof("McuTimeDate secToDate ")-1;
if (McuUtility_ScanDecimal32sNumber(&p, &unixSecs)==ERR_OK) {
McuTimeDate_UnixSecondsToTimeDate(unixSecs, 0, &time, &date);
buf[0] = '\0';
AddDateToBuf(buf, sizeof(buf), &date);
McuShell_SendStr(buf, io->stdOut);
McuShell_SendStr((uint8_t*)" ", io->stdOut);
buf[0] = '\0';
AddTimeToBuf(buf, sizeof(buf), &time);
McuShell_SendStr(buf, io->stdOut);
McuShell_SendStr((uint8_t*)"\r\n", io->stdOut);
} else {
McuShell_SendStr((uint8_t*)"Wrong second format.\r\n", io->stdErr);
}
} else if (McuUtility_strncmp((char*)cmd, "McuTimeDate dateToSec ", sizeof("McuTimeDate dateToSec ")-1)==0) {
*handled = TRUE;
p = cmd+sizeof("McuTimeDate dateToSec ")-1;
if (McuUtility_ScanDate(&p, &day, &month, &year)==ERR_OK) { /* format fine */
if (McuUtility_ScanTime(&p, &hour, &minute, &second, &hsec)==ERR_OK) { /* format fine */
time.Hour = hour;
time.Min = minute;
time.Sec = second;
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
time.Sec100 = 0;
#endif
date.Day = day;
date.Month = month;
date.Year = year;
unixSecs = McuTimeDate_TimeDateToUnixSeconds(&time, &date, 0);
McuShell_SendNum32s(unixSecs, io->stdOut);
McuShell_SendStr((uint8_t*)" sec\r\n", io->stdOut);
} else {
McuShell_SendStr((uint8_t*)"Wrong time format.\r\n", io->stdErr);
return ERR_FAILED;
}
} else {
McuShell_SendStr((uint8_t*)"Wrong date format.\r\n", io->stdErr);
return ERR_FAILED;
}
} else if (McuUtility_strncmp((char*)cmd, "McuTimeDate date", sizeof("McuTimeDate date")-1)==0) {
*handled = TRUE;
return DateCmd(cmd, io);
} else if (McuUtility_strncmp((char*)cmd, "McuTimeDate time", sizeof("McuTimeDate time")-1)==0) {
*handled = TRUE;
return TimeCmd(cmd, io);
}
return ERR_OK;
}
/*
** ===================================================================
** Method : DeInit (component GenericTimeDate)
**
** Description :
** Deinitializes the driver.
** Parameters : None
** Returns : Nothing
** ===================================================================
*/
void McuTimeDate_DeInit(void)
{
/* Nothing to do */
}
/*
** ===================================================================
** Method : TicksToTime (component GenericTimeDate)
**
** Description :
** Transforms ticks into time information
** Parameters :
** NAME - DESCRIPTION
** ticks -
** * time - Pointer where to store the time
** information
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_TicksToTime(uint32_t ticks, TIMEREC *time)
{
time->Hour = (uint8_t)(ticks/(3600*McuTimeDate_TICKS_PER_S)); /* number of hours */
ticks %= (3600*McuTimeDate_TICKS_PER_S); /* remainder of ticks inside hour */
time->Min = (uint8_t)(ticks/(60*McuTimeDate_TICKS_PER_S)); /* number of minutes */
ticks %= (60*McuTimeDate_TICKS_PER_S); /* remainder of ticks inside minute */
time->Sec = (uint8_t)(ticks/McuTimeDate_TICKS_PER_S); /* number of seconds */
ticks %= McuTimeDate_TICKS_PER_S;
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
time->Sec100 = (uint8_t)((ticks*(1000/McuTimeDate_TICKS_PER_S))/10); /* number of 1/100 seconds */
#endif
return ERR_OK;
}
/*
** ===================================================================
** Method : TimeToTicks (component GenericTimeDate)
**
** Description :
** Transforms time information into ticks
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer where to time information
** * ticks - Pointer to where to store the ticks
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_TimeToTicks(TIMEREC *time, uint32_t *ticks)
{
uint32_t cntr;
/* Load given time re-calculated to McuTimeDate_TICK_TIME_MS ms ticks into software tick counter */
cntr = (3600UL*McuTimeDate_TICKS_PER_S*(uint32_t)time->Hour)
+ (60UL*McuTimeDate_TICKS_PER_S*(uint32_t)time->Min)
+ (McuTimeDate_TICKS_PER_S*(uint32_t)time->Sec)
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
+ ((McuTimeDate_TICKS_PER_S/100)*(uint32_t)time->Sec100)
#endif
;
*ticks = cntr;
return ERR_OK;
}
/*
** ===================================================================
** Method : SetInternalRTCTimeDate (component GenericTimeDate)
**
** Description :
** This method sets a new actual time and date of the internal
** hardware RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to struct which contains the
** time to be set. Can be NULL if time shall
** not be set.
** * date - Pointer to struct which contains the
** date information to be set. Can be NULL if
** date shall not be set.
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SetInternalRTCTimeDate(TIMEREC *time, DATEREC *date)
{
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_LDD
LDD_RTC_TTime timeDate;
/* get current time/date */
RTC1_GetTime(RTC1_DeviceData, &timeDate); /* get information from HW RTC */
if (time!=NULL) {
timeDate.Hour = time->Hour;
timeDate.Minute = time->Min;
timeDate.Second = time->Sec;
}
if (date!=NULL) {
timeDate.Year = date->Year;
timeDate.Month = date->Month;
timeDate.Day = date->Day;
timeDate.DayOfWeek = McuTimeDate_CalculateDayOfWeek(date->Year, date->Month, date->Day);
}
return RTC1_SetTime(RTC1_DeviceData, &timeDate); /* get information from HW RTC */
#elif McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_BEAN
uint8_t res;
if (time!=NULL) {
res = RTC1_SetTime(time->Hour, time->Min, time->Sec); /* set information in HW RTC */
if (res!=ERR_OK) {
return res;
}
}
if (date!=NULL) {
res = RTC1_SetDate(date); /* set information in HW RTC */
if (res!=ERR_OK) {
return res;
}
}
return ERR_OK;
#else
(void)time;
(void)date;
return ERR_FAILED; /* no HW RTC configured */
#endif
}
/*
** ===================================================================
** Method : GetInternalRTCTimeDate (component GenericTimeDate)
**
** Description :
** This method returns current time and date from the hardware
** RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to the structure to return the
** time. Can be NULL.
** * date - Pointer to structure which returns the
** date information. Can be NULL
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_GetInternalRTCTimeDate(TIMEREC *time, DATEREC *date)
{
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_LDD
LDD_RTC_TTime timeDate;
RTC1_GetTime(RTC1_DeviceData, &timeDate); /* get information from HW RTC */
if (time!=NULL) {
time->Hour = timeDate.Hour;
time->Min = timeDate.Minute;
time->Sec = timeDate.Second;
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
time->Sec100 = 0;
#endif
}
if (date!=NULL) {
date->Year = timeDate.Year;
date->Month = timeDate.Month;
date->Day = timeDate.Day;
}
return ERR_OK;
#elif McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_BEAN
TIMEREC t;
DATEREC d;
uint8_t res;
if (Time!=NULL) {
res = RTC1_GetTime(&t); /* get information from HW RTC */
if (res!=ERR_OK) {
return res;
}
*time = t; /* struct copy */
}
if (date!=NULL) {
res = RTC1_GetDate(&d); /* get information from HW RTC */
if (res!=ERR_OK) {
return res;
}
*date = d; /* struct copy */
}
return ERR_OK;
#else
(void)time;
(void)date;
return ERR_FAILED; /* no HW RTC configured */
#endif
}
/*
** ===================================================================
** Method : CalculateDayOfWeek (component GenericTimeDate)
**
** Description :
** Returns the day of the week, Sunday starting as zero. Monday
** is 1, ...
** Parameters :
** NAME - DESCRIPTION
** Year - Years (16-bit unsigned integer)
** Month - Months (8-bit unsigned integer)
** Day - Days (8-bit unsigned integer)
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_CalculateDayOfWeek(uint16_t Year, uint8_t Month, uint8_t Day)
{
/* see http://stackoverflow.com/questions/478694/what-is-the-easiest-algorithm-to-find-the-day-of-week-of-day-zero-of-a-given-yea */
int32_t c, y, cc, yy, m, d;
uint8_t dayOfWeek;
cc = Year/100;
yy = Year-((Year/100)*100);
c = (cc/4) - 2*cc-1;
y = 5*yy/4;
m = 26*(Month+1)/10;
d = Day;
dayOfWeek = (uint8_t)(c+y+m+d)%7;
return dayOfWeek; /* 0: Sunday, 1: Monday, ... 6: Saturday */
}
/*
** ===================================================================
** Method : SyncSWtimeToInternalRTCsec (component GenericTimeDate)
**
** Description :
** This method synchronizes the software RTC with the internal
** HW RTC. Because the internal RTC only counts seconds, we
** sync on a second change.
** Parameters : None
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SyncSWtimeToInternalRTCsec(void)
{
/* This method synchronizes the software RTC with the internal HW RTC.
* Because the internal RTC only counts seconds, we sync on a second change.
*/
TIMEREC time;
uint8_t secs;
if (McuTimeDate_GetInternalRTCTimeDate(&time, NULL)!=ERR_OK) {
return ERR_FAILED;
}
secs = time.Sec; /* remember current second counter */
do {
if (McuTimeDate_GetInternalRTCTimeDate(&time, NULL)!=ERR_OK) {
return ERR_FAILED;
}
} while(secs==time.Sec);
/* internal RTC has switched to the new second: sync internal RTC with it */
if (McuTimeDate_SetSWTimeDate(&time, NULL)!=ERR_OK) { /* sync software RTC from HW RTC */
return ERR_FAILED;
}
return ERR_OK;
}
/*
** ===================================================================
** Method : SyncWithInternalRTC (component GenericTimeDate)
**
** Description :
** Synchronizes the software RTC with date and time from the
** internal hardware RTC
** Parameters : None
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SyncWithInternalRTC(void)
{
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_LDD || McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC_BEAN
TIMEREC time;
DATEREC date;
uint8_t res;
res = McuTimeDate_GetInternalRTCTimeDate(&time, &date);
if (res!=ERR_OK) {
return res;
}
/* update software time from hardware information */
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
res = McuTimeDate_SetTime(time.Hour, time.Min, time.Sec, time.Sec100);
#else
res = McuTimeDate_SetTime(time.Hour, time.Min, time.Sec, 0);
#endif
if (res!=ERR_OK) {
return res;
}
res = McuTimeDate_SetDate(date.Year, date.Month, date.Day);
if (res!=ERR_OK) {
return res;
}
/* now sync to the second of the internal RTC */
res = McuTimeDate_SyncSWtimeToInternalRTCsec();
if (res!=ERR_OK) {
return res;
}
return ERR_OK;
#else
return ERR_FAILED; /* no hardware RTC available */
#endif
}
/*
** ===================================================================
** Method : SyncWithExternalRTC (component GenericTimeDate)
**
** Description :
** Synchronizes the software RTC with date and time from the
** hardware RTC. Note that if that RTC interface requires
** interrupts, this function should be called only when
** interrupts are enabled.
** Parameters : None
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SyncWithExternalRTC(void)
{
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC
TIMEREC time;
DATEREC date;
uint8_t res;
res = McuTimeDate_GetExternalRTCTimeDate(&time, &date);
if (res!=ERR_OK) {
return res;
}
/* update software time from hardware information */
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
res = McuTimeDate_SetTime(time.Hour, time.Min, time.Sec, time.Sec100);
#else
res = McuTimeDate_SetTime(time.Hour, time.Min, time.Sec, 0);
#endif
if (res!=ERR_OK) {
return res;
}
return McuTimeDate_SetDate(date.Year, date.Month, date.Day);
#else
return ERR_FAILED; /* no external RTC available */
#endif
}
/*
** ===================================================================
** Method : SetExternalRTCTimeDate (component GenericTimeDate)
**
** Description :
** This method sets a new actual time and date of the external
** hardware RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to struct which contains the
** time to be set. Can be NULL if time shall
** not be set.
** * date - Pointer to struct which contains the
** date information to be set. Can be NULL if
** date shall not be set.
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SetExternalRTCTimeDate(TIMEREC *time, DATEREC *date)
{
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC
uint8_t res;
if (time!=NULL) {
res = McuExtRTC_SetTime(time->Hour, time->Min, time->Sec,
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
time->Sec100
#else
0
#endif
);
if (res!=ERR_OK) {
return res;
}
}
if (date!=NULL) {
res = McuExtRTC_SetDate(date->Year, date->Month, date->Day);
if (res!=ERR_OK) {
return res;
}
}
return ERR_OK;
#else
(void)time;
(void)date;
return ERR_FAILED; /* no external RTC available */
#endif
}
/*
** ===================================================================
** Method : GetExternalRTCTimeDate (component GenericTimeDate)
**
** Description :
** This method returns current time and date from the external
** hardware RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to the structure to return the
** time. Can be NULL.
** * date - Pointer to structure which returns the
** date information. Can be NULL
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_GetExternalRTCTimeDate(TIMEREC *time, DATEREC *date)
{
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC
uint8_t res;
if (time!=NULL) {
res = McuExtRTC_GetTime(time);
if (res!=ERR_OK) {
return res;
}
}
if (date!=NULL) {
res = McuExtRTC_GetDate(date);
if (res!=ERR_OK) {
return res;
}
}
return ERR_OK;
#else
(void)time;
(void)date;
return ERR_FAILED; /* no external RTC available */
#endif
}
/*
** ===================================================================
** Method : SetTimeDate (component GenericTimeDate)
**
** Description :
** This method sets a new actual time and date of the RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to struct which contains the
** time to be set. Can be NULL if time shall
** not be set.
** * date - Pointer to struct which contains the
** date information to be set. Can be NULL if
** date shall not be set.
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_SetTimeDate(TIMEREC *time, DATEREC *date)
{
uint8_t res = ERR_OK;
bool failed = FALSE;
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_SOFTWARE_RTC
res = McuTimeDate_SetSWTimeDate(time, date);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_INTERNAL_RTC
res = McuTimeDate_SetInternalRTCTimeDate(time, date);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
#if McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC && McuTimeDate_CONFIG_SET_TIME_DATE_METHOD_USES_EXTERNAL_RTC
res = McuTimeDate_SetExternalRTCTimeDate(time, date);
if (res!=ERR_OK) {
failed = TRUE;
}
#endif
if (failed) {
res = ERR_FAILED;
}
return res;
}
/*
** ===================================================================
** Method : GetTimeDate (component GenericTimeDate)
**
** Description :
** This method returns current time and date from the RTC.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to the structure to return the
** time. Can be NULL.
** * date - Pointer to structure which returns the
** date information. Can be NULL
** Returns :
** --- - Error code
** ===================================================================
*/
uint8_t McuTimeDate_GetTimeDate(TIMEREC *time, DATEREC *date)
{
uint8_t res;
#if McuTimeDate_CONFIG_USE_SOFTWARE_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_SOFTWARE_RTC
res = McuTimeDate_GetSWTimeDate(time, date);
#elif McuTimeDate_CONFIG_USE_INTERNAL_HW_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_INTERNAL_RTC
res = McuTimeDate_GetInternalRTCTimeDate(time, date);
#elif McuTimeDate_CONFIG_USE_EXTERNAL_HW_RTC && McuTimeDate_CONFIG_USE_GET_TIME_DATE_METHOD==McuTimeDate_GET_TIME_DATE_METHOD_EXTERNAL_RTC
res = McuTimeDate_GetExternalRTCTimeDate(time, date);
#else
#error "invalid configuration!"
res = ERR_FAILED;
#endif
return res;
}
/*
** ===================================================================
** Method : UnixSecondsToTimeDateCustom (component GenericTimeDate)
**
** Description :
** Transforms a given time/date into the Unix time stamp, with
** the number of seconds from a starting date
** Parameters :
** NAME - DESCRIPTION
** seconds - Unix time stamp in seconds after
** the given base year and base month
** offset_hours - Optional time zone
** offset, use 0 for no offset
** * time - Pointer to TIMEREC struct where the
** result is stored. Can be NULL.
** * date - Pointer to DATEREC struct where the
** result is stored. Can be NULL.
** baseYear - Base year from which is used as
** base to count the seconds, in YYYY format.
** Returns : Nothing
** ===================================================================
*/
void McuTimeDate_UnixSecondsToTimeDateCustom(int32_t seconds, int8_t offset_hours, TIMEREC *time, DATEREC *date, uint16_t baseYear)
{
/* Implementation based on https://www.experts-exchange.com/questions/26868405/convert-unix-time-stamp-for-8-bit-C-compiler.html */
uint8_t daysmonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int32_t secs_per_year;
int32_t secs_per_month;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hours;
uint8_t minutes;
/* adjust seconds to localtime */
seconds -= (int32_t)offset_hours*3600;
/* year */
year = baseYear;
if (McuUtility_IsLeapYear(year)) {
secs_per_year = (365+1)*24*3600;
} else {
secs_per_year = 365*24*3600;
}
while (seconds>=secs_per_year) {
seconds -= secs_per_year;
year++;
if (McuUtility_IsLeapYear(year)) {
secs_per_year = (365+1)*24*3600;
} else {
secs_per_year = 365*24*3600;
}
}
/* month update based on leap year */
if (McuUtility_IsLeapYear(year)) { /* adjust leap year month days */
daysmonth[2] = 29;
} else {
daysmonth[2] = 28;
}
/* month */
month = 1;
secs_per_month = (int32_t)daysmonth[1]*24*3600;
while (seconds >= secs_per_month) {
seconds -= secs_per_month;
month++;
secs_per_month = (int32_t)daysmonth[month]*24*3600;
}
/* day */
day = (uint8_t)(seconds/(24*3600))+1;
seconds = seconds%(24*3600);
hours = (uint8_t)(seconds/3600);
seconds = seconds%3600;
minutes = (uint8_t)(seconds/60);
seconds = seconds%60;
if (date!=NULL) {
date->Day = day;
date->Month = month;
date->Year = year;
}
if (time!=NULL) {
time->Hour = hours;
time->Min = minutes;
time->Sec = (uint8_t)seconds;
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
time->Sec100 = 0;
#endif
}
}
/*
** ===================================================================
** Method : TimeDateToUnixSecondsCustom (component GenericTimeDate)
**
** Description :
** Returns for a given time/date the corresponding UNIX time
** stamp with a custom base date.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to TIMEREC which holds the time
** to convert
** * date - Pointer to DATEREC with the date to
** convert
** offset_hours - Optional number of
** offset hours to adjust for the time zone.
** Use 0 for no adjustment.
** baseYear - Base year from which is used as
** base to count the seconds, in YYYY format
** Returns :
** --- - number of seconds after given base
** month/year
** ===================================================================
*/
int32_t McuTimeDate_TimeDateToUnixSecondsCustom(TIMEREC *time, DATEREC *date, int8_t offset_hours, uint16_t baseYear)
{
/* implementation based on https://www.experts-exchange.com/questions/26868405/convert-unix-time-stamp-for-8-bit-C-compiler.html */
uint8_t daysmonth[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int32_t nofSecs;
uint16_t year;
uint8_t month;
/* calculate the seconds for the given day */
nofSecs = (int32_t)time->Sec;
nofSecs += ((int32_t)time->Min)*60;
nofSecs += (int32_t)time->Hour*3600;
nofSecs += (int32_t)offset_hours*3600;
nofSecs += (int32_t)(date->Day-1)*24*3600;
/* month update based on leap year */
if (McuUtility_IsLeapYear(date->Year)) { /* adjust leap year month days */
daysmonth[2] = 29;
} else {
daysmonth[2] = 28;
}
/* calculate the seconds for the months in the given date */
for (month = date->Month-1; month>0; month--) {
nofSecs += (int32_t)daysmonth[month]*24*3600;
}
/* count the years back to the base year */
for (year=date->Year-1; year>=baseYear; year--) {
if (McuUtility_IsLeapYear(year)) {
nofSecs += (365+1)*24*3600;
} else {
nofSecs += 365*24*3600;
}
}
return nofSecs;
}
/*
** ===================================================================
** Method : UnixSecondsToTimeDate (component GenericTimeDate)
**
** Description :
** Transforms a given time/date into the Unix time stamp, with
** the number of seconds after 1-Jan-1970
** Parameters :
** NAME - DESCRIPTION
** seconds - Unix time stamp in seconds after
** the given base year and base month
** offset_hours - Optional time zone
** offset, use 0 for no offset
** * time - Pointer to TIMEREC struct where the
** result is stored. Can be NULL.
** * date - Pointer to DATEREC struct where the
** result is stored. Can be NULL.
** Returns : Nothing
** ===================================================================
*/
void McuTimeDate_UnixSecondsToTimeDate(int32_t seconds, int8_t offset_hours, TIMEREC *time, DATEREC *date)
{
McuTimeDate_UnixSecondsToTimeDateCustom(seconds, offset_hours, time, date, 1970);
}
/*
** ===================================================================
** Method : TimeDateToUnixSeconds (component GenericTimeDate)
**
** Description :
** Returns for a given time/date the corresponding UNIX time
** stamp, starting at 1-Jan-1970.
** Parameters :
** NAME - DESCRIPTION
** * time - Pointer to TIMEREC which holds the time
** to convert
** * date - Pointer to DATEREC with the date to
** convert
** offset_hours - Optional number of
** offset hours to adjust for the time zone.
** Use 0 for no adjustment.
** Returns :
** --- - number of seconds after given base
** month/year
** ===================================================================
*/
int32_t McuTimeDate_TimeDateToUnixSeconds(TIMEREC *time, DATEREC *date, int8_t offset_hours)
{
return McuTimeDate_TimeDateToUnixSecondsCustom(time, date, offset_hours, 1970);
}
/*
** ===================================================================
** Method : AddDateString (component GenericTimeDate)
**
** Description :
** Adds a formatted date string to a buffer
** Parameters :
** NAME - DESCRIPTION
** * buf - Pointer to zero terminated buffer where to
** append the string
** bufSize - Size of the buffer in bytes
** * date - Pointer to date information
** * format - Pointer to the format string.
** Supported formats: "dd.mm.yyyy"
** Returns :
** --- - Error code, ERR_OK for no error
** ===================================================================
*/
uint8_t McuTimeDate_AddDateString(uint8_t *buf, size_t bufSize, DATEREC *date, uint8_t *format)
{
/* currently only the following format is supported: "dd.mm.yyyy" */
(void)format; /* not supported yet */
McuUtility_strcatNum16uFormatted(buf, bufSize, date->Day, '0', 2);
McuUtility_chcat(buf, bufSize, '.');
McuUtility_strcatNum16uFormatted(buf, bufSize, date->Month, '0', 2);
McuUtility_chcat(buf, bufSize, '.');
McuUtility_strcatNum16u(buf, bufSize, (uint16_t)date->Year);
return ERR_OK;
}
/*
** ===================================================================
** Method : AddTimeString (component GenericTimeDate)
**
** Description :
** Adds a formatted time string to a buffer
** Parameters :
** NAME - DESCRIPTION
** * buf - Pointer to zero terminated buffer where to
** append the string
** bufSize - Size of the buffer in bytes
** * time - Pointer to time information
** * format - Pointer to the format string.
** Supported formats: "hh:mm.ss,cc"
** Returns :
** --- - Error code, ERR_OK for no error
** ===================================================================
*/
uint8_t McuTimeDate_AddTimeString(uint8_t *buf, size_t bufSize, TIMEREC *time, uint8_t *format)
{
/* currently only the following format is supported: hh:mm:ss,cc" */
(void)format; /* not supported yet */
McuUtility_strcatNum16sFormatted(buf, bufSize, time->Hour, '0', 2);
McuUtility_chcat(buf, bufSize, ':');
McuUtility_strcatNum16sFormatted(buf, bufSize, time->Min, '0', 2);
McuUtility_chcat(buf, bufSize, ':');
McuUtility_strcatNum16sFormatted(buf, bufSize, time->Sec, '0', 2);
McuUtility_chcat(buf, bufSize, ',');
#if McuTimeDate_HAS_SEC100_IN_TIMEREC
McuUtility_strcatNum16sFormatted(buf, bufSize, time->Sec100, '0', 2);
#else
McuUtility_strcatNum16sFormatted(buf, bufSize, 0, '0', 2);
#endif
return ERR_OK;
}
/* END McuTimeDate. */
/*!
** @}
*/