diff --git a/bsp_q7s/boardconfig/busConf.h b/bsp_q7s/boardconfig/busConf.h index e41ed093..5abd109b 100644 --- a/bsp_q7s/boardconfig/busConf.h +++ b/bsp_q7s/boardconfig/busConf.h @@ -17,6 +17,7 @@ static constexpr char UART_STAR_TRACKER_DEV[] = "/dev/ttyUL7"; static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio0"; static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio2"; static constexpr char UIO_PDEC_RAM[] = "/dev/uio3"; +static constexpr char UIO_PTME_CONFIG[] = "/dev/uio4"; namespace gpioNames { static constexpr char GYRO_0_ADIS_CS[] = "gyro_0_adis_chip_select"; @@ -69,7 +70,6 @@ static constexpr char RS485_EN_TX_DATA[] = "tx_data_enable_ltc2872"; static constexpr char RS485_EN_RX_CLOCK[] = "rx_clock_enable_ltc2872"; static constexpr char RS485_EN_RX_DATA[] = "rx_data_enable_ltc2872"; static constexpr char PDEC_RESET[] = "pdec_reset"; -static constexpr char BIT_RATE_SEL[] = "bit_rate_sel"; } // namespace gpioNames } // namespace q7s diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 7c089465..6db63f30 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -81,6 +81,7 @@ #include #include #include +#include ResetArgs resetArgsGnss0; ResetArgs resetArgsGnss1; @@ -943,17 +944,9 @@ void ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF) { ptme->addVcInterface(ccsds::VC2, vc2); ptme->addVcInterface(ccsds::VC3, vc3); - GpioCookie* gpioCookieRateSetter = new GpioCookie; - consumer.str(""); - consumer << "ptme rate setter"; - // Init to low -> default bit rate is low bit rate (200 kbps in downlink with syrlinks) - gpio = new GpiodRegularByLineName(q7s::gpioNames::BIT_RATE_SEL, consumer.str(), gpio::DIR_OUT, - gpio::LOW); - gpioCookieRateSetter->addGpio(gpioIds::BIT_RATE_SEL, gpio); - gpioComIF->addGpios(gpioCookieRateSetter); - - TxRateSetterIF* txRateSetterIF = new PtmeRateSetter(gpioIds::BIT_RATE_SEL, gpioComIF); - + PtmeAxiConfig* ptmeAxiConfig = new PtmeAxiConfig(objects::PTME_AXI_CONFIG, + std::string(q7s::UIO_PTME_CONFIG)); + TxRateSetterIF* txRateSetterIF = new PtmeRateSetter(objects::TX_RATE_SETTER, ptmeAxiConfig); CCSDSHandler* ccsdsHandler = new CCSDSHandler( objects::CCSDS_HANDLER, objects::PTME, objects::CCSDS_PACKET_DISTRIBUTOR, txRateSetterIF, gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA); diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 135259d6..e29a2013 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -90,7 +90,9 @@ enum commonObjects: uint32_t { PLOC_UPDATER = 0x44330000, PLOC_MEMORY_DUMPER = 0x44330001, - STR_HELPER = 0x44330002 + STR_HELPER = 0x44330002, + PTME_AXI_CONFIG = 44330003, + TX_RATE_SETTER = 44330004 }; } diff --git a/fsfw b/fsfw index 9b770602..c1e0bcee 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 9b77060295c9c32ebfc2e7cf6517eb2e66216191 +Subproject commit c1e0bcee6db652d6c474c87a4099e61ecf86b694 diff --git a/linux/obc/CMakeLists.txt b/linux/obc/CMakeLists.txt index 4119624c..d59a1a5f 100644 --- a/linux/obc/CMakeLists.txt +++ b/linux/obc/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(${TARGET_NAME} PUBLIC PdecHandler.cpp PdecConfig.cpp PtmeRateSetter.cpp + PtmeAxiConfig.cpp ) diff --git a/linux/obc/PtmeAxiConfig.cpp b/linux/obc/PtmeAxiConfig.cpp new file mode 100644 index 00000000..3ec45faa --- /dev/null +++ b/linux/obc/PtmeAxiConfig.cpp @@ -0,0 +1,49 @@ +#include +#include +#include "PtmeAxiConfig.h" +#include "fsfw/serviceinterface/ServiceInterface.h" + +PtmeAxiConfig::PtmeAxiConfig(object_id_t objectId, std::string configAxiUio) : + SystemObject(objectId), configAxiUio(configAxiUio) { + mutex = MutexFactory::instance()->createMutex(); + if (mutex == nullptr) { + sif::warning << "Failed to create mutex" << std::endl; + } +} + +PtmeAxiConfig::~PtmeAxiConfig() { +} + +ReturnValue_t PtmeAxiConfig::initialize() { + int fd = open(configAxiUio.c_str(), O_RDWR); + if (fd < 1) { + sif::warning << "PtmeAxiConfig::initialize: Invalid UIO device file" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + baseAddress = static_cast(mmap(NULL, MAP_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, + fd, 0)); + + if (baseAddress == MAP_FAILED) { + sif::warning << "PtmeAxiConfig::initialize: Failed to map uio address" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + 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 new file mode 100644 index 00000000..2b3e9d26 --- /dev/null +++ b/linux/obc/PtmeAxiConfig.h @@ -0,0 +1,40 @@ +#ifndef LINUX_OBC_PTMEAXICONFIG_H_ +#define LINUX_OBC_PTMEAXICONFIG_H_ + +#include +#include "fsfw/ipc/MutexIF.h" +#include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include "fsfw/objectmanager/SystemObject.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. + */ + PtmeAxiConfig(object_id_t objectId, std::string configAxiUio); + 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; + static const int MAP_SIZE = 0x1000; + + std::string configAxiUio; + 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.h b/linux/obc/PtmeConfig.h index b5b722ac..2dd7b7b2 100644 --- a/linux/obc/PtmeConfig.h +++ b/linux/obc/PtmeConfig.h @@ -25,7 +25,8 @@ 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 #endif /* LINUX_OBC_PTMECONFIG_H_ */ diff --git a/linux/obc/PtmeRateSetter.cpp b/linux/obc/PtmeRateSetter.cpp index b5a6ee1c..4a81c361 100644 --- a/linux/obc/PtmeRateSetter.cpp +++ b/linux/obc/PtmeRateSetter.cpp @@ -2,24 +2,40 @@ #include "fsfw/serviceinterface/ServiceInterface.h" -PtmeRateSetter::PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif) - : bitrateSel(bitrateSel), gpioif(gpioif) {} +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(BitRates rate) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + uint8_t rateVal = 0; switch (rate) { - case RATE_2000KHZ: - result = gpioif->pullHigh(bitrateSel); + case RATE_2000KBPS: + rateVal = static_cast(PtmeConfig::BIT_CLK_FREQ / 2000000 - 1); break; - case RATE_400KHZ: - result = gpioif->pullLow(bitrateSel); + case RATE_1000KBPS: + rateVal = static_cast(PtmeConfig::BIT_CLK_FREQ / 1000000 - 1); + break; + case RATE_500KBPS: + rateVal = static_cast(PtmeConfig::BIT_CLK_FREQ / 500000 - 1); + break; + case RATE_200KBPS: + rateVal = static_cast(PtmeConfig::BIT_CLK_FREQ / 200000 - 1); + break; + case RATE_100KBPS: + rateVal = static_cast(PtmeConfig::BIT_CLK_FREQ / 100000 - 1); break; default: - sif::debug << "PtmeRateSetter::setRate: Invalid rate" << std::endl; - result = HasReturnvaluesIF::RETURN_FAILED; - break; + sif::debug << "PtmeRateSetter::setRate: Unknown bit rate" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; } - return result; + return ptmeAxiConfig->writeCaduRateReg(rateVal); } diff --git a/linux/obc/PtmeRateSetter.h b/linux/obc/PtmeRateSetter.h index 14dfec4b..6b9d6c5a 100644 --- a/linux/obc/PtmeRateSetter.h +++ b/linux/obc/PtmeRateSetter.h @@ -3,36 +3,36 @@ #include "TxRateSetterIF.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" -#include "fsfw_hal/common/gpio/GpioIF.h" -#include "fsfw_hal/common/gpio/gpioDefinitions.h" +#include "linux/obc/PtmeAxiConfig.h" +#include "linux/obc/PtmeConfig.h" +#include "fsfw/objectmanager/SystemObject.h" /** - * @brief Class to set the downlink bit rate by using the cadu_rate_switcher implemented in - * the programmable logic. + * @brief Class to set the downlink bit rate by writing to the AXI configuration interface of the + * PTME IP core. * - * @details The cadu_rate_switcher module sets the input rate to the syrlinks transceiver either - * to 2000 kHz (bitrateSel = 1) or 400 kHz (bitrate = 0). + * @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: - /** - * @brief Constructor - * - * @param bitrateSel GPIO ID of the GPIO connected to the bitrate_sel input of the - * cadu_rate_switcher. - * @param gpioif GPIO interface to drive the bitrateSel GPIO - */ - PtmeRateSetter(gpioId_t bitrateSel, GpioIF* gpioif); - virtual ~PtmeRateSetter(); +class PtmeRateSetter: public TxRateSetterIF, public SystemObject { +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 setRate(BitRates rate); + virtual ReturnValue_t initialize() override; + virtual ReturnValue_t setRate(BitRates rate); - private: - gpioId_t bitrateSel = gpio::NO_GPIO; +private: - GpioIF* gpioif = nullptr; + PtmeAxiConfig* ptmeAxiConfig = nullptr; }; #endif /* LINUX_OBC_PTMERATESETTER_H_ */ diff --git a/linux/obc/TxRateSetterIF.h b/linux/obc/TxRateSetterIF.h index 1eaded33..6090825f 100644 --- a/linux/obc/TxRateSetterIF.h +++ b/linux/obc/TxRateSetterIF.h @@ -3,7 +3,14 @@ #include "fsfw/returnvalues/HasReturnvaluesIF.h" -enum BitRates : uint32_t { RATE_2000KHZ, RATE_400KHZ }; +enum BitRates : uint32_t { + RATE_2000KBPS, + RATE_1000KBPS, + RATE_500KBPS, + RATE_400KBPS, + RATE_200KBPS, + RATE_100KBPS +}; /** * @brief Abstract class for objects implementing the functionality to switch the diff --git a/mission/tmtc/CCSDSHandler.cpp b/mission/tmtc/CCSDSHandler.cpp index ba34d273..3747b42d 100644 --- a/mission/tmtc/CCSDSHandler.cpp +++ b/mission/tmtc/CCSDSHandler.cpp @@ -191,11 +191,11 @@ ReturnValue_t CCSDSHandler::executeAction(ActionId_t actionId, MessageQueueId_t const uint8_t* data, size_t size) { switch (actionId) { case SET_LOW_RATE: { - txRateSetterIF->setRate(BitRates::RATE_400KHZ); + txRateSetterIF->setRate(BitRates::RATE_100KBPS); return EXECUTION_FINISHED; } case SET_HIGH_RATE: { - txRateSetterIF->setRate(BitRates::RATE_2000KHZ); + txRateSetterIF->setRate(BitRates::RATE_500KBPS); return EXECUTION_FINISHED; } case EN_TRANSMITTER: { diff --git a/mission/tmtc/CCSDSHandler.h b/mission/tmtc/CCSDSHandler.h index 3090c24e..aedeccff 100644 --- a/mission/tmtc/CCSDSHandler.h +++ b/mission/tmtc/CCSDSHandler.h @@ -23,6 +23,9 @@ * @brief This class handles the data exchange with the CCSDS IP cores implemented in the * programmable logic of the Q7S. * + * @details After reboot default CADU bitrate is always set to 100 kbps (results in downlink rate + * of 200 kbps due to convolutional code added by syrlinks transceiver) + * * @author J. Meier */ class CCSDSHandler : public SystemObject, diff --git a/tmtc b/tmtc index 6f24d6a8..580ac8b2 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 6f24d6a83995ca7a895c17a77a00bceac4d7f141 +Subproject commit 580ac8b2d7e73aa860f3de55066187d7684d2d64