diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 847cce5f..1fb9efed 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -783,15 +783,10 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, AxiPtmeConfig* axiPtmeConfig = new AxiPtmeConfig(objects::AXI_PTME_CONFIG, q7s::UIO_PTME, q7s::uiomapids::PTME_CONFIG); PtmeConfig* ptmeConfig = new PtmeConfig(objects::PTME_CONFIG, axiPtmeConfig); -#if OBSW_ENABLE_SYRLINKS_TRANSMIT_TIMEOUT == 1 - // Set to high value when not sending via syrlinks - static const uint32_t TRANSMITTER_TIMEOUT = 86400000; // 1 day -#else - static const uint32_t TRANSMITTER_TIMEOUT = 900000; // 15 minutes -#endif + *ipCoreHandler = new CcsdsIpCoreHandler( objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, ptmeConfig, - gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA, TRANSMITTER_TIMEOUT); + gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA); VirtualChannel* vc = nullptr; vc = new VirtualChannel(ccsds::VC0, config::VC0_QUEUE_SIZE, objects::CCSDS_HANDLER); (*ipCoreHandler)->addVirtualChannel(ccsds::VC0, vc); diff --git a/mission/system/objects/ComSubsystem.cpp b/mission/system/objects/ComSubsystem.cpp index 426e9c6c..5c98dfd8 100644 --- a/mission/system/objects/ComSubsystem.cpp +++ b/mission/system/objects/ComSubsystem.cpp @@ -1,13 +1,32 @@ +#include + #include "ComSubsystem.h" +#include #include +#include +#include +#include +#include -#include "mission/config/comCfg.h" +extern std::pair> COM_SEQUENCE_RX_ONLY; +extern std::pair> COM_SEQUENCE_RX_AND_TX_DEFAULT_RATE; +extern std::pair> COM_SEQUENCE_RX_AND_TX_LOW_RATE; +extern std::pair> COM_SEQUENCE_RX_AND_TX_HIGH_RATE; ComSubsystem::ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, - uint32_t maxNumberOfTables) + uint32_t maxNumberOfTables, uint32_t transmitterTimeout) : Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables), paramHelper(this) { com::setCurrentDatarate(com::Datarate::LOW_RATE_MODULATION_BPSK); + auto mqArgs = MqArgs(setObjectId, static_cast(this)); + eventQueue = + QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); + transmitterCountdown.setTimeout(transmitterTimeout); +} + +void ComSubsystem::performChildOperation() { + readEventQueue(); + checkTransmitterCountdown(); } MessageQueueId_t ComSubsystem::getCommandQueue() const { return Subsystem::getCommandQueue(); } @@ -44,5 +63,97 @@ ReturnValue_t ComSubsystem::initialize() { if (result != returnvalue::OK) { return result; } + EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (manager == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "ComSubsystem::initialize: Invalid event manager" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->registerListener(eventQueue->getId()); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "ComSubsystem::initialize: Failed to register Com Subsystem as event " + "listener" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEventRange(eventQueue->getId(), + event::getEventId(PdecHandler::CARRIER_LOCK), + event::getEventId(PdecHandler::BIT_LOCK_PDEC)); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "ComSubsystem::initialize: Failed to subscribe to events from PDEC " + "handler" + << std::endl; +#endif + return result; + } return Subsystem::initialize(); } + +void ComSubsystem::startTransition(Mode_t mode, Submode_t submode) { + // Depending on the mode the transmitter timeout is enabled or + // disabled here + if (mode == COM_SEQUENCE_RX_ONLY.first) { + transmitterCountdown.timeOut(); + } else if ((mode == COM_SEQUENCE_RX_AND_TX_DEFAULT_RATE.first) || + (mode == COM_SEQUENCE_RX_AND_TX_LOW_RATE.first) || + (mode == COM_SEQUENCE_RX_AND_TX_HIGH_RATE.first)) { + transmitterCountdown.resetTimer(); + } + Subsystem::startTransition(mode, submode); +} + +void ComSubsystem::readEventQueue() { + EventMessage event; + for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; + result = eventQueue->receiveMessage(&event)) { + switch (event.getMessageId()) { + case EventMessage::EVENT_MESSAGE: + handleEventMessage(&event); + break; + default: + sif::debug << "CcsdsHandler::checkEvents: Did not subscribe to this event message" + << std::endl; + break; + } + } +} + +void ComSubsystem::handleEventMessage(EventMessage *eventMessage) { + Event event = eventMessage->getEvent(); + switch (event) { + case PdecHandler::BIT_LOCK_PDEC: { + handleBitLockEvent(); + break; + } + case PdecHandler::CARRIER_LOCK: { + handleCarrierLockEvent(); + break; + } + default: + sif::debug << "ComSubsystem::handleEvent: Did not subscribe to this event" << std::endl; + break; + } +} + +void ComSubsystem::handleBitLockEvent() { startRxAndTxDefaultSeq(); } + +void ComSubsystem::handleCarrierLockEvent() { + if (!enableTxWhenCarrierLock) { + return; + } + startRxAndTxDefaultSeq(); +} + +void ComSubsystem::startRxAndTxDefaultSeq() { + // Turns transmitter on + startTransition(COM_SEQUENCE_RX_AND_TX_DEFAULT_RATE.first, SUBMODE_NONE); +} + +void ComSubsystem::checkTransmitterCountdown() { + if (transmitterCountdown.hasTimedOut()) { + startTransition(COM_SEQUENCE_RX_ONLY.first, SUBMODE_NONE); + } +} diff --git a/mission/system/objects/ComSubsystem.h b/mission/system/objects/ComSubsystem.h index 74f0c30e..3f1ef5d2 100644 --- a/mission/system/objects/ComSubsystem.h +++ b/mission/system/objects/ComSubsystem.h @@ -4,26 +4,61 @@ #include #include #include +#include #include "mission/comDefs.h" class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF { public: - ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables); + /** + * @brief Constructor + * + * @param setObjectId + * @param maxNumberOfSequences + * @param maxNumberOfTables + * @param transmitterTimeout Maximum time the transmitter of the syrlinks + * will be enabled + */ + ComSubsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables, + uint32_t transmitterTimeout); virtual ~ComSubsystem() = default; MessageQueueId_t getCommandQueue() const override; ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, uint16_t startAtIndex) override; + virtual void performChildOperation() override; private: ReturnValue_t handleCommandMessage(CommandMessage *message) override; ReturnValue_t initialize() override; + void startTransition(Mode_t mode, Submode_t submode) override; + + void readEventQueue(); + void handleEventMessage(EventMessage* eventMessage); + void handleBitLockEvent(); + void handleCarrierLockEvent(); + void checkTransmitterCountdown(); + /** + * @brief Enables transmitter in default (low) rate mode + */ + void startRxAndTxDefaultSeq(); + uint8_t datarateCfg = static_cast(com::Datarate::LOW_RATE_MODULATION_BPSK); ParameterHelper paramHelper; + + MessageQueueIF* eventQueue = nullptr; + + bool enableTxWhenCarrierLock = false; + + // Maximum time after which the transmitter will be turned of. This is a + // protection mechanism due prevent the syrlinks from overheating + uint32_t transmitterTimeout = 0; + + // Countdown will be started as soon as the transmitter was enabled + Countdown transmitterCountdown; }; #endif /* MISSION_SYSTEM_COMSUBSYSTEM_H_ */ diff --git a/mission/system/tree/comModeTree.cpp b/mission/system/tree/comModeTree.cpp index e08ba5ba..d0811dd7 100644 --- a/mission/system/tree/comModeTree.cpp +++ b/mission/system/tree/comModeTree.cpp @@ -1,6 +1,5 @@ #include "comModeTree.h" -#include #include #include #include @@ -11,7 +10,7 @@ const auto check = subsystem::checkInsert; -ComSubsystem satsystem::com::SUBSYSTEM = ComSubsystem(objects::COM_SUBSYSTEM, 12, 24); +ComSubsystem satsystem::com::SUBSYSTEM = ComSubsystem(objects::COM_SUBSYSTEM, 12, 24, TRANSMITTER_TIMEOUT); static const auto OFF = HasModesIF::MODE_OFF; static const auto ON = HasModesIF::MODE_ON; @@ -94,7 +93,7 @@ void buildRxOnlySequence(Subsystem& ss, ModeListEntry& eh) { // Build RX Only table. We could track the state of the CCSDS IP core handler // as well but I do not think this is necessary because enabling that should - // not intefere with the Syrlinks Handler. + // not interfere with the Syrlinks Handler. iht(objects::SYRLINKS_HANDLER, NML, ::com::Submode::RX_ONLY, COM_TABLE_RX_ONLY_TGT.second); check(ss.addTable(TableEntry(COM_TABLE_RX_ONLY_TGT.first, &COM_TABLE_RX_ONLY_TGT.second)), ctxc); diff --git a/mission/system/tree/comModeTree.h b/mission/system/tree/comModeTree.h index ccc7f15f..587cc8ed 100644 --- a/mission/system/tree/comModeTree.h +++ b/mission/system/tree/comModeTree.h @@ -2,12 +2,17 @@ #define MISSION_SYSTEM_TREE_COMMODETREE_H_ #include +#include namespace satsystem { namespace com { extern ComSubsystem SUBSYSTEM; +// The syrlinks must not transmitting longer then 15 minutes otherwise the +// transceiver might be damaged due to overheating +static const uint32_t TRANSMITTER_TIMEOUT = 900000; // 15 minutes + void init(); } // namespace com diff --git a/mission/tmtc/CcsdsIpCoreHandler.cpp b/mission/tmtc/CcsdsIpCoreHandler.cpp index 85d1143b..0b6a210d 100644 --- a/mission/tmtc/CcsdsIpCoreHandler.cpp +++ b/mission/tmtc/CcsdsIpCoreHandler.cpp @@ -1,12 +1,10 @@ #include "CcsdsIpCoreHandler.h" #include -#include #include #include #include "eive/definitions.h" -#include "fsfw/events/EventManagerIF.h" #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/serialize/SerializeAdapter.h" @@ -16,8 +14,7 @@ CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination, PtmeConfig* ptmeConfig, - GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData, - uint32_t transmitterTimeout) + GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData) : SystemObject(objectId), ptmeId(ptmeId), tcDestination(tcDestination), @@ -27,8 +24,7 @@ CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t ptmeId, ptmeConfig(ptmeConfig), gpioIF(gpioIF), enTxClock(enTxClock), - enTxData(enTxData), - transmitterTimeout(transmitterTimeout) { + enTxData(enTxData) { commandQueue = QueueFactory::instance()->createMessageQueue(QUEUE_SIZE); auto mqArgs = MqArgs(objectId, static_cast(this)); eventQueue = @@ -38,11 +34,9 @@ CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t ptmeId, CcsdsIpCoreHandler::~CcsdsIpCoreHandler() {} ReturnValue_t CcsdsIpCoreHandler::performOperation(uint8_t operationCode) { - checkEvents(); readCommandQueue(); handleTelemetry(); handleTelecommands(); - checkTxTimer(); return returnvalue::OK; } @@ -98,34 +92,6 @@ ReturnValue_t CcsdsIpCoreHandler::initialize() { iter->second->setPtmeObject(ptme); } - EventManagerIF* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); - if (manager == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CcsdsHandler::initialize: Invalid event manager" << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } - result = manager->registerListener(eventQueue->getId()); - if (result != returnvalue::OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "CcsdsHandler::initialize: Failed to register CCSDS handler as event " - "listener" - << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; - ; - } - result = manager->subscribeToEventRange(eventQueue->getId(), - event::getEventId(PdecHandler::CARRIER_LOCK), - event::getEventId(PdecHandler::BIT_LOCK_PDEC)); - if (result != returnvalue::OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "CcsdsHandler::initialize: Failed to subscribe to events from PDEC " - "handler" - << std::endl; -#endif - return result; - } result = ptmeConfig->initialize(); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; @@ -135,9 +101,6 @@ ReturnValue_t CcsdsIpCoreHandler::initialize() { return ObjectManagerIF::CHILD_INIT_FAILED; } - transmitterCountdown.setTimeout(transmitterTimeout); - transmitterCountdown.timeOut(); - #if OBSW_SYRLINKS_SIMULATED == 1 // Update data on rising edge ptmeConfig->invertTxClock(false); @@ -286,54 +249,6 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu return EXECUTION_FINISHED; } -void CcsdsIpCoreHandler::checkEvents() { - EventMessage event; - for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; - result = eventQueue->receiveMessage(&event)) { - switch (event.getMessageId()) { - case EventMessage::EVENT_MESSAGE: - handleEvent(&event); - break; - default: - sif::debug << "CcsdsHandler::checkEvents: Did not subscribe to this event message" - << std::endl; - break; - } - } -} - -void CcsdsIpCoreHandler::handleEvent(EventMessage* eventMessage) { - Event event = eventMessage->getEvent(); - switch (event) { - case PdecHandler::BIT_LOCK_PDEC: { - handleBitLockEvent(); - break; - } - case PdecHandler::CARRIER_LOCK: { - handleCarrierLockEvent(); - break; - } - default: - sif::debug << "CcsdsHandler::handleEvent: Did not subscribe to this event" << std::endl; - break; - } -} - -void CcsdsIpCoreHandler::handleBitLockEvent() { - if (transmitterCountdown.isBusy()) { - // Transmitter already enabled - return; - } - enableTransmit(); -} - -void CcsdsIpCoreHandler::handleCarrierLockEvent() { - if (!enableTxWhenCarrierLock) { - return; - } - enableTransmit(); -} - void CcsdsIpCoreHandler::forwardLinkstate() { VirtualChannelMapIter iter; for (iter = virtualChannelMap.begin(); iter != virtualChannelMap.end(); iter++) { @@ -342,27 +257,12 @@ void CcsdsIpCoreHandler::forwardLinkstate() { } void CcsdsIpCoreHandler::enableTransmit() { - if (transmitterCountdown.isBusy()) { - // Transmitter already enabled - return; - } #ifndef TE0720_1CFA gpioIF->pullHigh(enTxClock); gpioIF->pullHigh(enTxData); #endif linkState = UP; forwardLinkstate(); - transmitterCountdown.resetTimer(); -} - -void CcsdsIpCoreHandler::checkTxTimer() { - if (linkState == DOWN) { - return; - } - if (transmitterCountdown.hasTimedOut()) { - disableTransmit(); - //TODO: set mode to off (move timer to subsystem) - } } void CcsdsIpCoreHandler::getMode(Mode_t* mode, Submode_t* submode) { @@ -431,7 +331,6 @@ void CcsdsIpCoreHandler::disableTransmit() { #endif linkState = DOWN; forwardLinkstate(); - transmitterCountdown.timeOut(); } const char* CcsdsIpCoreHandler::getName() const { return "CCSDS Handler"; } diff --git a/mission/tmtc/CcsdsIpCoreHandler.h b/mission/tmtc/CcsdsIpCoreHandler.h index 37212851..356c2f8d 100644 --- a/mission/tmtc/CcsdsIpCoreHandler.h +++ b/mission/tmtc/CcsdsIpCoreHandler.h @@ -59,8 +59,7 @@ class CcsdsIpCoreHandler : public SystemObject, * @param enTxData GPIO ID of RS485 tx data enable */ CcsdsIpCoreHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination, - PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData, - uint32_t transmitterTimeout = 900000); + PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData); ~CcsdsIpCoreHandler(); @@ -154,29 +153,16 @@ class CcsdsIpCoreHandler : public SystemObject, PtmeConfig* ptmeConfig = nullptr; GpioIF* gpioIF = nullptr; + // GPIO to enable RS485 transceiver for TX clock gpioId_t enTxClock = gpio::NO_GPIO; + // GPIO to enable RS485 transceiver for TX data signal gpioId_t enTxData = gpio::NO_GPIO; - // Syrlinks must not be transmitting more than 15 minutes (according to datasheet) - // Value initialized by constructor argument - const uint32_t transmitterTimeout = 0; - - // Countdown to disable transmitter after 15 minutes - Countdown transmitterCountdown; - - // When true transmitting is started as soon as carrier lock has been detected - bool enableTxWhenCarrierLock = false; - bool linkState = DOWN; void readCommandQueue(void); void handleTelemetry(); void handleTelecommands(); - void checkEvents(); - void handleEvent(EventMessage* eventMessage); - - void handleBitLockEvent(); - void handleCarrierLockEvent(); /** * @brief Forward link state to virtual channels. @@ -188,12 +174,6 @@ class CcsdsIpCoreHandler : public SystemObject, */ void enableTransmit(); - /** - * @brief Checks Tx timer for timeout and disables RS485 tx clock and tx data in case - * timer has expired. - */ - void checkTxTimer(); - /** * @brief Disables the transmitter by pulling the enable tx clock and tx data pin of the * RS485 transceiver chips to high.