Index: RTC.c =================================================================== diff -u -r3015d5852f61ed7031b5563b115000a5b52a28a6 -r08a11b37a4877e676b08fa7b12aa46c064c3478b --- RTC.c (.../RTC.c) (revision 3015d5852f61ed7031b5563b115000a5b52a28a6) +++ RTC.c (.../RTC.c) (revision 08a11b37a4877e676b08fa7b12aa46c064c3478b) @@ -14,14 +14,16 @@ * @date (original) 11-Jan-2020 * ***************************************************************************/ -#include // For epoch conversion functions mktime and gmtime - -#include "Timers.h" -#include "RTC.h" #include "mibspi.h" -#include "SystemCommMessages.h" #include "OperationModes.h" +#include "RTC.h" +#include "SystemCommMessages.h" +#include "Timers.h" +#ifdef USE_LIBRARY_TIME_FUNCTIONS +#include // For epoch conversion functions mktime and gmtime +#endif + /** * @addtogroup RTC * @{ @@ -113,11 +115,23 @@ #define MAX_ALLOWED_RTC_RAM_ADDRESS 512U ///< Max allowed RTC RAM legal address (512) #define TEN 10U ///< Ten #define YEAR_2000 2000U ///< Year 2000 +#ifndef USE_LIBRARY_TIME_FUNCTIONS +#define EPOCH_YEAR 1970U ///< Reference year to calculate epoch (1970) +#else #define EPOCH_YEAR 1900U ///< Reference year to calculate epoch (1900) #define YEAR_1900_TO_1970_SECONDS_DIFF 2208988800U ///< Difference in seconds from 1/1/1900 to 1/1/1970 (2208988800) -/// Six hour offset that is apparently needed before converting epoch to date/time structure using gmtime(). +/// Six hour offset is needed because TI library works in CST. #define OFFSET_6_HRS (6 * MIN_PER_HOUR * SEC_PER_MIN) +#endif +#define SECS_IN_HOUR 3600 +#define MONTHS_IN_YEAR 12 +#define LEAP_YEAR_MONTH 1 +#define SECONDS_IN_NORMAL_YEAR ( SECONDS_IN_A_DAY * 365 ) +#define SECONDS_IN_LEAP_YEAR ( SECONDS_IN_A_DAY * 366 ) +static const U32 SECONDS_IN_4_YEARS = SECONDS_IN_NORMAL_YEAR * 3 + SECONDS_IN_LEAP_YEAR; +static const U32 SECONDS_IN_2_YEARS = SECONDS_IN_NORMAL_YEAR * 2; + #ifdef _VECTORCAST_ #define LOCAL_TO_GTM_TIME_CONVERSION 8U ///< Local time to GTM conversion for VectorCAST #endif @@ -202,14 +216,21 @@ static U16 prepRAMBuffer[ RTC_RAM_PREP_BUFFER_LENGTH ]; ///< Buffer to send prep read/write commands to RTC RAM. static U16 RAMBuffer[ MIBSPI_MAX_BUFFER_LENGTH ]; ///< Buffer to read RTC RAM data. +/// Array of days in each month. +static U32 daysInMonth[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + // ********** Private function prototypes ********* static BOOL serviceRTC( U16* bufferTransmit, U16* bufferReceive, U16 bufferLength ); static BOOL isRTCFunctional( void ); static U08 convertBCD2Decimal( U08 bcd ); static U08 convertDecimal2BCD( U08 decimal ); +static U32 convertDateTime2Epoch( RTC_TIMESTAMP_T dateTime ); +static BOOL convertEpoch2DateTime( U32 epoch ); +#ifdef USE_LIBRARY_TIME_FUNCTIONS static U32 convertTime2Epoch( void ); static void convertEpoch2Time( U32 epoch ); +#endif static void updateReadTimestampStruct( void ); static BOOL setMibSPIBufferLength( U16 length ); static void prepBufferForReadCommand( U08 length ); // Puts the read command @@ -228,8 +249,6 @@ static RTC_EXEC_STATE_T handleExecReadFromRAMState( void ); static RTC_EXEC_STATE_T handleExecWriteState( void ); -// ********** Public functions ********** - /*********************************************************************//** * @brief * The initRTC initializes the RTC module. @@ -313,7 +332,11 @@ { BOOL result; +#ifndef USE_LIBRARY_TIME_FUNCTIONS + result = convertEpoch2DateTime( epoch ); +#else convertEpoch2Time( epoch ); +#endif result = setRTCTimestamp( RTCNewTimestampStruct.seconds, RTCNewTimestampStruct.minutes, RTCNewTimestampStruct.hours, @@ -810,6 +833,93 @@ /*********************************************************************//** * @brief + * The convertTime2Epoch converts a given date/time record into an epoch + * (seconds from Jan 1 1970). + * @details Inputs: none + * @details Outputs: none + * @param dateTime UTC Date & Time structure to convert to epoch + * @return epoch time (seconds since Jan 1, 1970) + *************************************************************************/ +static U32 convertDateTime2Epoch( RTC_TIMESTAMP_T dateTime ) +{ + U32 epoch; + U32 secs = dateTime.seconds; + U32 mins = dateTime.minutes; + U32 hrs = dateTime.hours; + U32 days = dateTime.days; + U32 mos = dateTime.months - 1; // convert months from 1..12 to 0..11 + U32 yrs = dateTime.years - EPOCH_YEAR; + U32 lyrs = ( yrs / 4 ) + ( yrs % 4 > 2 ? 1 : 0 ); + BOOL leap = ( dateTime.years % 4 == 0 ? TRUE : FALSE ); + U32 i, dayCnt; + + daysInMonth[ LEAP_YEAR_MONTH ] = ( TRUE == leap ? 29 : 28 ); + dayCnt = 0; + for ( i = 0; i <= dateTime.months; i++ ) + { + dayCnt += daysInMonth[ i ]; + } + + epoch = secs + ( mins * SEC_PER_MIN ) + ( hrs * SECS_IN_HOUR ); + epoch += ( days * SECONDS_IN_A_DAY ); + epoch += ( dayCnt * SECONDS_IN_A_DAY ); + epoch += ( lyrs * SECONDS_IN_LEAP_YEAR ); + epoch += ( ( yrs - lyrs ) * SECONDS_IN_NORMAL_YEAR ); + + return epoch; +} + +/*********************************************************************//** + * @brief + * The convertEpoch2DateTime converts a given epoch to a date/time record (UTC). + * @details Inputs: none + * @details Outputs: none + * @param epoch Number of seconds since Jan 1, 1970 + * @return populated date/time record + *************************************************************************/ +static BOOL convertEpoch2DateTime( U32 epoch ) +{ + BOOL result; + RTC_TIMESTAMP_T dtTime; + U32 i, dayCnt; + U32 fourYears = epoch / SECONDS_IN_4_YEARS; + U32 twoYrEpoch = epoch - ( fourYears * SECONDS_IN_4_YEARS ); + U32 twoYears = twoYrEpoch / SECONDS_IN_2_YEARS; + U32 oneYrEpoch = twoYrEpoch - ( twoYears * SECONDS_IN_2_YEARS ); + U32 oneYears = ( twoYears > 0 ? oneYrEpoch / SECONDS_IN_LEAP_YEAR : oneYrEpoch / SECONDS_IN_NORMAL_YEAR ); + U32 wholeYears = ( fourYears * 4 ) + ( twoYears * 2 ) + oneYears; + BOOL leapYear = ( twoYears > 0 && 0 == oneYears ? TRUE : FALSE ); + U32 days = oneYrEpoch / SECONDS_IN_A_DAY; + U32 oneDayEpoch= oneYrEpoch % SECONDS_IN_A_DAY; + U32 hours = oneDayEpoch / SECS_IN_HOUR; + U32 oneHrEpoch = oneDayEpoch - ( hours * SECS_IN_HOUR ); + U32 mins = oneHrEpoch / SEC_PER_MIN; + U32 secs = oneHrEpoch - ( mins * SEC_PER_MIN ); + + dtTime.years = EPOCH_YEAR + wholeYears; + dtTime.months = 0; + dayCnt = 0; + daysInMonth[ LEAP_YEAR_MONTH ] = ( TRUE == leapYear ? 29 : 28 ); + for ( i = 0; i < MONTHS_IN_YEAR; i++ ) + { + if ( days >= dayCnt ) + { + dtTime.months = i + 1; + } + dayCnt += daysInMonth[ i ]; + } + dtTime.days = days; + dtTime.hours = hours; + dtTime.minutes = mins; + dtTime.seconds = secs; + result = setRTCTimestamp( dtTime.seconds, dtTime.minutes, dtTime.hours, dtTime.days, dtTime.months, dtTime.years ); + + return result; +} + +#ifdef USE_LIBRARY_TIME_FUNCTIONS +/*********************************************************************//** + * @brief * The convertTime2Epoch converts the time into epoch (seconds from Jan 1 1970). * @details Inputs: RTCTimestampStruct * @details Outputs: none @@ -842,9 +952,12 @@ epochTime = mktime(&t); epochTime = epochTime - YEAR_1900_TO_1970_SECONDS_DIFF; #endif + return (U32)epochTime; } +#endif +#ifdef USE_LIBRARY_TIME_FUNCTIONS /*********************************************************************//** * @brief * The convertEpoch2Time converts a given epoch date/time to a date/time @@ -870,6 +983,7 @@ RTCNewTimestampStruct.minutes = ptm->tm_min; RTCNewTimestampStruct.seconds = ptm->tm_sec; } +#endif /*********************************************************************//** * @brief @@ -1206,7 +1320,11 @@ if ( isRTCFunctional() ) { updateReadTimestampStruct(); +#ifndef USE_LIBRARY_TIME_FUNCTIONS + lastEpochTime = convertDateTime2Epoch( RTCTimestampStruct ); +#else lastEpochTime = convertTime2Epoch(); +#endif timeCounter = 1; broadcastRTCEpoch( lastEpochTime ); }