/* ################################################################### ** 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 /* 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 ", (const unsigned char*)"Convert date/time int UNIX timestamp (seconds after 1970)\r\n", io->stdOut); McuShell_SendHelpStr((unsigned char*)" secToDate ", (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. */ /*! ** @} */