From 4a6840f0987bc895d8e1fb808b763b83bf2fd40e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 8 Apr 2022 11:22:16 +0200 Subject: [PATCH] bugfixes and improvements - Tests finished --- bsp_q7s/core/CoreController.cpp | 87 ++++++++------ bsp_q7s/core/CoreController.h | 6 +- generators/events/translateEvents.cpp | 2 +- generators/objects/translateObjects.cpp | 2 +- linux/devices/GPSHyperionLinuxController.cpp | 19 ++- linux/devices/GPSHyperionLinuxController.h | 4 +- linux/fsfwconfig/events/translateEvents.cpp | 2 +- linux/fsfwconfig/objects/translateObjects.cpp | 2 +- linux/utility/utility.cpp | 13 ++ linux/utility/utility.h | 4 +- .../devicedefinitions/GPSDefinitions.h | 8 +- mission/utility/compileTime.h | 113 ++++++++---------- 12 files changed, 144 insertions(+), 118 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index c39caa12..ef6e4fa0 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1,6 +1,9 @@ #include "CoreController.h" #include +#include + +#include #include "OBSWConfig.h" #include "OBSWVersion.h" @@ -8,7 +11,6 @@ #include "fsfw/timemanager/Stopwatch.h" #include "fsfw/version.h" #include "watchdogConf.h" -#include #if OBSW_USE_TMTC_TCP_BRIDGE == 0 #include "fsfw/osal/common/UdpTmTcBridge.h" #else @@ -22,6 +24,7 @@ #include "bsp_q7s/memory/SdCardManager.h" #include "bsp_q7s/memory/scratchApi.h" #include "bsp_q7s/xadc/Xadc.h" +#include "linux/utility/utility.h" xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; @@ -51,6 +54,7 @@ CoreController::CoreController(object_id_t objectId) } catch (const std::filesystem::filesystem_error &e) { sif::error << "CoreController::CoreController: Failed with exception " << e.what() << std::endl; } + eventQueue = QueueFactory::instance()->createMessageQueue(5, EventMessage::MAX_MESSAGE_SIZE); } ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { @@ -62,10 +66,10 @@ void CoreController::performControlOperation() { for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == RETURN_OK; result = eventQueue->receiveMessage(&event)) { switch (event.getEvent()) { - case(GpsHyperion::GPS_FIX_CHANGE): { - gpsFix = static_cast(event.getParameter2()); - break; - } + case (GpsHyperion::GPS_FIX_CHANGE): { + gpsFix = static_cast(event.getParameter2()); + break; + } } } performWatchdogControlOperation(); @@ -90,8 +94,10 @@ LocalPoolDataSetBase *CoreController::getDataSetHandle(sid_t sid) { } ReturnValue_t CoreController::initialize() { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - + ReturnValue_t result = ExtendedControllerBase::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: Base init failed" << std::endl; + } result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::initialize: Setting up alloc failure " @@ -102,18 +108,23 @@ ReturnValue_t CoreController::initialize() { sdStateMachine(); triggerEvent(REBOOT_SW, CURRENT_CHIP, CURRENT_COPY); - EventManagerIF* eventManager = ObjectManager::instance()->get( - objects::EVENT_MANAGER); + EventManagerIF *eventManager = + ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (eventManager == nullptr or eventQueue == nullptr) { + sif::warning << "CoreController::initialize: No valid event manager found or " + "queue invalid" + << std::endl; + } result = eventManager->registerListener(eventQueue->getId()); - if(result != HasReturnvaluesIF::RETURN_OK) { + if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::initialize: Registering as event listener failed" << std::endl; } - result = eventManager->subscribeToEvent(this->getCommandQueue(), - event::getEventId(GpsHyperion::GPS_FIX_CHANGE)); - if(result != HasReturnvaluesIF::RETURN_OK) { + result = eventManager->subscribeToEvent(eventQueue->getId(), + event::getEventId(GpsHyperion::GPS_FIX_CHANGE)); + if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Subscribing for GPS GPS_FIX_CHANGE event failed" << std::endl; } - return ExtendedControllerBase::initialize(); + return RETURN_OK; } ReturnValue_t CoreController::initializeAfterTaskCreation() { @@ -661,8 +672,7 @@ ReturnValue_t CoreController::initVersionFile() { fsfw::FSFW_VERSION.getVersion(versionString, sizeof(versionString)); std::string fullFsfwVersionString = "FSFW: v" + std::string(versionString); std::string systemString = "System: " + unameLine; - std::string mountPrefix = SdCardManager::instance()->getCurrentMountPrefix(); - std::string versionFilePath = mountPrefix + VERSION_FILE; + std::string versionFilePath = currMntPrefix + VERSION_FILE; std::fstream versionFile; if (not std::filesystem::exists(versionFilePath)) { @@ -1220,15 +1230,17 @@ void CoreController::performWatchdogControlOperation() { } void CoreController::performMountedSdCardOperations() { + currMntPrefix = sdcMan->getCurrentMountPrefix(); if (doPerformMountedSdCardOps) { bool sdCardMounted = false; sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); if (sdCardMounted) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + "/" + CONF_FOLDER; + std::string path = currMntPrefix + "/" + CONF_FOLDER; if (not std::filesystem::exists(path)) { std::filesystem::create_directory(path); } initVersionFile(); + initClockFromTimeFile(); performRebootFileHandling(false); doPerformMountedSdCardOps = false; } @@ -1238,7 +1250,7 @@ void CoreController::performMountedSdCardOperations() { void CoreController::performRebootFileHandling(bool recreateFile) { using namespace std; - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = currMntPrefix + REBOOT_FILE; if (not std::filesystem::exists(path) or recreateFile) { #if OBSW_VERBOSE_LEVEL >= 1 sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; @@ -1617,7 +1629,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = currMntPrefix + REBOOT_FILE; // Disable the reboot file mechanism parseRebootFile(path, rebootFile); if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) { @@ -1644,7 +1656,7 @@ void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { } void CoreController::rewriteRebootFile(RebootFile file) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = currMntPrefix + REBOOT_FILE; std::ofstream rebootFile(path); if (rebootFile.is_open()) { // Initiate reboot file first. Reboot handling will be on on initialization @@ -1681,15 +1693,15 @@ void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::C } ReturnValue_t CoreController::timeFileHandler() { - if(gpsFix == GpsHyperion::FixMode::FIX_2D or gpsFix == GpsHyperion::FixMode::FIX_3D) { + if (gpsFix == GpsHyperion::FixMode::FIX_2D or gpsFix == GpsHyperion::FixMode::FIX_3D) { // It is assumed that the system time is set from the GPS time timeval currentTime = {}; ReturnValue_t result = Clock::getClock_timeval(¤tTime); - if(result != HasReturnvaluesIF::RETURN_OK) { + if (result != HasReturnvaluesIF::RETURN_OK) { return result; } - std::ofstream timeFile(TIME_FILE); - timeFile << "UNIX SECONDS: " << currentTime.tv_sec; + std::ofstream timeFile(currMntPrefix + TIME_FILE); + timeFile << "UNIX SECONDS: " << currentTime.tv_sec << std::endl; } return RETURN_OK; } @@ -1697,30 +1709,30 @@ ReturnValue_t CoreController::timeFileHandler() { ReturnValue_t CoreController::initClockFromTimeFile() { using namespace GpsHyperion; using namespace std; - if ((gpsFix == FixMode::UNKNOWN or gpsFix == FixMode::NOT_SEEN) and - std::filesystem::exists(TIME_FILE)) { - - ifstream timeFile(TIME_FILE); + std::string fileName = currMntPrefix + TIME_FILE; + if (std::filesystem::exists(fileName) and + ((gpsFix == FixMode::UNKNOWN or gpsFix == FixMode::NOT_SEEN) or + not utility::timeSanityCheck())) { + ifstream timeFile(fileName); string nextWord; getline(timeFile, nextWord); istringstream iss(nextWord); iss >> nextWord; - if(iss.bad() or nextWord != "UNIX") { + if (iss.bad() or nextWord != "UNIX") { return RETURN_FAILED; } iss >> nextWord; - if(iss.bad() or nextWord != "SECONDS:") { + if (iss.bad() or nextWord != "SECONDS:") { return RETURN_FAILED; } iss >> nextWord; timeval currentTime = {}; - char* checkPtr; + char *checkPtr; currentTime.tv_sec = strtol(nextWord.c_str(), &checkPtr, 10); - if(iss.bad() or *checkPtr) { + if (iss.bad() or *checkPtr) { return RETURN_FAILED; } - Clock::setClock(¤tTime); - return RETURN_OK; + return Clock::setClock(¤tTime); } return RETURN_OK; } @@ -1759,8 +1771,7 @@ void CoreController::readHkData() { } } -bool CoreController::isNumber(const std::string& s) -{ - return !s.empty() && std::find_if(s.begin(), - s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end(); +bool CoreController::isNumber(const std::string &s) { + return !s.empty() && std::find_if(s.begin(), s.end(), + [](unsigned char c) { return !std::isdigit(c); }) == s.end(); } diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 05ec6315..b5e4e511 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -7,10 +7,10 @@ #include #include "CoreDefinitions.h" -#include "mission/devices/devicedefinitions/GPSDefinitions.h" #include "bsp_q7s/memory/SdCardManager.h" #include "events/subsystemIdRanges.h" #include "fsfw/controller/ExtendedControllerBase.h" +#include "mission/devices/devicedefinitions/GPSDefinitions.h" class Timer; class SdCardManager; @@ -59,8 +59,7 @@ class CoreController : public ExtendedControllerBase { "/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME); const std::string REBOOT_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME); - const std::string TIME_FILE = - "/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME); + const std::string TIME_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME); static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; @@ -179,6 +178,7 @@ class CoreController : public ExtendedControllerBase { sd::SdState commandedState = sd::SdState::OFF; } sdInfo; RebootFile rebootFile = {}; + std::string currMntPrefix; bool doPerformMountedSdCardOps = true; /** diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 7112fa87..aeebd2cb 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 183 translations. * @details - * Generated on: 2022-04-07 17:27:42 + * Generated on: 2022-04-08 11:21:58 */ #include "translateEvents.h" diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 78113fd9..bed40c70 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 117 translations. - * Generated on: 2022-04-07 17:27:42 + * Generated on: 2022-04-08 11:21:58 */ #include "translateObjects.h" diff --git a/linux/devices/GPSHyperionLinuxController.cpp b/linux/devices/GPSHyperionLinuxController.cpp index 2b49e0d0..22f3affd 100644 --- a/linux/devices/GPSHyperionLinuxController.cpp +++ b/linux/devices/GPSHyperionLinuxController.cpp @@ -3,7 +3,7 @@ #include "OBSWConfig.h" #include "fsfw/datapool/PoolReadGuard.h" #include "fsfw/timemanager/Clock.h" - +#include "linux/utility/utility.h" #include "mission/utility/compileTime.h" #if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1 @@ -127,9 +127,14 @@ void GPSHyperionLinuxController::readGpsDataFromGpsd() { return; } + bool validFix = false; + static_cast(validFix); // 0: Not seen, 1: No fix, 2: 2D-Fix, 3: 3D-Fix int newFixMode = gps->fix.mode; - if(gpsSet.fixMode.value != newFixMode) { + if (newFixMode == 2 or newFixMode == 3) { + validFix = true; + } + if (gpsSet.fixMode.value != newFixMode) { triggerEvent(GpsHyperion::GPS_FIX_CHANGE, gpsSet.fixMode.value, newFixMode); } gpsSet.fixMode.value = newFixMode; @@ -185,11 +190,19 @@ void GPSHyperionLinuxController::readGpsDataFromGpsd() { } else { timeIsConstantCounter = 0; } + if (timeInit) { + if (not utility::timeSanityCheck()) { + sif::info << "Setting init clock in gps ctrl" << std::endl; + // For some reason, the clock needs to be somewhat correct for NTP to work. Really dumb.. + Clock::setClock(&time); + } + timeInit = false; + } // If the received time does not change anymore for whatever reason, do not set it here // to avoid stale times. Also, don't do it too often often to avoid jumping times if (timeIsConstantCounter < 20 and timeUpdateCd.hasTimedOut()) { // Update the system time here for now. NTP seems to be unable to do so for whatever reason. - // Further tests have shown that the time seems to be set by NTPD after sme time.. + // Further tests have shown that the time seems to be set by NTPD after some time.. // Clock::setClock(&time); timeUpdateCd.resetTimer(); } diff --git a/linux/devices/GPSHyperionLinuxController.h b/linux/devices/GPSHyperionLinuxController.h index ac8a4735..dedd782c 100644 --- a/linux/devices/GPSHyperionLinuxController.h +++ b/linux/devices/GPSHyperionLinuxController.h @@ -1,8 +1,8 @@ #ifndef MISSION_DEVICES_GPSHYPERIONHANDLER_H_ #define MISSION_DEVICES_GPSHYPERIONHANDLER_H_ -#include "fsfw/FSFW.h" #include "commonSubsystemIds.h" +#include "fsfw/FSFW.h" #include "fsfw/controller/ExtendedControllerBase.h" #include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "mission/devices/devicedefinitions/GPSDefinitions.h" @@ -24,7 +24,6 @@ class GPSHyperionLinuxController : public ExtendedControllerBase { public: static constexpr uint32_t MAX_SECONDS_TO_REACH_FIX = 60 * 60 * 5; - GPSHyperionLinuxController(object_id_t objectId, object_id_t parentId, bool debugHyperionGps = false); virtual ~GPSHyperionLinuxController(); @@ -52,6 +51,7 @@ class GPSHyperionLinuxController : public ExtendedControllerBase { GpsPrimaryDataset gpsSet; Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000); bool modeCommanded = true; + bool timeInit = true; gpsmm myGpsmm; bool debugHyperionGps = false; uint32_t timeIsConstantCounter = 0; diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 7112fa87..aeebd2cb 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 183 translations. * @details - * Generated on: 2022-04-07 17:27:42 + * Generated on: 2022-04-08 11:21:58 */ #include "translateEvents.h" diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 78113fd9..bed40c70 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 117 translations. - * Generated on: 2022-04-07 17:27:42 + * Generated on: 2022-04-08 11:21:58 */ #include "translateObjects.h" diff --git a/linux/utility/utility.cpp b/linux/utility/utility.cpp index cd0d47ef..fb58109b 100644 --- a/linux/utility/utility.cpp +++ b/linux/utility/utility.cpp @@ -1,3 +1,4 @@ + #include "utility.h" #include @@ -5,6 +6,7 @@ #include "FSFWConfig.h" #include "OBSWConfig.h" #include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/timemanager/Clock.h" void utility::handleSystemError(int retcode, std::string function) { #if OBSW_VERBOSE_LEVEL >= 1 @@ -12,3 +14,14 @@ void utility::handleSystemError(int retcode, std::string function) { << strerror(retcode) << std::endl; #endif } + +bool utility::timeSanityCheck() { + timeval currentTime = {}; + Clock::getUptime(¤tTime); + Clock::TimeOfDay_t currTimeOfDay = {}; + Clock::convertTimevalToTimeOfDay(¤tTime, &currTimeOfDay); + if (currTimeOfDay.year == 2000) { + return false; + } + return true; +} diff --git a/linux/utility/utility.h b/linux/utility/utility.h index 8f7df04f..b4c4fe8b 100644 --- a/linux/utility/utility.h +++ b/linux/utility/utility.h @@ -9,6 +9,8 @@ namespace utility { void handleSystemError(int retcode, std::string function); -} +bool timeSanityCheck(); + +} // namespace utility #endif /* LINUX_UTILITY_UTILITY_H_ */ diff --git a/mission/devices/devicedefinitions/GPSDefinitions.h b/mission/devices/devicedefinitions/GPSDefinitions.h index bf3fbe52..f953da22 100644 --- a/mission/devices/devicedefinitions/GPSDefinitions.h +++ b/mission/devices/devicedefinitions/GPSDefinitions.h @@ -6,13 +6,7 @@ namespace GpsHyperion { -enum class FixMode: uint8_t { - NOT_SEEN = 0, - NO_FIX = 1, - FIX_2D = 2, - FIX_3D = 3, - UNKNOWN = 4 -}; +enum class FixMode : uint8_t { NOT_SEEN = 0, NO_FIX = 1, FIX_2D = 2, FIX_3D = 3, UNKNOWN = 4 }; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::GPS_HANDLER; //! [EXPORT] : [COMMENT] Fix has changed. P1: Old fix. P2: New fix diff --git a/mission/utility/compileTime.h b/mission/utility/compileTime.h index c55673f6..0e367248 100644 --- a/mission/utility/compileTime.h +++ b/mission/utility/compileTime.h @@ -5,14 +5,17 @@ * Authors: * * Assembled from the code released on Stackoverflow by: - * Dennis (instructable.com/member/nqtronix) | https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string + * Dennis (instructable.com/member/nqtronix) | + * https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string * and - * Alexis Wilke | https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date + * Alexis Wilke | + * https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date * * Assembled by Jean Rabault * - * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro. - * This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps. + * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of + * compilation from macros using the compiler defined __TIME__ macro. This should include Gregorian + * calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps. * * Careful: __TIME__ is the local time of the computer, NOT the UTC time in general! * @@ -22,76 +25,66 @@ #define COMPILE_TIME_H_ // Some definitions for calculation -#define SEC_PER_MIN 60UL -#define SEC_PER_HOUR 3600UL -#define SEC_PER_DAY 86400UL -#define SEC_PER_YEAR (SEC_PER_DAY*365) +#define SEC_PER_MIN 60UL +#define SEC_PER_HOUR 3600UL +#define SEC_PER_DAY 86400UL +#define SEC_PER_YEAR (SEC_PER_DAY * 365) // extracts 1..4 characters from a string and interprets it as a decimal value -#define CONV_STR2DEC_1(str, i) (str[i]>'0'?str[i]-'0':0) -#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0') -#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0') -#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0') +#define CONV_STR2DEC_1(str, i) (str[i] > '0' ? str[i] - '0' : 0) +#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i) * 10 + str[i + 1] - '0') +#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i) * 10 + str[i + 2] - '0') +#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i) * 10 + str[i + 3] - '0') // Custom "glue logic" to convert the month name to a usable number -#define GET_MONTH(str, i) (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 : \ - str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 : \ - str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 : \ - str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 : \ - str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 : \ - str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 : \ - str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 : \ - str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 : \ - str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 : \ - str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 : \ - str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 : \ - str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0) +#define GET_MONTH(str, i) \ + (str[i] == 'J' && str[i + 1] == 'a' && str[i + 2] == 'n' ? 1 \ + : str[i] == 'F' && str[i + 1] == 'e' && str[i + 2] == 'b' ? 2 \ + : str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'r' ? 3 \ + : str[i] == 'A' && str[i + 1] == 'p' && str[i + 2] == 'r' ? 4 \ + : str[i] == 'M' && str[i + 1] == 'a' && str[i + 2] == 'y' ? 5 \ + : str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'n' ? 6 \ + : str[i] == 'J' && str[i + 1] == 'u' && str[i + 2] == 'l' ? 7 \ + : str[i] == 'A' && str[i + 1] == 'u' && str[i + 2] == 'g' ? 8 \ + : str[i] == 'S' && str[i + 1] == 'e' && str[i + 2] == 'p' ? 9 \ + : str[i] == 'O' && str[i + 1] == 'c' && str[i + 2] == 't' ? 10 \ + : str[i] == 'N' && str[i + 1] == 'o' && str[i + 2] == 'v' ? 11 \ + : str[i] == 'D' && str[i + 1] == 'e' && str[i + 2] == 'c' ? 12 \ + : 0) // extract the information from the time string given by __TIME__ and __DATE__ -#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6) -#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3) -#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0) -#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4) -#define __TIME_MONTH__ GET_MONTH(__DATE__, 0) -#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7) +#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6) +#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3) +#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0) +#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4) +#define __TIME_MONTH__ GET_MONTH(__DATE__, 0) +#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7) // Days in February #define _UNIX_TIMESTAMP_FDAY(year) \ - (((year) % 400) == 0UL ? 29UL : \ - (((year) % 100) == 0UL ? 28UL : \ - (((year) % 4) == 0UL ? 29UL : \ - 28UL))) + (((year) % 400) == 0UL ? 29UL \ + : (((year) % 100) == 0UL ? 28UL : (((year) % 4) == 0UL ? 29UL : 28UL))) // Days in the year -#define _UNIX_TIMESTAMP_YDAY(year, month, day) \ - ( \ - /* January */ day \ - /* February */ + (month >= 2 ? 31UL : 0UL) \ - /* March */ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \ - /* April */ + (month >= 4 ? 31UL : 0UL) \ - /* May */ + (month >= 5 ? 30UL : 0UL) \ - /* June */ + (month >= 6 ? 31UL : 0UL) \ - /* July */ + (month >= 7 ? 30UL : 0UL) \ - /* August */ + (month >= 8 ? 31UL : 0UL) \ - /* September */+ (month >= 9 ? 31UL : 0UL) \ - /* October */ + (month >= 10 ? 30UL : 0UL) \ - /* November */ + (month >= 11 ? 31UL : 0UL) \ - /* December */ + (month >= 12 ? 30UL : 0UL) \ - ) +#define _UNIX_TIMESTAMP_YDAY(year, month, day) \ + (/* January */ day /* February */ + (month >= 2 ? 31UL : 0UL) /* March */ + \ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) /* April */ + \ + (month >= 4 ? 31UL : 0UL) /* May */ + (month >= 5 ? 30UL : 0UL) /* June */ + \ + (month >= 6 ? 31UL : 0UL) /* July */ + (month >= 7 ? 30UL : 0UL) /* August */ + \ + (month >= 8 ? 31UL : 0UL) /* September */ + (month >= 9 ? 31UL : 0UL) /* October */ + \ + (month >= 10 ? 30UL : 0UL) /* November */ + (month >= 11 ? 31UL : 0UL) /* December */ + \ + (month >= 12 ? 30UL : 0UL)) // get the UNIX timestamp from a digits representation -#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \ - ( /* time */ second \ - + minute * SEC_PER_MIN \ - + hour * SEC_PER_HOUR \ - + /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY \ - + /* year */ (year - 1970UL) * SEC_PER_YEAR \ - + ((year - 1969UL) / 4UL) * SEC_PER_DAY \ - - ((year - 1901UL) / 100UL) * SEC_PER_DAY \ - + ((year - 1601UL) / 400UL) * SEC_PER_DAY \ - ) +#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \ + (/* time */ second + minute * SEC_PER_MIN + hour * SEC_PER_HOUR + \ + /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY + \ + /* year */ (year - 1970UL) * SEC_PER_YEAR + ((year - 1969UL) / 4UL) * SEC_PER_DAY - \ + ((year - 1901UL) / 100UL) * SEC_PER_DAY + ((year - 1601UL) / 400UL) * SEC_PER_DAY) // the UNIX timestamp -#define UNIX_TIMESTAMP (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__)) +#define UNIX_TIMESTAMP \ + (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, \ + __TIME_MINUTES__, __TIME_SECONDS__)) #endif