Merge remote-tracking branch 'origin/develop' into mueller/master
This commit is contained in:
commit
26ff40ae0c
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit 43917d98c025b446aa0d79d2166b1f031fb288ae
|
Subproject commit a11d7455dfaf2e736f73f6c4dda1f8c06b9f1234
|
@ -4,6 +4,8 @@
|
|||||||
#include "fsfw/datapool/PoolReadGuard.h"
|
#include "fsfw/datapool/PoolReadGuard.h"
|
||||||
#include "fsfw/timemanager/Clock.h"
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
|
#include "mission/utility/compileTime.h"
|
||||||
|
|
||||||
#if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1
|
#if FSFW_DEV_HYPERION_GPS_CREATE_NMEA_CSV == 1
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -79,11 +81,7 @@ ReturnValue_t GPSHyperionLinuxController::initializeLocalDataPool(
|
|||||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||||
bool enablePeriodicHk = false;
|
poolManager.subscribeForPeriodicPacket(gpsSet.getSid(), false, 30.0, false);
|
||||||
#if OBSW_ENABLE_PERIODIC_HK == 1
|
|
||||||
enablePeriodicHk = true;
|
|
||||||
#endif
|
|
||||||
poolManager.subscribeForPeriodicPacket(gpsSet.getSid(), enablePeriodicHk, 2.0, false);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,9 +183,10 @@ void GPSHyperionLinuxController::readGpsDataFromGpsd() {
|
|||||||
}
|
}
|
||||||
// If the received time does not change anymore for whatever reason, do not set it here
|
// 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
|
// to avoid stale times. Also, don't do it too often often to avoid jumping times
|
||||||
if (timeIsConstantCounter < 3 and timeUpdateCd.hasTimedOut()) {
|
if (timeIsConstantCounter < 20 and timeUpdateCd.hasTimedOut()) {
|
||||||
// Update the system time here for now. NTP seems to be unable to do so for whatever reason
|
// Update the system time here for now. NTP seems to be unable to do so for whatever reason.
|
||||||
settimeofday(&time, nullptr);
|
// Further tests have shown that the time seems to be set by NTPD after sme time..
|
||||||
|
// Clock::setClock(&time);
|
||||||
timeUpdateCd.resetTimer();
|
timeUpdateCd.resetTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +271,7 @@ ReturnValue_t ACUHandler::initializeLocalDataPool(localpool::DataPool &localData
|
|||||||
localDataPoolMap.emplace(pool::ACU_WDT_CNT_GND, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(pool::ACU_WDT_CNT_GND, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(pool::ACU_WDT_GND_LEFT, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(pool::ACU_WDT_GND_LEFT, new PoolEntry<uint32_t>({0}));
|
||||||
|
|
||||||
|
poolManager.subscribeForPeriodicPacket(acuHkTableDataset.getSid(), false, 30.0, false);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,10 +270,7 @@ ReturnValue_t BpxBatteryHandler::initializeLocalDataPool(localpool::DataPool& lo
|
|||||||
localDataPoolMap.emplace(BpxBattery::BATTERY_HEATER_MODE, &battheatMode);
|
localDataPoolMap.emplace(BpxBattery::BATTERY_HEATER_MODE, &battheatMode);
|
||||||
localDataPoolMap.emplace(BpxBattery::BATTHEAT_LOW_LIMIT, &battheatLow);
|
localDataPoolMap.emplace(BpxBattery::BATTHEAT_LOW_LIMIT, &battheatLow);
|
||||||
localDataPoolMap.emplace(BpxBattery::BATTHEAT_HIGH_LIMIT, &battheatHigh);
|
localDataPoolMap.emplace(BpxBattery::BATTHEAT_HIGH_LIMIT, &battheatHigh);
|
||||||
|
poolManager.subscribeForPeriodicPacket(hkSet.getSid(), false, 30.0, false);
|
||||||
#if OBSW_ENABLE_PERIODIC_HK == 1
|
|
||||||
poolManager.subscribeForPeriodicPacket(hkSet.getSid(), true, 1.0, false);
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@ ReturnValue_t GPSHyperionHandler::initializeLocalDataPool(localpool::DataPool &l
|
|||||||
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>());
|
localDataPoolMap.emplace(GpsHyperion::UNIX_SECONDS, new PoolEntry<uint32_t>());
|
||||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||||
poolManager.subscribeForPeriodicPacket(gpsSet.getSid(), true, 2.0, false);
|
poolManager.subscribeForPeriodicPacket(gpsSet.getSid(), false, 30.0, false);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +363,7 @@ ReturnValue_t GyroADIS1650XHandler::initializeLocalDataPool(localpool::DataPool
|
|||||||
localDataPoolMap.emplace(ADIS1650X::FILTER_SETTINGS, new PoolEntry<uint8_t>());
|
localDataPoolMap.emplace(ADIS1650X::FILTER_SETTINGS, new PoolEntry<uint8_t>());
|
||||||
localDataPoolMap.emplace(ADIS1650X::MSC_CTRL_REGISTER, new PoolEntry<uint16_t>());
|
localDataPoolMap.emplace(ADIS1650X::MSC_CTRL_REGISTER, new PoolEntry<uint16_t>());
|
||||||
localDataPoolMap.emplace(ADIS1650X::DEC_RATE_REGISTER, new PoolEntry<uint16_t>());
|
localDataPoolMap.emplace(ADIS1650X::DEC_RATE_REGISTER, new PoolEntry<uint16_t>());
|
||||||
|
poolManager.subscribeForPeriodicPacket(primaryDataset.getSid(), false, 5.0, true);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,6 +599,8 @@ ReturnValue_t IMTQHandler::initializeLocalDataPool(localpool::DataPool& localDat
|
|||||||
localDataPoolMap.emplace(IMTQ::FINA_NEG_Z_COIL_Y_TEMPERATURE, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(IMTQ::FINA_NEG_Z_COIL_Y_TEMPERATURE, new PoolEntry<uint16_t>({0}));
|
||||||
localDataPoolMap.emplace(IMTQ::FINA_NEG_Z_COIL_Z_TEMPERATURE, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(IMTQ::FINA_NEG_Z_COIL_Z_TEMPERATURE, new PoolEntry<uint16_t>({0}));
|
||||||
|
|
||||||
|
poolManager.subscribeForPeriodicPacket(engHkDataset.getSid(), false, 10.0, true);
|
||||||
|
poolManager.subscribeForPeriodicPacket(calMtmMeasurementSet.getSid(), false, 10.0, true);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,8 +515,7 @@ ReturnValue_t Max31865PT1000Handler::initializeLocalDataPool(localpool::DataPool
|
|||||||
localDataPoolMap.emplace(Max31865Definitions::PoolIds::TEMPERATURE_C,
|
localDataPoolMap.emplace(Max31865Definitions::PoolIds::TEMPERATURE_C,
|
||||||
new PoolEntry<float>({0}, 1, true));
|
new PoolEntry<float>({0}, 1, true));
|
||||||
localDataPoolMap.emplace(Max31865Definitions::PoolIds::FAULT_BYTE, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(Max31865Definitions::PoolIds::FAULT_BYTE, new PoolEntry<uint8_t>({0}));
|
||||||
// poolManager.subscribeForPeriodicPacket(sensorDatasetSid,
|
poolManager.subscribeForPeriodicPacket(sensorDataset.getSid(), false, 30.0, false);
|
||||||
// false, 4.0, false);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +426,7 @@ ReturnValue_t PDU1Handler::initializeLocalDataPool(localpool::DataPool &localDat
|
|||||||
localDataPoolMap.emplace(P60System::pool::PDU1_WDT_CAN_LEFT, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(P60System::pool::PDU1_WDT_CAN_LEFT, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(P60System::pool::PDU1_WDT_CSP_LEFT1, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(P60System::pool::PDU1_WDT_CSP_LEFT1, new PoolEntry<uint8_t>({0}));
|
||||||
localDataPoolMap.emplace(P60System::pool::PDU1_WDT_CSP_LEFT2, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(P60System::pool::PDU1_WDT_CSP_LEFT2, new PoolEntry<uint8_t>({0}));
|
||||||
poolManager.subscribeForPeriodicPacket(pdu1HkTableDataset.getSid(), false, 0.4, true);
|
poolManager.subscribeForPeriodicPacket(pdu1HkTableDataset.getSid(), false, 10.0, false);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,9 +354,7 @@ ReturnValue_t PDU2Handler::initializeLocalDataPool(localpool::DataPool &localDat
|
|||||||
localDataPoolMap.emplace(pool::PDU2_WDT_CAN_LEFT, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(pool::PDU2_WDT_CAN_LEFT, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(pool::PDU2_WDT_CSP_LEFT1, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(pool::PDU2_WDT_CSP_LEFT1, new PoolEntry<uint8_t>({0}));
|
||||||
localDataPoolMap.emplace(pool::PDU2_WDT_CSP_LEFT2, new PoolEntry<uint8_t>({0}));
|
localDataPoolMap.emplace(pool::PDU2_WDT_CSP_LEFT2, new PoolEntry<uint8_t>({0}));
|
||||||
#if OBSW_ENABLE_PERIODIC_HK == 1
|
poolManager.subscribeForPeriodicPacket(pdu2HkTableDataset.getSid(), false, 10.0, false);
|
||||||
poolManager.subscribeForPeriodicPacket(pdu2HkTableDataset.getSid(), false, 0.4, true);
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ void PayloadPcduHandler::doShutDown() {
|
|||||||
auto opCode = pwrStateMachine.fsm();
|
auto opCode = pwrStateMachine.fsm();
|
||||||
if (opCode == power::OpCodes::TO_OFF_DONE or opCode == power::OpCodes::TIMEOUT_OCCURED) {
|
if (opCode == power::OpCodes::TO_OFF_DONE or opCode == power::OpCodes::TIMEOUT_OCCURED) {
|
||||||
pwrStateMachine.reset();
|
pwrStateMachine.reset();
|
||||||
|
state = States::PL_PCDU_OFF;
|
||||||
// No need to set mode _MODE_POWER_DOWN, power switching was already handled
|
// No need to set mode _MODE_POWER_DOWN, power switching was already handled
|
||||||
setMode(MODE_OFF);
|
setMode(MODE_OFF);
|
||||||
}
|
}
|
||||||
@ -66,7 +67,8 @@ void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
|||||||
|
|
||||||
ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_t subModeFrom) {
|
ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||||
using namespace plpcdu;
|
using namespace plpcdu;
|
||||||
if (submode == NormalSubmodes::SOLID_STATE_RELAYS_ADC_ON) {
|
bool doFinish = true;
|
||||||
|
if (((submode >> SOLID_STATE_RELAYS_ADC_ON) & 0b1) == 1) {
|
||||||
if (state == States::PL_PCDU_OFF) {
|
if (state == States::PL_PCDU_OFF) {
|
||||||
sif::error << "PayloadPcduHandler::stateMachineToNormal: Unexpected state PL_PCDU_OFF"
|
sif::error << "PayloadPcduHandler::stateMachineToNormal: Unexpected state PL_PCDU_OFF"
|
||||||
<< "detected" << std::endl;
|
<< "detected" << std::endl;
|
||||||
@ -82,22 +84,24 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
|
|||||||
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_VBAT1);
|
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_VBAT1);
|
||||||
state = States::ON_TRANS_SSR;
|
state = States::ON_TRANS_SSR;
|
||||||
transitionOk = true;
|
transitionOk = true;
|
||||||
|
doFinish = false;
|
||||||
}
|
}
|
||||||
if (state == States::ON_TRANS_SSR) {
|
if (state == States::ON_TRANS_SSR) {
|
||||||
// If necessary, check whether a certain amount of time has elapsed
|
// If necessary, check whether a certain amount of time has elapsed
|
||||||
if (transitionOk) {
|
if (transitionOk) {
|
||||||
transitionOk = false;
|
transitionOk = false;
|
||||||
state = States::ON_TRANS_ADC_CLOSE_ZERO;
|
state = States::ON_TRANS_ADC_CLOSE_ZERO;
|
||||||
|
|
||||||
adcCountdown.setTimeout(50);
|
adcCountdown.setTimeout(50);
|
||||||
adcCountdown.resetTimer();
|
adcCountdown.resetTimer();
|
||||||
adcState = AdcStates::BOOT_DELAY;
|
adcState = AdcStates::BOOT_DELAY;
|
||||||
|
doFinish = false;
|
||||||
// If the values are not close to zero, we should not allow transition
|
// If the values are not close to zero, we should not allow transition
|
||||||
monMode = MonitoringMode::CLOSE_TO_ZERO;
|
monMode = MonitoringMode::CLOSE_TO_ZERO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state == States::ON_TRANS_ADC_CLOSE_ZERO) {
|
if (state == States::ON_TRANS_ADC_CLOSE_ZERO) {
|
||||||
if (adcState == AdcStates::BOOT_DELAY) {
|
if (adcState == AdcStates::BOOT_DELAY) {
|
||||||
|
doFinish = false;
|
||||||
if (adcCountdown.hasTimedOut()) {
|
if (adcCountdown.hasTimedOut()) {
|
||||||
adcState = AdcStates::SEND_SETUP;
|
adcState = AdcStates::SEND_SETUP;
|
||||||
adcCmdExecuted = false;
|
adcCmdExecuted = false;
|
||||||
@ -106,68 +110,38 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
|
|||||||
if (adcState == AdcStates::SEND_SETUP) {
|
if (adcState == AdcStates::SEND_SETUP) {
|
||||||
if (adcCmdExecuted) {
|
if (adcCmdExecuted) {
|
||||||
adcState = AdcStates::NORMAL;
|
adcState = AdcStates::NORMAL;
|
||||||
|
doFinish = true;
|
||||||
adcCountdown.setTimeout(100);
|
adcCountdown.setTimeout(100);
|
||||||
adcCountdown.resetTimer();
|
adcCountdown.resetTimer();
|
||||||
adcCmdExecuted = false;
|
adcCmdExecuted = false;
|
||||||
setMode(MODE_NORMAL, submode);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (submode == NormalSubmodes::DRO_ON) {
|
auto switchHandler = [&](NormalSubmodeBits bit, gpioId_t id, std::string info) {
|
||||||
|
if (((diffMask >> bit) & 1) == 1) {
|
||||||
|
if (((submode >> bit) & 1) == 1) {
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
sif::info << "Enabling PL PCDU DRO module" << std::endl;
|
sif::info << "Enabling PL PCDU " << info << " module" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
// Switch on DRO and start monitoring for negative voltages
|
// Switch on DRO and start monitoring for negative voltages
|
||||||
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_DRO);
|
updateSwitchGpio(id, gpio::Levels::HIGH);
|
||||||
adcCountdown.setTimeout(100);
|
} else {
|
||||||
adcCountdown.resetTimer();
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
setMode(MODE_NORMAL, submode);
|
sif::info << "Disabling PL PCDU " << info << " module" << std::endl;
|
||||||
}
|
#endif
|
||||||
|
updateSwitchGpio(id, gpio::Levels::LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (submode == NormalSubmodes::X8_ON) {
|
switchHandler(DRO_ON, gpioIds::PLPCDU_ENB_DRO, "DRO");
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
switchHandler(X8_ON, gpioIds::PLPCDU_ENB_X8, "X8");
|
||||||
sif::info << "Enabling PL PCDU X8 module" << std::endl;
|
switchHandler(TX_ON, gpioIds::PLPCDU_ENB_TX, "TX");
|
||||||
#endif
|
switchHandler(MPA_ON, gpioIds::PLPCDU_ENB_MPA, "MPA");
|
||||||
// Switch on DRO and start monitoring for negative voltages
|
switchHandler(HPA_ON, gpioIds::PLPCDU_ENB_HPA, "HPA");
|
||||||
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_X8);
|
if (doFinish) {
|
||||||
adcCountdown.setTimeout(100);
|
|
||||||
adcCountdown.resetTimer();
|
|
||||||
setMode(MODE_NORMAL, submode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (submode == NormalSubmodes::TX_ON) {
|
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
|
||||||
sif::info << "Enabling PL PCDU TX module" << std::endl;
|
|
||||||
#endif
|
|
||||||
// Switch on DRO and start monitoring for negative voltages
|
|
||||||
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_TX);
|
|
||||||
adcCountdown.setTimeout(100);
|
|
||||||
adcCountdown.resetTimer();
|
|
||||||
setMode(MODE_NORMAL, submode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (submode == NormalSubmodes::MPA_ON) {
|
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
|
||||||
sif::info << "Enabling PL PCDU MPA module" << std::endl;
|
|
||||||
#endif
|
|
||||||
// Switch on DRO and start monitoring for negative voltages
|
|
||||||
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_MPA);
|
|
||||||
adcCountdown.setTimeout(100);
|
|
||||||
adcCountdown.resetTimer();
|
|
||||||
setMode(MODE_NORMAL, submode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (submode == NormalSubmodes::HPA_ON) {
|
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
|
||||||
sif::info << "Enabling PL PCDU HPA module" << std::endl;
|
|
||||||
#endif
|
|
||||||
// Switch on DRO and start monitoring for negative voltages
|
|
||||||
gpioIF->pullHigh(gpioIds::PLPCDU_ENB_HPA);
|
|
||||||
adcCountdown.setTimeout(100);
|
|
||||||
adcCountdown.resetTimer();
|
|
||||||
setMode(MODE_NORMAL, submode);
|
setMode(MODE_NORMAL, submode);
|
||||||
}
|
}
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
@ -201,6 +175,16 @@ ReturnValue_t PayloadPcduHandler::buildTransitionDeviceCommand(DeviceCommandId_t
|
|||||||
return NOTHING_TO_SEND;
|
return NOTHING_TO_SEND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PayloadPcduHandler::updateSwitchGpio(gpioId_t id, gpio::Levels level) {
|
||||||
|
if (level == gpio::Levels::HIGH) {
|
||||||
|
gpioIF->pullHigh(id);
|
||||||
|
} else {
|
||||||
|
gpioIF->pullLow(id);
|
||||||
|
}
|
||||||
|
adcCountdown.setTimeout(100);
|
||||||
|
adcCountdown.resetTimer();
|
||||||
|
}
|
||||||
|
|
||||||
void PayloadPcduHandler::fillCommandAndReplyMap() {
|
void PayloadPcduHandler::fillCommandAndReplyMap() {
|
||||||
insertInCommandAndReplyMap(plpcdu::READ_CMD, 2, &adcSet);
|
insertInCommandAndReplyMap(plpcdu::READ_CMD, 2, &adcSet);
|
||||||
insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1, &adcSet);
|
insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1, &adcSet);
|
||||||
@ -309,7 +293,7 @@ ReturnValue_t PayloadPcduHandler::initializeLocalDataPool(localpool::DataPool& l
|
|||||||
localDataPoolMap.emplace(plpcdu::PlPcduPoolIds::CHANNEL_VEC, &channelValues);
|
localDataPoolMap.emplace(plpcdu::PlPcduPoolIds::CHANNEL_VEC, &channelValues);
|
||||||
localDataPoolMap.emplace(plpcdu::PlPcduPoolIds::PROCESSED_VEC, &processedValues);
|
localDataPoolMap.emplace(plpcdu::PlPcduPoolIds::PROCESSED_VEC, &processedValues);
|
||||||
localDataPoolMap.emplace(plpcdu::PlPcduPoolIds::TEMP, &tempC);
|
localDataPoolMap.emplace(plpcdu::PlPcduPoolIds::TEMP, &tempC);
|
||||||
poolManager.subscribeForPeriodicPacket(adcSet.getSid(), false, 0.1, true);
|
poolManager.subscribeForPeriodicPacket(adcSet.getSid(), false, 5.0, true);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,25 +532,33 @@ bool PayloadPcduHandler::checkCurrent(float val, float upperBound, Event event)
|
|||||||
ReturnValue_t PayloadPcduHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
ReturnValue_t PayloadPcduHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||||
using namespace plpcdu;
|
using namespace plpcdu;
|
||||||
if (mode == MODE_NORMAL) {
|
if (mode == MODE_NORMAL) {
|
||||||
|
diffMask = submode ^ this->submode;
|
||||||
// Also deals with the case where the mode is MODE_ON, submode should be 0 here
|
// Also deals with the case where the mode is MODE_ON, submode should be 0 here
|
||||||
if (submode == NormalSubmodes::SOLID_STATE_RELAYS_ADC_ON and
|
if ((((submode >> SOLID_STATE_RELAYS_ADC_ON) & 0b1) == SOLID_STATE_RELAYS_ADC_ON) and
|
||||||
(this->mode == MODE_NORMAL and this->submode != NormalSubmodes::ALL_OFF)) {
|
(this->mode == MODE_NORMAL and this->submode != ALL_OFF_SUBMODE)) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
if ((submode == NormalSubmodes::DRO_ON and
|
if (((((submode >> DRO_ON) & 1) == 1) and
|
||||||
this->submode != NormalSubmodes::SOLID_STATE_RELAYS_ADC_ON)) {
|
((this->submode & 0b1) != (1 << SOLID_STATE_RELAYS_ADC_ON)))) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
if ((submode == NormalSubmodes::X8_ON and this->submode != NormalSubmodes::DRO_ON)) {
|
if ((((submode >> X8_ON) & 1) == 1) and
|
||||||
|
((this->submode & 0b11) != ((1 << SOLID_STATE_RELAYS_ADC_ON) | (1 << DRO_ON)))) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
if ((submode == NormalSubmodes::TX_ON and this->submode != NormalSubmodes::X8_ON)) {
|
if (((((submode >> TX_ON) & 1) == 1) and
|
||||||
|
((this->submode & 0b111) !=
|
||||||
|
((1 << X8_ON) | (1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
if ((submode == NormalSubmodes::MPA_ON and this->submode != NormalSubmodes::TX_ON)) {
|
if ((((submode >> MPA_ON) & 1) == 1 and
|
||||||
|
((this->submode & 0b1111) !=
|
||||||
|
((1 << TX_ON) | (1 << X8_ON) | (1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
if ((submode == NormalSubmodes::HPA_ON and this->submode != NormalSubmodes::MPA_ON)) {
|
if ((((submode >> HPA_ON) & 1) == 1 and
|
||||||
|
((this->submode & 0b11111) != ((1 << MPA_ON) | (1 << TX_ON) | (1 << X8_ON) |
|
||||||
|
(1 << DRO_ON) | (1 << SOLID_STATE_RELAYS_ADC_ON))))) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
@ -134,6 +134,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
|||||||
SdCardMountedIF* sdcMan;
|
SdCardMountedIF* sdcMan;
|
||||||
plpcdu::PlPcduParameter params;
|
plpcdu::PlPcduParameter params;
|
||||||
bool quickTransitionAlreadyCalled = true;
|
bool quickTransitionAlreadyCalled = true;
|
||||||
|
uint8_t diffMask = 0;
|
||||||
|
|
||||||
PoolEntry<uint16_t> channelValues = PoolEntry<uint16_t>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
PoolEntry<uint16_t> channelValues = PoolEntry<uint16_t>({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||||
PoolEntry<float> processedValues =
|
PoolEntry<float> processedValues =
|
||||||
@ -141,6 +142,8 @@ class PayloadPcduHandler : public DeviceHandlerBase {
|
|||||||
PoolEntry<float> tempC = PoolEntry<float>({0.0});
|
PoolEntry<float> tempC = PoolEntry<float>({0.0});
|
||||||
DualLanePowerStateMachine pwrStateMachine;
|
DualLanePowerStateMachine pwrStateMachine;
|
||||||
|
|
||||||
|
void updateSwitchGpio(gpioId_t id, gpio::Levels level);
|
||||||
|
|
||||||
void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
|
void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
|
||||||
void doStartUp() override;
|
void doStartUp() override;
|
||||||
void doShutDown() override;
|
void doShutDown() override;
|
||||||
|
@ -203,6 +203,7 @@ ReturnValue_t RadiationSensorHandler::initializeLocalDataPool(localpool::DataPoo
|
|||||||
localDataPoolMap.emplace(RAD_SENSOR::AIN5, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(RAD_SENSOR::AIN5, new PoolEntry<uint16_t>({0}));
|
||||||
localDataPoolMap.emplace(RAD_SENSOR::AIN6, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(RAD_SENSOR::AIN6, new PoolEntry<uint16_t>({0}));
|
||||||
localDataPoolMap.emplace(RAD_SENSOR::AIN7, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(RAD_SENSOR::AIN7, new PoolEntry<uint16_t>({0}));
|
||||||
|
poolManager.subscribeForPeriodicPacket(dataset.getSid(), false, 20.0, false);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,9 @@ ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataP
|
|||||||
localDataPoolMap.emplace(RwDefinitions::SPI_BYTES_READ, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(RwDefinitions::SPI_BYTES_READ, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(RwDefinitions::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(RwDefinitions::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(RwDefinitions::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(RwDefinitions::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||||
|
poolManager.subscribeForPeriodicPacket(temperatureSet.getSid(), false, 30.0, false);
|
||||||
|
poolManager.subscribeForPeriodicPacket(statusSet.getSid(), false, 5.0, true);
|
||||||
|
poolManager.subscribeForPeriodicPacket(tmDataset.getSid(), false, 30.0, false);
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +200,7 @@ ReturnValue_t SusHandler::initializeLocalDataPool(localpool::DataPool &localData
|
|||||||
LocalDataPoolManager &poolManager) {
|
LocalDataPoolManager &poolManager) {
|
||||||
localDataPoolMap.emplace(SUS::TEMPERATURE_C, &tempC);
|
localDataPoolMap.emplace(SUS::TEMPERATURE_C, &tempC);
|
||||||
localDataPoolMap.emplace(SUS::CHANNEL_VEC, &channelVec);
|
localDataPoolMap.emplace(SUS::CHANNEL_VEC, &channelVec);
|
||||||
|
poolManager.subscribeForPeriodicPacket(dataset.getSid(), false, 5.0, true);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,6 +627,9 @@ ReturnValue_t SyrlinksHkHandler::initializeLocalDataPool(localpool::DataPool& lo
|
|||||||
localDataPoolMap.emplace(syrlinks::TEMP_BASEBAND_BOARD, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(syrlinks::TEMP_BASEBAND_BOARD, new PoolEntry<uint16_t>({0}));
|
||||||
localDataPoolMap.emplace(syrlinks::TEMP_POWER_AMPLIFIER, new PoolEntry<uint16_t>({0}));
|
localDataPoolMap.emplace(syrlinks::TEMP_POWER_AMPLIFIER, new PoolEntry<uint16_t>({0}));
|
||||||
|
|
||||||
|
poolManager.subscribeForPeriodicPacket(txDataset.getSid(), false, 5.0, true);
|
||||||
|
poolManager.subscribeForPeriodicPacket(rxDataset.getSid(), false, 5.0, true);
|
||||||
|
poolManager.subscribeForPeriodicPacket(temperatureSet.getSid(), false, 10.0, false);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +119,7 @@ uint32_t Tmp1075Handler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
|
|||||||
|
|
||||||
ReturnValue_t Tmp1075Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
ReturnValue_t Tmp1075Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||||
LocalDataPoolManager &poolManager) {
|
LocalDataPoolManager &poolManager) {
|
||||||
localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075_1, new PoolEntry<float>({0.0}));
|
localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry<float>({0.0}));
|
||||||
|
poolManager.subscribeForPeriodicPacket(dataset.getSid(), false, 30.0, false);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ static const uint32_t TMP1075_DATA_SET_ID = GET_TEMP;
|
|||||||
|
|
||||||
static const uint8_t MAX_REPLY_LENGTH = GET_TEMP_REPLY_SIZE;
|
static const uint8_t MAX_REPLY_LENGTH = GET_TEMP_REPLY_SIZE;
|
||||||
|
|
||||||
enum Tmp1075PoolIds : lp_id_t { TEMPERATURE_C_TMP1075_1, TEMPERATURE_C_TMP1075_2 };
|
enum Tmp1075PoolIds : lp_id_t { TEMPERATURE_C_TMP1075 };
|
||||||
|
|
||||||
class Tmp1075Dataset : public StaticLocalDataSet<sizeof(float)> {
|
class Tmp1075Dataset : public StaticLocalDataSet<sizeof(float)> {
|
||||||
public:
|
public:
|
||||||
@ -29,7 +29,7 @@ class Tmp1075Dataset : public StaticLocalDataSet<sizeof(float)> {
|
|||||||
|
|
||||||
Tmp1075Dataset(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TMP1075_DATA_SET_ID)) {}
|
Tmp1075Dataset(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TMP1075_DATA_SET_ID)) {}
|
||||||
|
|
||||||
lp_var_t<float> temperatureCelcius = lp_var_t<float>(sid.objectId, TEMPERATURE_C_TMP1075_1, this);
|
lp_var_t<float> temperatureCelcius = lp_var_t<float>(sid.objectId, TEMPERATURE_C_TMP1075, this);
|
||||||
};
|
};
|
||||||
} // namespace TMP1075
|
} // namespace TMP1075
|
||||||
|
|
||||||
|
@ -91,16 +91,17 @@ static constexpr DeviceCommandId_t SETUP_CMD = 1;
|
|||||||
static constexpr DeviceCommandId_t READ_TEMP_EXT = 2;
|
static constexpr DeviceCommandId_t READ_TEMP_EXT = 2;
|
||||||
static constexpr DeviceCommandId_t READ_WITH_TEMP_EXT = 3;
|
static constexpr DeviceCommandId_t READ_WITH_TEMP_EXT = 3;
|
||||||
|
|
||||||
enum NormalSubmodes {
|
enum NormalSubmodeBits {
|
||||||
ALL_OFF = 0,
|
SOLID_STATE_RELAYS_ADC_ON = 0,
|
||||||
SOLID_STATE_RELAYS_ADC_ON = 1,
|
DRO_ON = 1,
|
||||||
DRO_ON = 2,
|
X8_ON = 2,
|
||||||
X8_ON = 3,
|
TX_ON = 3,
|
||||||
TX_ON = 4,
|
MPA_ON = 4,
|
||||||
MPA_ON = 5,
|
HPA_ON = 5
|
||||||
HPA_ON = 6
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr Submode_t ALL_OFF_SUBMODE = 0;
|
||||||
|
|
||||||
// 12 ADC values * 2 + trailing zero
|
// 12 ADC values * 2 + trailing zero
|
||||||
static constexpr size_t ADC_REPLY_SIZE = 25;
|
static constexpr size_t ADC_REPLY_SIZE = 25;
|
||||||
// Conversion byte + 24 * zero
|
// Conversion byte + 24 * zero
|
||||||
|
97
mission/utility/compileTime.h
Normal file
97
mission/utility/compileTime.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Created: 29.03.2018
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* and
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMPILE_TIME_H_
|
||||||
|
#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)
|
||||||
|
|
||||||
|
// 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')
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// Days in February
|
||||||
|
#define _UNIX_TIMESTAMP_FDAY(year) \
|
||||||
|
(((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) \
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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 \
|
||||||
|
)
|
||||||
|
|
||||||
|
// the UNIX timestamp
|
||||||
|
#define UNIX_TIMESTAMP (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__))
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user