2022-03-22 17:54:09 +01:00
|
|
|
#include <ctime>
|
|
|
|
|
2021-07-13 20:22:54 +02:00
|
|
|
#include "fsfw/ipc/MutexGuard.h"
|
2022-02-02 10:29:30 +01:00
|
|
|
#include "fsfw/timemanager/Clock.h"
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-03-25 18:47:31 +01:00
|
|
|
uint16_t Clock::leapSeconds = 0;
|
|
|
|
MutexIF* Clock::timeMutex = nullptr;
|
|
|
|
bool Clock::leapSecondsSet = false;
|
|
|
|
|
2022-03-22 17:54:09 +01:00
|
|
|
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
|
2022-02-02 10:29:30 +01:00
|
|
|
uint16_t leapSeconds;
|
|
|
|
ReturnValue_t result = getLeapSeconds(&leapSeconds);
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 10:29:30 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
timeval leapSeconds_timeval = {0, 0};
|
|
|
|
leapSeconds_timeval.tv_sec = leapSeconds;
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
// initial offset between UTC and TAI
|
|
|
|
timeval UTCtoTAI1972 = {10, 0};
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
timeval TAItoTT = {32, 184000};
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
*tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT;
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2021-06-15 15:59:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) {
|
2022-08-15 20:28:16 +02:00
|
|
|
if (checkOrCreateClockMutex() != returnvalue::OK) {
|
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
MutexGuard helper(timeMutex);
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
leapSeconds = leapSeconds_;
|
2022-03-25 18:47:31 +01:00
|
|
|
leapSecondsSet = true;
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2021-06-15 15:59:20 +02:00
|
|
|
}
|
|
|
|
|
2022-03-22 17:54:09 +01:00
|
|
|
ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
|
2022-03-25 18:48:53 +01:00
|
|
|
if (not leapSecondsSet) {
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-03-25 18:47:31 +01:00
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
if (checkOrCreateClockMutex() != returnvalue::OK) {
|
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
MutexGuard helper(timeMutex);
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-02-02 10:29:30 +01:00
|
|
|
*leapSeconds_ = leapSeconds;
|
2021-06-15 15:59:20 +02:00
|
|
|
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2021-06-15 15:59:20 +02:00
|
|
|
}
|
|
|
|
|
2022-03-22 17:54:09 +01:00
|
|
|
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
|
|
|
|
struct tm* timeInfo;
|
2022-03-25 13:32:29 +01:00
|
|
|
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s
|
|
|
|
// in the Windows CRT is incompatible with the C standard but this should not be an issue for
|
|
|
|
// this implementation
|
2022-03-25 18:47:31 +01:00
|
|
|
ReturnValue_t result = checkOrCreateClockMutex();
|
2022-08-15 20:28:16 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-03-25 18:47:31 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
// gmtime writes its output in a global buffer which is not Thread Safe
|
|
|
|
// Therefore we have to use a Mutex here
|
2022-09-27 21:46:11 +02:00
|
|
|
MutexGuard helper(timeMutex);
|
|
|
|
#ifdef PLATFORM_WIN
|
|
|
|
time_t time;
|
|
|
|
time = from->tv_sec;
|
|
|
|
timeInfo = gmtime(&time);
|
|
|
|
#else
|
2022-03-22 17:54:09 +01:00
|
|
|
timeInfo = gmtime(&from->tv_sec);
|
2022-09-27 21:46:11 +02:00
|
|
|
#endif
|
2022-03-22 17:54:09 +01:00
|
|
|
to->year = timeInfo->tm_year + 1900;
|
|
|
|
to->month = timeInfo->tm_mon + 1;
|
|
|
|
to->day = timeInfo->tm_mday;
|
|
|
|
to->hour = timeInfo->tm_hour;
|
|
|
|
to->minute = timeInfo->tm_min;
|
|
|
|
to->second = timeInfo->tm_sec;
|
|
|
|
to->usecond = from->tv_usec;
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2022-03-22 17:54:09 +01:00
|
|
|
}
|
|
|
|
|
2021-06-15 16:12:25 +02:00
|
|
|
ReturnValue_t Clock::checkOrCreateClockMutex() {
|
2022-02-02 10:29:30 +01:00
|
|
|
if (timeMutex == nullptr) {
|
2022-03-22 17:54:09 +01:00
|
|
|
MutexFactory* mutexFactory = MutexFactory::instance();
|
2022-02-02 10:29:30 +01:00
|
|
|
if (mutexFactory == nullptr) {
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
timeMutex = mutexFactory->createMutex();
|
|
|
|
if (timeMutex == nullptr) {
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::FAILED;
|
2022-02-02 10:29:30 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 20:28:16 +02:00
|
|
|
return returnvalue::OK;
|
2021-06-15 15:59:20 +02:00
|
|
|
}
|