diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index bceb303d..cb01496c 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -263,7 +263,7 @@ void initmission::createPstTasks(TaskFactory& factory, sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; } taskVec.push_back(gomSpacePstTask); -#else /* BOARD_TE7020 == 0 */ +#else /* BOARD_TE7020 == 0 */ FixedTimeslotTaskIF* pollingSequenceTaskTE0720 = factory.createFixedTimeslotTask( "PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0, missedDeadlineFunc); result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720); diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 17b22830..6b93201a 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -75,13 +75,11 @@ #include "linux/boardtest/LibgpiodTest.h" #endif +#include #include #include #include -#include #include -#include -#include ResetArgs resetArgsGnss0; ResetArgs resetArgsGnss1; @@ -960,11 +958,11 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) { ptme->addVcInterface(ccsds::VC2, vc2); ptme->addVcInterface(ccsds::VC3, vc3); - PtmeAxiConfig* ptmeAxiConfig = - new PtmeAxiConfig(objects::PTME_AXI_CONFIG, q7s::UIO_PTME, q7s::uiomapids::PTME_CONFIG); - TxRateSetterIF* txRateSetterIF = new PtmeRateSetter(objects::TX_RATE_SETTER, ptmeAxiConfig); + AxiPtmeConfig* axiPtmeConfig = + new AxiPtmeConfig(objects::AXI_PTME_CONFIG, q7s::UIO_PTME, q7s::uiomapids::PTME_CONFIG); + PtmeConfig* ptmeConfig = new PtmeConfig(objects::PTME_CONFIG, axiPtmeConfig); CCSDSHandler* ccsdsHandler = new CCSDSHandler( - objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, txRateSetterIF, + objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, ptmeConfig, gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA); VirtualChannel* vc = nullptr; diff --git a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp index 96c47fe9..c0db5089 100644 --- a/bsp_q7s/devices/startracker/StarTrackerHandler.cpp +++ b/bsp_q7s/devices/startracker/StarTrackerHandler.cpp @@ -775,7 +775,7 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, void StarTrackerHandler::setNormalDatapoolEntriesInvalid() {} -uint32_t StarTrackerHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 30000; } +uint32_t StarTrackerHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 20000; } ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { diff --git a/bsp_q7s/devices/startracker/StrHelper.cpp b/bsp_q7s/devices/startracker/StrHelper.cpp index eedd0241..417ea248 100644 --- a/bsp_q7s/devices/startracker/StrHelper.cpp +++ b/bsp_q7s/devices/startracker/StrHelper.cpp @@ -1,4 +1,5 @@ #include "StrHelper.h" +#include "OBSWConfig.h" #include #include @@ -248,6 +249,9 @@ ReturnValue_t StrHelper::performImageDownload() { file.write(reinterpret_cast(datalinkLayer.getReply() + IMAGE_DATA_OFFSET), IMAGE_DATA_SIZE); downloadReq.position++; +#if OBSW_DEBUG_STARTRACKER == 1 + printProgress(downloadReq.position, ImageDownload::LAST_POSITION); +#endif /* OBSW_DEBUG_STARTRACKER == 1 */ retries = 0; } file.close(); @@ -286,6 +290,9 @@ ReturnValue_t StrHelper::performImageUpload() { if (result != RETURN_OK) { return result; } +#if OBSW_DEBUG_STARTRACKER == 1 + printProgress((uploadReq.position + 1) * SIZE_IMAGE_PART, imageSize); +#endif /* OBSW_DEBUG_STARTRACKER == 1 */ uploadReq.position++; } std::memset(uploadReq.data, 0, sizeof(uploadReq.data)); @@ -303,6 +310,9 @@ ReturnValue_t StrHelper::performImageUpload() { if (result != RETURN_OK) { return result; } +#if OBSW_DEBUG_STARTRACKER == 1 + printProgress((uploadReq.position + 1) * SIZE_IMAGE_PART, imageSize); +#endif /* OBSW_DEBUG_STARTRACKER == 1 */ return RETURN_OK; } @@ -670,3 +680,15 @@ ReturnValue_t StrHelper::checkPath(std::string name) { } return RETURN_OK; } + +void StrHelper::printProgress(uint32_t itemsTransferred, uint32_t fullNumItems) { + float progressInPercent = + static_cast(itemsTransferred) / static_cast(fullNumItems) * 100; + if (static_cast(progressInPercent) == nextProgressPrint) { + sif::info << "Str Helper Progress: " << progressInPercent << " %" << std::endl; + nextProgressPrint += FIVE_PERCENT; + } + if (nextProgressPrint > 100) { + nextProgressPrint = 0; + } +} diff --git a/bsp_q7s/devices/startracker/StrHelper.h b/bsp_q7s/devices/startracker/StrHelper.h index c08aaae1..77fe7d2a 100644 --- a/bsp_q7s/devices/startracker/StrHelper.h +++ b/bsp_q7s/devices/startracker/StrHelper.h @@ -184,6 +184,7 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu // Size of one image part which can be sent per action request static const size_t SIZE_IMAGE_PART = 1024; + static constexpr uint32_t FIVE_PERCENT = 5; class ImageDownload { public: @@ -292,6 +293,8 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu bool terminate = false; + uint32_t nextProgressPrint = 0; + /** * UART communication object responsible for low level access of star tracker * Must be set by star tracker handler @@ -392,6 +395,14 @@ class StrHelper : public SystemObject, public ExecutableObjectIF, public HasRetu * @return SD_NOT_MOUNTED id SD card is not mounted, otherwise RETURN_OK */ ReturnValue_t checkPath(std::string name); + + /** + * @brief Prints progress of transfer which can be useful for large data transfers + * + * @param itemsTransferred Number of items transferred + * @param fullNumItems Full number of items to transfer + */ + void printProgress(uint32_t itemsTransferred, uint32_t fullNumItems); }; #endif /* BSP_Q7S_DEVICES_STRHELPER_H_ */ diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 99096ba4..bd364daf 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -87,8 +87,8 @@ enum commonObjects: uint32_t { PLOC_UPDATER = 0x44330000, PLOC_MEMORY_DUMPER = 0x44330001, STR_HELPER = 0x44330002, - PTME_AXI_CONFIG = 44330003, - TX_RATE_SETTER = 44330004 + AXI_PTME_CONFIG = 44330003, + PTME_CONFIG = 44330004, }; } diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 00d2d9fd..c3caf1a9 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -53,6 +53,7 @@ debugging. */ #define OBSW_ADD_RAD_SENSORS 0 #define OBSW_ADD_SYRLINKS 0 #define OBSW_ENABLE_SYRLINKS_TRANSMIT_TIMEOUT 0 +#define OBSW_SYRLINKS_SIMULATED 1 #endif diff --git a/linux/obc/AxiPtmeConfig.cpp b/linux/obc/AxiPtmeConfig.cpp new file mode 100644 index 00000000..26830d05 --- /dev/null +++ b/linux/obc/AxiPtmeConfig.cpp @@ -0,0 +1,119 @@ +#include "AxiPtmeConfig.h" + +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw_hal/linux/uio/UioMapper.h" + +AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNum) + : SystemObject(objectId), axiUio(axiUio), mapNum(mapNum) { + mutex = MutexFactory::instance()->createMutex(); + if (mutex == nullptr) { + sif::warning << "Failed to create mutex" << std::endl; + } +} + +AxiPtmeConfig::~AxiPtmeConfig() {} + +ReturnValue_t AxiPtmeConfig::initialize() { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + UioMapper uioMapper(axiUio, mapNum); + result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + result = mutex->lockMutex(timeoutType, mutexTimeout); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + *(baseAddress + CADU_BITRATE_REG) = static_cast(rateVal); + result = mutex->unlockMutex(); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to unlock mutex" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::enableTxclockManipulator() { + ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::disableTxclockManipulator() { + ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::EN_TX_CLK_MANIPULATOR); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::enableTxclockInversion() { + ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::INVERT_CLOCK); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::disableTxclockInversion() { + ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::INVERT_CLOCK); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::writeReg(uint32_t regOffset, uint32_t writeVal) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + result = mutex->lockMutex(timeoutType, mutexTimeout); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "AxiPtmeConfig::readReg: Failed to lock mutex" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + *(baseAddress + regOffset / ADRESS_DIVIDER) = writeVal; + result = mutex->unlockMutex(); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "AxiPtmeConfig::readReg: Failed to unlock mutex" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::readReg(uint32_t regOffset, uint32_t* readVal) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + result = mutex->lockMutex(timeoutType, mutexTimeout); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "AxiPtmeConfig::readReg: Failed to lock mutex" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + *readVal = *(baseAddress + regOffset / ADRESS_DIVIDER); + result = mutex->unlockMutex(); + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "AxiPtmeConfig::readReg: Failed to unlock mutex" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AxiPtmeConfig::writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos) { + uint32_t readVal = 0; + ReturnValue_t result = readReg(regOffset, &readVal); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + uint32_t writeVal = + (readVal & ~(1 << static_cast(bitPos))) | bitVal << static_cast(bitPos); + result = writeReg(regOffset, writeVal); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/linux/obc/AxiPtmeConfig.h b/linux/obc/AxiPtmeConfig.h new file mode 100644 index 00000000..c86bb429 --- /dev/null +++ b/linux/obc/AxiPtmeConfig.h @@ -0,0 +1,99 @@ +#ifndef LINUX_OBC_AXIPTMECONFIG_H_ +#define LINUX_OBC_AXIPTMECONFIG_H_ + +#include + +#include "fsfw/ipc/MutexIF.h" +#include "fsfw/objectmanager/SystemObject.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + +/** + * @brief Class providing low level access to the configuration interface of the PTME. + * + * @author J. Meier + */ +class AxiPtmeConfig : public SystemObject { + public: + /** + * @brief Constructor + * @param axiUio Device file of UIO belonging to the AXI configuration interface. + * @param mapNum Number of map belonging to axi configuration interface. + */ + AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNum); + virtual ~AxiPtmeConfig(); + + virtual ReturnValue_t initialize() override; + /** + * @brief Will write to the bitrate configuration register. Actual generated rate depends on + * frequency of the clock connected to the bit clock input of PTME. + */ + ReturnValue_t writeCaduRateReg(uint8_t rateVal); + + /** + * @brief Next to functions control the tx clock manipulator component + * + * @details If the tx clock manipulator is enabled the output clock of the PTME is manipulated + * in a way that both high and low periods in the clock signal have equal lengths. + * The default implementation of the PTME generates a clock where the high level is + * only one bit clock period long. This might be too short to match the setup and hold + * times of the S-and transceiver. + */ + ReturnValue_t enableTxclockManipulator(); + ReturnValue_t disableTxclockManipulator(); + + /** + * @brief The next to functions control whether data will be updated on the rising or falling edge + * of the tx clock. + * Enable inversion will update data on falling edge (not the configuration required by the + * syrlinks) + * Disable clock inversion. Data updated on rising edge. + */ + ReturnValue_t enableTxclockInversion(); + ReturnValue_t disableTxclockInversion(); + + private: + // Address of register storing the bitrate configuration parameter + static const uint32_t CADU_BITRATE_REG = 0x0; + // Address to register storing common configuration parameters + static const uint32_t COMMON_CONFIG_REG = 0x4; + static const uint32_t ADRESS_DIVIDER = 4; + + enum class BitPos : uint32_t { EN_TX_CLK_MANIPULATOR, INVERT_CLOCK }; + + std::string axiUio; + std::string uioMap; + int mapNum = 0; + MutexIF* mutex = nullptr; + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t mutexTimeout = 20; + + uint32_t* baseAddress = nullptr; + + /** + * @brief Function to write to configuration registers + * + * @param writeVal Value to write + */ + ReturnValue_t writeReg(uint32_t regOffset, uint32_t writeVal); + + /** + * @brief Reads value from configuration register + * + * @param regOffset Offset of register from base address to read from + * Qparam readVal Pointer to variable where read value will be written to + */ + ReturnValue_t readReg(uint32_t regOffset, uint32_t* readVal); + + /** + * @brief Sets one bit in a register + * + * @param regOffset Offset of the register where to set the bit + * @param bitVal The value of the bit to set (1 or 0) + * @param bitPos The position of the bit within the register to set + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED + */ + ReturnValue_t writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos); +}; + +#endif /* LINUX_OBC_AXIPTMECONFIG_H_ */ diff --git a/linux/obc/CMakeLists.txt b/linux/obc/CMakeLists.txt index d59a1a5f..79e32a78 100644 --- a/linux/obc/CMakeLists.txt +++ b/linux/obc/CMakeLists.txt @@ -3,8 +3,8 @@ target_sources(${TARGET_NAME} PUBLIC Ptme.cpp PdecHandler.cpp PdecConfig.cpp - PtmeRateSetter.cpp - PtmeAxiConfig.cpp + PtmeConfig.cpp + AxiPtmeConfig.cpp ) diff --git a/linux/obc/PtmeAxiConfig.cpp b/linux/obc/PtmeAxiConfig.cpp deleted file mode 100644 index 0619ca38..00000000 --- a/linux/obc/PtmeAxiConfig.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "PtmeAxiConfig.h" - -#include "fsfw/serviceinterface/ServiceInterface.h" -#include "fsfw_hal/linux/uio/UioMapper.h" - -PtmeAxiConfig::PtmeAxiConfig(object_id_t objectId, std::string configAxiUio, int mapNum) - : SystemObject(objectId), configAxiUio(configAxiUio), mapNum(mapNum) { - mutex = MutexFactory::instance()->createMutex(); - if (mutex == nullptr) { - sif::warning << "Failed to create mutex" << std::endl; - } -} - -PtmeAxiConfig::~PtmeAxiConfig() {} - -ReturnValue_t PtmeAxiConfig::initialize() { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - UioMapper uioMapper(configAxiUio, mapNum); - result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t PtmeAxiConfig::writeCaduRateReg(uint8_t rateVal) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - result = mutex->lockMutex(timeoutType, mutexTimeout); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "PtmeAxiConfig::writeCaduRateReg: Failed to lock mutex" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - *(baseAddress + CADU_BITRATE_REG) = static_cast(rateVal); - result = mutex->unlockMutex(); - if (result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "PtmeAxiConfig::writeCaduRateReg: Failed to unlock mutex" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} diff --git a/linux/obc/PtmeAxiConfig.h b/linux/obc/PtmeAxiConfig.h deleted file mode 100644 index 4638d0c0..00000000 --- a/linux/obc/PtmeAxiConfig.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef LINUX_OBC_PTMEAXICONFIG_H_ -#define LINUX_OBC_PTMEAXICONFIG_H_ - -#include - -#include "fsfw/ipc/MutexIF.h" -#include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" - -/** - * @brief Class providing low level access to the configuration interface of the PTME. - * - * @author J. Meier - */ -class PtmeAxiConfig : public SystemObject { - public: - /** - * @brief Constructor - * @param configAxiUio Device file of UIO belonging to the AXI configuration interface. - * @param mapNum Number of map belonging to axi configuration interface. - */ - PtmeAxiConfig(object_id_t objectId, std::string configAxiUio, int mapNum); - virtual ~PtmeAxiConfig(); - - virtual ReturnValue_t initialize() override; - ReturnValue_t writeCaduRateReg(uint8_t rateVal); - - private: - // Address of register storing the bitrate configuration parameter - static const uint32_t CADU_BITRATE_REG = 0x0; - - std::string configAxiUio; - std::string uioMap; - int mapNum = 0; - MutexIF* mutex = nullptr; - MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; - uint32_t mutexTimeout = 20; - - uint32_t* baseAddress = nullptr; -}; - -#endif /* LINUX_OBC_PTMEAXICONFIG_H_ */ diff --git a/linux/obc/PtmeConfig.cpp b/linux/obc/PtmeConfig.cpp new file mode 100644 index 00000000..9cbda7a6 --- /dev/null +++ b/linux/obc/PtmeConfig.cpp @@ -0,0 +1,50 @@ +#include "PtmeConfig.h" + +#include "fsfw/serviceinterface/ServiceInterface.h" + +PtmeConfig::PtmeConfig(object_id_t objectId, AxiPtmeConfig* axiPtmeConfig) + : SystemObject(objectId), axiPtmeConfig(axiPtmeConfig) {} + +PtmeConfig::~PtmeConfig() {} + +ReturnValue_t PtmeConfig::initialize() { + if (axiPtmeConfig == nullptr) { + sif::warning << "PtmeConfig::initialize: Invalid AxiPtmeConfig object" << std::endl; + return RETURN_FAILED; + } + return RETURN_OK; +} + +ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) { + if (bitRate == 0) { + return BAD_BIT_RATE; + } + uint32_t rateVal = BIT_CLK_FREQ / bitRate - 1; + if (rateVal > 0xFF) { + return RATE_NOT_SUPPORTED; + } + return axiPtmeConfig->writeCaduRateReg(static_cast(rateVal)); +} + +ReturnValue_t PtmeConfig::invertTxClock(bool invert) { + ReturnValue_t result = RETURN_OK; + if (invert) { + result = axiPtmeConfig->enableTxclockInversion(); + } else { + result = axiPtmeConfig->disableTxclockInversion(); + } + if (result != RETURN_OK) { + return CLK_INVERSION_FAILED; + } + return result; +} + +ReturnValue_t PtmeConfig::configTxManipulator(bool enable) { + ReturnValue_t result = RETURN_OK; + if (enable) { + result = axiPtmeConfig->enableTxclockManipulator(); + } else { + result = axiPtmeConfig->disableTxclockManipulator(); + } + return result; +} diff --git a/linux/obc/PtmeConfig.h b/linux/obc/PtmeConfig.h index 2dd7b7b2..d6e35b57 100644 --- a/linux/obc/PtmeConfig.h +++ b/linux/obc/PtmeConfig.h @@ -1,32 +1,76 @@ #ifndef LINUX_OBC_PTMECONFIG_H_ #define LINUX_OBC_PTMECONFIG_H_ -#include - -#include "OBSWConfig.h" +#include "AxiPtmeConfig.h" +#include "fsfw/objectmanager/SystemObject.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "linux/obc/PtmeConfig.h" /** - * @brief PTME specific configuration parameters derived from FPGA design and device tree. + * @brief Class to configure donwlink specific parameters in the PTME IP core. * * @author J. Meier */ -namespace PtmeConfig { -/** - * Offset of virtual channels mapped into address space - * 0x10000 = (0x4000 * 4) - */ -static const uint32_t VC0_OFFSETT = 0; -static const uint32_t VC1_OFFSETT = 0x4000; -static const uint32_t VC2_OFFSETT = 0x8000; -static const uint32_t VC3_OFFSETT = 0xC000; -#if BOARD_TE0720 == 0 -static const char UIO_DEVICE_FILE[] = "/dev/uio1"; -#else -static const char UIO_DEVICE_FILE[] = "/dev/uio1"; -#endif -// Bit clock frequency of PMTE IP core in Hz -static const uint32_t BIT_CLK_FREQ = 20000000; -}; // namespace PtmeConfig +class PtmeConfig : public SystemObject, public HasReturnvaluesIF { + public: + /** + * @brief Constructor + * + * ptmeAxiConfig Pointer to object providing access to PTME configuration registers. + */ + PtmeConfig(object_id_t opbjectId, AxiPtmeConfig* axiPtmeConfig); + virtual ~PtmeConfig(); + + virtual ReturnValue_t initialize() override; + /** + * @brief Changes the input frequency to the S-Band transceiver and thus the downlink rate + * + * @details This is the bitrate of the CADU clock and not the downlink which has twice the bitrate + * of the CADU clock due to the convolutional code added by the s-Band transceiver. + */ + ReturnValue_t setRate(uint32_t bitRate); + + /** + * @brief Will change the time the tx data signal is updated with respect to the tx clock + * + * @param invert True -> Data signal will be updated on the falling edge (not desired by the + * Syrlinks) + * False -> Data signal updated on rising edge (default configuration and desired + * by the syrlinks) + * + * @return REUTRN_OK if successful, otherwise error return value + */ + ReturnValue_t invertTxClock(bool invert); + + /** + * @brief Controls the tx clock manipulator of the PTME wrapper component + * + * @param enable Manipulator will be enabled (this is also the default configuration) + * @param disable Manipulator will be disabled + * + * @return REUTRN_OK if successful, otherwise error return value + */ + ReturnValue_t configTxManipulator(bool enable); + + private: + static const uint8_t INTERFACE_ID = CLASS_ID::RATE_SETTER; + + //! [EXPORT] : [COMMENT] The commanded rate is not supported by the current FPGA design + static const ReturnValue_t RATE_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] Bad bitrate has been commanded (e.g. 0) + static const ReturnValue_t BAD_BIT_RATE = MAKE_RETURN_CODE(0xA1); + //! [EXPORT] : [COMMENT] Failed to invert clock and thus change the time the data is updated with + //! respect to the tx clock + static const ReturnValue_t CLK_INVERSION_FAILED = MAKE_RETURN_CODE(0xA2); + //! [EXPORT] : [COMMENT] Failed to change configuration bit of tx clock manipulator + static const ReturnValue_t TX_MANIPULATOR_CONFIG_FAILED = MAKE_RETURN_CODE(0xA3); + + // Bitrate register field is only 8 bit wide + static const uint32_t MAX_BITRATE = 0xFF; + // Bit clock frequency of PMTE IP core in Hz + static const uint32_t BIT_CLK_FREQ = 20000000; + + AxiPtmeConfig* axiPtmeConfig = nullptr; +}; #endif /* LINUX_OBC_PTMECONFIG_H_ */ diff --git a/linux/obc/PtmeRateSetter.cpp b/linux/obc/PtmeRateSetter.cpp deleted file mode 100644 index 8275e8fe..00000000 --- a/linux/obc/PtmeRateSetter.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "PtmeRateSetter.h" - -#include "fsfw/serviceinterface/ServiceInterface.h" - -PtmeRateSetter::PtmeRateSetter(object_id_t objectId, PtmeAxiConfig* ptmeAxiConfig) - : SystemObject(objectId), ptmeAxiConfig(ptmeAxiConfig) {} - -PtmeRateSetter::~PtmeRateSetter() {} - -ReturnValue_t PtmeRateSetter::initialize() { - if (ptmeAxiConfig == nullptr) { - sif::warning << "PtmeRateSetter::initialize: Invalid PtmeAxiConfig object" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t PtmeRateSetter::setRate(uint32_t bitRate) { - if (bitRate <= 1) { - return BAD_BIT_RATE; - } - uint32_t rateVal = PtmeConfig::BIT_CLK_FREQ / bitRate - 1; - if (rateVal > 0xFF) { - return RATE_NOT_SUPPORTED; - } - return ptmeAxiConfig->writeCaduRateReg(static_cast(rateVal)); -} diff --git a/linux/obc/PtmeRateSetter.h b/linux/obc/PtmeRateSetter.h deleted file mode 100644 index 44ac9b48..00000000 --- a/linux/obc/PtmeRateSetter.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef LINUX_OBC_PTMERATESETTER_H_ -#define LINUX_OBC_PTMERATESETTER_H_ - -#include "TxRateSetterIF.h" -#include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/returnvalues/HasReturnvaluesIF.h" -#include "linux/obc/PtmeAxiConfig.h" -#include "linux/obc/PtmeConfig.h" - -/** - * @brief Class to set the downlink bit rate by writing to the AXI configuration interface of the - * PTME IP core. - * - * @details This is the bitrate of the CADU clock and not the downlink which has twice the bitrate - * of the CADU clock due to the convolutional code added by the s-Band transceiver. - * - * @author J. Meier - */ -class PtmeRateSetter : public TxRateSetterIF, public SystemObject, public HasReturnvaluesIF { - public: - /** - * @brief Constructor - * - * objectId Object id of system object - * ptmeAxiConfig Pointer to object providing access to PTME configuration registers. - */ - PtmeRateSetter(object_id_t objectId, PtmeAxiConfig* ptmeAxiConfig); - virtual ~PtmeRateSetter(); - - virtual ReturnValue_t initialize() override; - virtual ReturnValue_t setRate(uint32_t bitRate); - - private: - static const uint8_t INTERFACE_ID = CLASS_ID::RATE_SETTER; - - //! [EXPORT] : [COMMENT] The commanded rate is not supported by the current FPGA design - static const ReturnValue_t RATE_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0); - //! [EXPORT] : [COMMENT] Bad bitrate has been commanded (e.g. 0) - static const ReturnValue_t BAD_BIT_RATE = MAKE_RETURN_CODE(0xA1); - - // Bitrate register field is only 8 bit wide - static const uint32_t MAX_BITRATE = 0xFF; - - PtmeAxiConfig* ptmeAxiConfig = nullptr; -}; - -#endif /* LINUX_OBC_PTMERATESETTER_H_ */ diff --git a/linux/obc/TxRateSetterIF.h b/linux/obc/TxRateSetterIF.h deleted file mode 100644 index e8682551..00000000 --- a/linux/obc/TxRateSetterIF.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LINUX_OBC_TXRATESETTERIF_H_ -#define LINUX_OBC_TXRATESETTERIF_H_ - -#include "fsfw/returnvalues/HasReturnvaluesIF.h" - -/** - * @brief Abstract class for objects implementing the functionality to switch the - * downlink bit rate. - * - * @author J. Meier - */ -class TxRateSetterIF { - public: - TxRateSetterIF(){}; - virtual ~TxRateSetterIF(){}; - - virtual ReturnValue_t setRate(uint32_t bitRate) = 0; -}; - -#endif /* LINUX_OBC_TXRATESETTERIF_H_ */ diff --git a/mission/tmtc/CCSDSHandler.cpp b/mission/tmtc/CCSDSHandler.cpp index bb31723b..35978627 100644 --- a/mission/tmtc/CCSDSHandler.cpp +++ b/mission/tmtc/CCSDSHandler.cpp @@ -1,6 +1,7 @@ #include "CCSDSHandler.h" #include +#include #include "fsfw/events/EventManagerIF.h" #include "fsfw/ipc/QueueFactory.h" @@ -10,14 +11,14 @@ #include "fsfw/serviceinterface/serviceInterfaceDefintions.h" CCSDSHandler::CCSDSHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination, - TxRateSetterIF* txRateSetterIF, GpioIF* gpioIF, gpioId_t enTxClock, + PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData) : SystemObject(objectId), ptmeId(ptmeId), tcDestination(tcDestination), parameterHelper(this), actionHelper(this, nullptr), - txRateSetterIF(txRateSetterIF), + ptmeConfig(ptmeConfig), gpioIF(gpioIF), enTxClock(enTxClock), enTxData(enTxData) { @@ -111,6 +112,15 @@ ReturnValue_t CCSDSHandler::initialize() { #endif return result; } + result = ptmeConfig->initialize(); + if (result != RETURN_OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + +#if OBSW_SYRLINKS_SIMULATED == 1 + ptmeConfig->invertTxClock(true); +#endif /* OBSW_SYRLINKS_SIMULATED == 1*/ + return result; } @@ -193,27 +203,43 @@ ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t ReturnValue_t result = RETURN_OK; switch (actionId) { case SET_LOW_RATE: { - result = txRateSetterIF->setRate(RATE_100KBPS); + result = ptmeConfig->setRate(RATE_100KBPS); break; } case SET_HIGH_RATE: { - result = txRateSetterIF->setRate(RATE_500KBPS); + result = ptmeConfig->setRate(RATE_500KBPS); break; } case ARBITRARY_RATE: { uint32_t bitrate = 0; SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG); - result = txRateSetterIF->setRate(bitrate); + result = ptmeConfig->setRate(bitrate); break; } case EN_TRANSMITTER: { enableTransmit(); return EXECUTION_FINISHED; } - case DIS_TRANSMITTER: { + case DISABLE_TRANSMITTER: { disableTransmit(); return EXECUTION_FINISHED; } + case ENABLE_TX_CLK_MANIPULATOR: { + result = ptmeConfig->configTxManipulator(true); + break; + } + case DISABLE_TX_CLK_MANIPULATOR: { + result = ptmeConfig->configTxManipulator(false); + break; + } + case UPDATE_ON_RISING_EDGE: { + result = ptmeConfig->invertTxClock(false); + break; + } + case UPDATE_ON_FALLING_EDGE: { + result = ptmeConfig->invertTxClock(true); + break; + } default: return COMMAND_NOT_IMPLEMENTED; } diff --git a/mission/tmtc/CCSDSHandler.h b/mission/tmtc/CCSDSHandler.h index 95c22a78..4f62102c 100644 --- a/mission/tmtc/CCSDSHandler.h +++ b/mission/tmtc/CCSDSHandler.h @@ -17,7 +17,7 @@ #include "fsfw/tmtcservices/AcceptsTelemetryIF.h" #include "fsfw_hal/common/gpio/GpioIF.h" #include "fsfw_hal/common/gpio/gpioDefinitions.h" -#include "linux/obc/TxRateSetterIF.h" +#include "linux/obc/PtmeConfig.h" /** * @brief This class handles the data exchange with the CCSDS IP cores implemented in the @@ -51,8 +51,7 @@ class CCSDSHandler : public SystemObject, * @param enTxData GPIO ID of RS485 tx data enable */ CCSDSHandler(object_id_t objectId, object_id_t ptmeId, object_id_t tcDestination, - TxRateSetterIF* txRateSetterIF, GpioIF* gpioIF, gpioId_t enTxClock, - gpioId_t enTxData); + PtmeConfig* ptmeConfig, GpioIF* gpioIF, gpioId_t enTxClock, gpioId_t enTxData); ~CCSDSHandler(); @@ -87,8 +86,14 @@ class CCSDSHandler : public SystemObject, static const ActionId_t SET_LOW_RATE = 0; static const ActionId_t SET_HIGH_RATE = 1; static const ActionId_t EN_TRANSMITTER = 2; - static const ActionId_t DIS_TRANSMITTER = 3; + static const ActionId_t DISABLE_TRANSMITTER = 3; static const ActionId_t ARBITRARY_RATE = 4; + static const ActionId_t ENABLE_TX_CLK_MANIPULATOR = 5; + static const ActionId_t DISABLE_TX_CLK_MANIPULATOR = 6; + // Will update data with respect to tx clock signal of cadu bitsream on rising edge + static const ActionId_t UPDATE_ON_RISING_EDGE = 7; + // Will update data with respect to tx clock signal of cadu bitsream on falling edge + static const ActionId_t UPDATE_ON_FALLING_EDGE = 8; // Syrlinks supports two bitrates (200 kbps and 1000 kbps) // Due to convolutional code added by the syrlinks the input frequency must be half the @@ -129,7 +134,7 @@ class CCSDSHandler : public SystemObject, MessageQueueId_t tcDistributorQueueId; - TxRateSetterIF* txRateSetterIF = nullptr; + PtmeConfig* ptmeConfig = nullptr; GpioIF* gpioIF = nullptr; gpioId_t enTxClock = gpio::NO_GPIO; diff --git a/tmtc b/tmtc index 598635ee..2e326da1 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 598635ee4fb1eb246980564ae9f3a0feb1f4da30 +Subproject commit 2e326da175bb0e806b460507ddcf2977cd1a2372