#include #include #include "boost_timegm.h" #include "fsfw/ipc/MutexGuard.h" #include "fsfw/timemanager/Clock.h" uint16_t Clock::leapSeconds = 0; MutexIF* Clock::timeMutex = nullptr; bool Clock::leapSecondsSet = false; ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { uint16_t leapSeconds; ReturnValue_t result = getLeapSeconds(&leapSeconds); if (result != returnvalue::OK) { return result; } timeval leapSeconds_timeval = {0, 0}; leapSeconds_timeval.tv_sec = leapSeconds; // initial offset between UTC and TAI timeval UTCtoTAI1972 = {10, 0}; timeval TAItoTT = {32, 184000}; *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; return returnvalue::OK; } ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if (checkOrCreateClockMutex() != returnvalue::OK) { return returnvalue::FAILED; } MutexGuard helper(timeMutex); leapSeconds = leapSeconds_; leapSecondsSet = true; return returnvalue::OK; } ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if (not leapSecondsSet) { return returnvalue::FAILED; } if (checkOrCreateClockMutex() != returnvalue::OK) { return returnvalue::FAILED; } MutexGuard helper(timeMutex); *leapSeconds_ = leapSeconds; return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) { struct tm time_tm; // WINDOWS does not provide gmtime_r, but gmtime_s #ifdef _MSC_VER time_t seconds = from->tv_sec; errno_t result = gmtime_s(&time_tm, &seconds); if (result != 0) { return returnvalue::FAILED; } #else void* result = gmtime_r(&from->tv_sec, &time_tm); if (result == nullptr) { return returnvalue::FAILED; } #endif to->year = time_tm.tm_year + 1900; to->month = time_tm.tm_mon + 1; to->day = time_tm.tm_mday; to->hour = time_tm.tm_hour; to->minute = time_tm.tm_min; to->second = time_tm.tm_sec; to->usecond = from->tv_usec; return returnvalue::OK; } ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) { struct tm time_tm = {}; time_tm.tm_year = from->year - 1900; time_tm.tm_mon = from->month - 1; time_tm.tm_mday = from->day; time_tm.tm_hour = from->hour; time_tm.tm_min = from->minute; time_tm.tm_sec = from->second; time_tm.tm_isdst = 0; time_t seconds = internal_timegm(&time_tm); to->tv_sec = seconds; to->tv_usec = from->usecond; return returnvalue::OK; } ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.; return returnvalue::OK; } ReturnValue_t Clock::checkOrCreateClockMutex() { if (timeMutex == nullptr) { MutexFactory* mutexFactory = MutexFactory::instance(); if (mutexFactory == nullptr) { return returnvalue::FAILED; } timeMutex = mutexFactory->createMutex(); if (timeMutex == nullptr) { return returnvalue::FAILED; } } return returnvalue::OK; } ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { timeval time_timeval; ReturnValue_t result = getClock_timeval(&time_timeval); if (result != returnvalue::OK) { return result; } return convertTimevalToTimeOfDay(&time_timeval, time); } ReturnValue_t Clock::getClock_usecs(uint64_t* time) { timeval timeVal{}; ReturnValue_t result = getClock_timeval(&timeVal); if (result != returnvalue::OK) { return result; } *time = static_cast(timeVal.tv_sec) * 1e6 + timeVal.tv_usec; return returnvalue::OK; } ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { timeval timeTimeval{}; ReturnValue_t result = convertTimeOfDayToTimeval(time, &timeTimeval); if (result != returnvalue::OK) { return result; } return setClock(&timeTimeval); } uint32_t Clock::getUptime_ms() { timeval uptime = getUptime(); // TODO verify that overflow is correct return uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3; }