Merge remote-tracking branch 'origin/develop' into mueller/master

This commit is contained in:
Robin Müller 2021-05-17 16:02:04 +02:00
commit e2a9bed4d8
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
35 changed files with 2910 additions and 292 deletions

View File

@ -266,7 +266,7 @@ To transfer files from the local machine to the Q7S, use port forwarding
ssh -L 1535:192.168.133.10:22 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5 ssh -L 1535:192.168.133.10:22 eive@2001:7c0:2018:1099:babe:0:e1fe:f1a5
``` ```
Then you can copy an `example` file like this An `example` file can be copied like this
```sh ```sh
scp -P 1535 example root@localhost:/tmp scp -P 1535 example root@localhost:/tmp
@ -277,7 +277,7 @@ Copying a file from Q7S to flatsat PC
scp -P 22 root@192.168.133.10:/tmp/kernel-config /tmp scp -P 22 root@192.168.133.10:/tmp/kernel-config /tmp
```` ````
From a windows machine files can be copied with putty tools From a windows machine files can be copied with putty tools (note: use IPv4 address)
```` ````
pscp -scp -P 22 eive@192.168.199.227:</directory-to-example-file/>/example-file </windows-machine-path/> pscp -scp -P 22 eive@192.168.199.227:</directory-to-example-file/>/example-file </windows-machine-path/>
```` ````
@ -579,4 +579,23 @@ to install the required GPIO libraries before cloning the system root folder.
When using Eclipse, there are two special build variables in the project properties When using Eclipse, there are two special build variables in the project properties
&rarr; C/C++ Build &rarr; Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set &rarr; C/C++ Build &rarr; Build Variables called `Q7S_SYSROOT` or `RPI_SYSROOT`. You can set
the sysroot path in those variables to get any additional includes like `gpiod.h` in the the sysroot path in those variables to get any additional includes like `gpiod.h` in the
Eclipse indexer. Eclipse indexer.
## Xilinx UARTLIE
Get info about ttyUL* devices
````
cat /proc/tty/driver
````
## I2C
Getting information about I2C device
````
ls /sys/class/i2c-dev/i2c-0/device/device/driver
````
This shows the memory mapping of /dev/i2c-0
## Useful Q7S Linux Commands
Rebooting currently running image:
````
xsc_boot_copy -r
````

View File

@ -135,6 +135,8 @@ void initmission::initTasks() {
initmission::printAddObjectError("PUS_17", objects::PUS_SERVICE_17_TEST); initmission::printAddObjectError("PUS_17", objects::PUS_SERVICE_17_TEST);
} }
#if TE0720 == 0
//TODO: Add handling of missed deadlines //TODO: Add handling of missed deadlines
/* Polling Sequence Table Default */ /* Polling Sequence Table Default */
#if Q7S_ADD_SPI_TEST == 0 #if Q7S_ADD_SPI_TEST == 0
@ -147,14 +149,22 @@ void initmission::initTasks() {
} }
#endif #endif
#if TE0720 == 0
FixedTimeslotTaskIF* gomSpacePstTask = factory-> FixedTimeslotTaskIF* gomSpacePstTask = factory->
createFixedTimeslotTask("GS_PST_TASK", 50, createFixedTimeslotTask("GS_PST_TASK", 50,
PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 3.0, missedDeadlineFunc); PeriodicTaskIF::MINIMUM_STACK_SIZE*8, 1.0, missedDeadlineFunc);
result = pst::gomspacePstInit(gomSpacePstTask); result = pst::gomspacePstInit(gomSpacePstTask);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl;
} }
#else
FixedTimeslotTaskIF * pollingSequenceTaskTE0720 = factory->createFixedTimeslotTask(
"PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0,
missedDeadlineFunc);
result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720);
if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "InitMission::initTasks: Creating TE0720 PST failed!" << std::endl;
}
#endif #endif
#if OBSW_ADD_TEST_CODE == 1 #if OBSW_ADD_TEST_CODE == 1
@ -184,12 +194,11 @@ void initmission::initTasks() {
udpBridgeTask->startTask(); udpBridgeTask->startTask();
udpPollingTask->startTask(); udpPollingTask->startTask();
#if TE0720 == 0 #if TE0720 == 0 && Q7S_ADD_SPI_TEST == 0
gomSpacePstTask->startTask(); gomSpacePstTask->startTask();
#endif
#if Q7S_ADD_SPI_TEST == 0
pollingSequenceTableTaskDefault->startTask(); pollingSequenceTableTaskDefault->startTask();
#elif TE0720 == 1 && Q7S_ADD_SPI_TEST == 0
pollingSequenceTaskTE0720->startTask();
#endif #endif
pusVerification->startTask(); pusVerification->startTask();

View File

@ -20,14 +20,20 @@
#include <mission/devices/Tmp1075Handler.h> #include <mission/devices/Tmp1075Handler.h>
#include <mission/devices/Max31865PT1000Handler.h> #include <mission/devices/Max31865PT1000Handler.h>
#include <mission/devices/IMTQHandler.h> #include <mission/devices/IMTQHandler.h>
#include <mission/devices/devicedefinitions/Max31865Definitions.h>
#include <mission/devices/SyrlinksHkHandler.h> #include <mission/devices/SyrlinksHkHandler.h>
#include <mission/devices/MGMHandlerLIS3MDL.h> #include <mission/devices/MGMHandlerLIS3MDL.h>
#include <mission/devices/MGMHandlerRM3100.h> #include <mission/devices/MGMHandlerRM3100.h>
#include <mission/devices/GyroL3GD20Handler.h> #include <mission/devices/GyroL3GD20Handler.h>
#include <mission/devices/PlocHandler.h>
#include <mission/devices/RadiationSensorHandler.h>
#include <mission/devices/SusHandler.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h> #include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include <mission/devices/devicedefinitions/SyrlinksDefinitions.h> #include <mission/devices/devicedefinitions/SyrlinksDefinitions.h>
#include <mission/devices/devicedefinitions/PlocDefinitions.h>
#include <mission/devices/devicedefinitions/RadSensorDefinitions.h>
#include <mission/devices/devicedefinitions/Max31865Definitions.h>
#include <mission/devices/devicedefinitions/SusDefinitions.h>
#include <mission/utility/TmFunnel.h> #include <mission/utility/TmFunnel.h>
#include <linux/csp/CspCookie.h> #include <linux/csp/CspCookie.h>
@ -99,19 +105,17 @@ void ObjectFactory::produce(){
new UartComIF(objects::UART_COM_IF); new UartComIF(objects::UART_COM_IF);
#if Q7S_ADD_SPI_TEST == 0 #if Q7S_ADD_SPI_TEST == 0
new SpiComIF(objects::SPI_COM_IF, gpioComIF); new SpiComIF(objects::SPI_COM_IF, gpioComIF);
#endif #endif /* Q7S_ADD_SPI_TEST == 0 */
/* Temperature sensors */ /* Temperature sensors */
Tmp1075Handler* tmp1075Handler_1 = new Tmp1075Handler( Tmp1075Handler* tmp1075Handler_1 = new Tmp1075Handler(
objects::TMP1075_HANDLER_1, objects::I2C_COM_IF, objects::TMP1075_HANDLER_1, objects::I2C_COM_IF,
i2cCookieTmp1075tcs1); i2cCookieTmp1075tcs1);
tmp1075Handler_1->setStartUpImmediately(); (void) tmp1075Handler_1;
Tmp1075Handler* tmp1075Handler_2 = new Tmp1075Handler( Tmp1075Handler* tmp1075Handler_2 = new Tmp1075Handler(
objects::TMP1075_HANDLER_2, objects::I2C_COM_IF, objects::TMP1075_HANDLER_2, objects::I2C_COM_IF,
i2cCookieTmp1075tcs2); i2cCookieTmp1075tcs2);
tmp1075Handler_2->setStartUpImmediately(); (void) tmp1075Handler_2;
GpioCookie* heaterGpiosCookie = new GpioCookie;
#if TE0720 == 0 #if TE0720 == 0
CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_LENGTH, CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_LENGTH,
@ -147,16 +151,127 @@ void ObjectFactory::produce(){
(void) pdu2handler; (void) pdu2handler;
(void) acuhandler; (void) acuhandler;
/* Adding gpios for chip select decoding to the gpioComIf */
gpioCallbacks::initSpiCsDecoder(gpioComIF);
GpioCookie* gpioCookieRadSensor = new GpioCookie;
GpiodRegular* chipSelectRadSensor = new GpiodRegular(std::string("gpiochip5"), 19,
std::string("Chip Select Radiation Sensor"), gpio::OUT, 1);
gpioCookieRadSensor->addGpio(gpioIds::CS_RAD_SENSOR, chipSelectRadSensor);
gpioComIF->addGpios(gpioCookieRadSensor);
SpiCookie* spiCookieRadSensor = new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR,
std::string("/dev/spidev2.0"), RAD_SENSOR::READ_SIZE, spi::DEFAULT_MAX_1227_MODE,
spi::DEFAULT_MAX_1227_SPEED);
new RadiationSensorHandler(objects::RAD_SENSOR, objects::SPI_COM_IF, spiCookieRadSensor);
GpioCookie* gpioCookieSus = new GpioCookie();
GpioCallback* susgpio = new GpioCallback(std::string("Chip select SUS 1"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_1, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 2"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_2, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 3"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_3, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 4"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_4, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 5"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_5, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 6"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_6, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 7"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_7, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 8"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_8, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 9"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_9, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 10"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_10, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 11"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_11, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 12"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_12, susgpio);
susgpio = new GpioCallback(std::string("Chip select SUS 13"), gpio::OUT, 1,
&gpioCallbacks::spiCsDecoderCallback, gpioComIF);
gpioCookieSus->addGpio(gpioIds::CS_SUS_13, susgpio);
gpioComIF->addGpios(gpioCookieSus);
SpiCookie* spiCookieSus1 = new SpiCookie(addresses::SUS_1, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus2 = new SpiCookie(addresses::SUS_2, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus3 = new SpiCookie(addresses::SUS_3, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus4 = new SpiCookie(addresses::SUS_4, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus5 = new SpiCookie(addresses::SUS_5, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus6 = new SpiCookie(addresses::SUS_6, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus7 = new SpiCookie(addresses::SUS_7, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus8 = new SpiCookie(addresses::SUS_8, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus9 = new SpiCookie(addresses::SUS_9, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus10 = new SpiCookie(addresses::SUS_10, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus11 = new SpiCookie(addresses::SUS_11, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus12 = new SpiCookie(addresses::SUS_12, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
SpiCookie* spiCookieSus13 = new SpiCookie(addresses::SUS_13, gpio::NO_GPIO,
std::string("/dev/spidev2.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
SUS::MAX1227_SPI_FREQ);
new SusHandler(objects::SUS_1, objects::SPI_COM_IF, spiCookieSus1, gpioComIF, gpioIds::CS_SUS_1);
new SusHandler(objects::SUS_2, objects::SPI_COM_IF, spiCookieSus2, gpioComIF, gpioIds::CS_SUS_2);
new SusHandler(objects::SUS_3, objects::SPI_COM_IF, spiCookieSus3, gpioComIF, gpioIds::CS_SUS_3);
new SusHandler(objects::SUS_4, objects::SPI_COM_IF, spiCookieSus4, gpioComIF, gpioIds::CS_SUS_4);
new SusHandler(objects::SUS_5, objects::SPI_COM_IF, spiCookieSus5, gpioComIF, gpioIds::CS_SUS_5);
new SusHandler(objects::SUS_6, objects::SPI_COM_IF, spiCookieSus6, gpioComIF, gpioIds::CS_SUS_6);
new SusHandler(objects::SUS_7, objects::SPI_COM_IF, spiCookieSus7, gpioComIF, gpioIds::CS_SUS_7);
new SusHandler(objects::SUS_8, objects::SPI_COM_IF, spiCookieSus8, gpioComIF, gpioIds::CS_SUS_8);
new SusHandler(objects::SUS_9, objects::SPI_COM_IF, spiCookieSus9, gpioComIF, gpioIds::CS_SUS_9);
new SusHandler(objects::SUS_10, objects::SPI_COM_IF, spiCookieSus10, gpioComIF, gpioIds::CS_SUS_10);
new SusHandler(objects::SUS_11, objects::SPI_COM_IF, spiCookieSus11, gpioComIF, gpioIds::CS_SUS_11);
new SusHandler(objects::SUS_12, objects::SPI_COM_IF, spiCookieSus12, gpioComIF, gpioIds::CS_SUS_12);
new SusHandler(objects::SUS_13, objects::SPI_COM_IF, spiCookieSus13, gpioComIF, gpioIds::CS_SUS_13);
#if OBSW_ADD_ACS_BOARD == 1 #if OBSW_ADD_ACS_BOARD == 1
GpioCookie* gpioCookieAcsBoard = new GpioCookie(); GpioCookie* gpioCookieAcsBoard = new GpioCookie();
GpiodRegular* gpio = nullptr; GpiodRegular* gpio = nullptr;
gpio = new GpiodRegular(std::string("gpiochip5"), 1, std::string("CS_GYRO_1_ADIS"), gpio = new GpiodRegular(std::string("gpiochip5"), 1, std::string("CS_GYRO_0_ADIS"),
gpio::OUT, gpio::HIGH); gpio::OUT, gpio::HIGH);
gpioCookieAcsBoard->addGpio(gpioIds::GYRO_0_ADIS_CS, gpio); gpioCookieAcsBoard->addGpio(gpioIds::GYRO_0_ADIS_CS, gpio);
gpio = new GpiodRegular(std::string("gpiochip5"), 7, std::string("CS_GYRO_2_L3G"), gpio = new GpiodRegular(std::string("gpiochip5"), 7, std::string("CS_GYRO_1_L3G"),
gpio::OUT, gpio::HIGH); gpio::OUT, gpio::HIGH);
gpioCookieAcsBoard->addGpio(gpioIds::GYRO_1_L3G_CS, gpio); gpioCookieAcsBoard->addGpio(gpioIds::GYRO_1_L3G_CS, gpio);
gpio = new GpiodRegular(std::string("gpiochip5"), 3, std::string("CS_GYRO_3_L3G"), gpio = new GpiodRegular(std::string("gpiochip5"), 3, std::string("CS_GYRO_2_L3G"),
gpio::OUT, gpio::HIGH); gpio::OUT, gpio::HIGH);
gpioCookieAcsBoard->addGpio(gpioIds::GYRO_2_L3G_CS, gpio); gpioCookieAcsBoard->addGpio(gpioIds::GYRO_2_L3G_CS, gpio);
@ -164,7 +279,7 @@ void ObjectFactory::produce(){
gpio::OUT, gpio::HIGH); gpio::OUT, gpio::HIGH);
gpioCookieAcsBoard->addGpio(gpioIds::MGM_0_LIS3_CS, gpio); gpioCookieAcsBoard->addGpio(gpioIds::MGM_0_LIS3_CS, gpio);
gpio = new GpiodRegular(std::string("gpiochip5"), 17, std::string("CS_MGM_1_RM3100_A"), gpio = new GpiodRegular(std::string("gpiochip5"), 16, std::string("CS_MGM_1_RM3100_A"),
gpio::OUT, gpio::HIGH); gpio::OUT, gpio::HIGH);
gpioCookieAcsBoard->addGpio(gpioIds::MGM_1_RM3100_CS, gpio); gpioCookieAcsBoard->addGpio(gpioIds::MGM_1_RM3100_CS, gpio);
@ -197,13 +312,31 @@ void ObjectFactory::produce(){
objects::SPI_COM_IF, spiCookie); objects::SPI_COM_IF, spiCookie);
mgmRm3100Handler->setStartUpImmediately(); mgmRm3100Handler->setStartUpImmediately();
spiCookie = new SpiCookie(addresses::MGM_3_RM3100, gpioIds::MGM_3_RM3100_CS, spiDev,
RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED);
mgmRm3100Handler = new MGMHandlerRM3100(objects::MGM_3_RM3100_HANDLER,
objects::SPI_COM_IF, spiCookie);
mgmRm3100Handler->setStartUpImmediately();
//TODO: Adis Gyro (Gyro 0 Side A)
/* Gyro 1 Side A */
spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, spiDev, spiCookie = new SpiCookie(addresses::GYRO_1_L3G, gpioIds::GYRO_1_L3G_CS, spiDev,
L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF, auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF,
spiCookie); spiCookie);
gyroL3gHandler->setStartUpImmediately(); gyroL3gHandler->setStartUpImmediately();
/* Gyro 2 Side B */
spiCookie = new SpiCookie(addresses::GYRO_2_L3G, gpioIds::GYRO_2_L3G_CS, spiDev,
L3GD20H::MAX_BUFFER_SIZE, spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED);
gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_2_L3G_HANDLER, objects::SPI_COM_IF,
spiCookie);
gyroL3gHandler->setStartUpImmediately();
#endif #endif
GpioCookie* heaterGpiosCookie = new GpioCookie;
/* Pin H2-11 on stack connector */ /* Pin H2-11 on stack connector */
GpiodRegular* gpioConfigHeater0 = new GpiodRegular(std::string("gpiochip7"), 6, GpiodRegular* gpioConfigHeater0 = new GpiodRegular(std::string("gpiochip7"), 6,
std::string("Heater0"), gpio::OUT, 0); std::string("Heater0"), gpio::OUT, 0);
@ -406,17 +539,25 @@ void ObjectFactory::produce(){
#endif /* Q7S_ADD_RTD_DEVICES == 1 */ #endif /* Q7S_ADD_RTD_DEVICES == 1 */
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE,
std::string("/dev/i2c-0"));
IMTQHandler* imtqHandler = new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie);
// imtqHandler->setStartUpImmediately();
(void) imtqHandler;
UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyUL3"), 115200,
PLOC::MAX_REPLY_SIZE);
PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF,
plocUartCookie);
// plocHandler->setStartUpImmediately();
(void) plocHandler;
#endif /* TE0720 == 0 */ #endif /* TE0720 == 0 */
new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE, new UdpTmTcBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE,
objects::TC_STORE); objects::TC_STORE);
new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE); new UdpTcPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, IMTQ::MAX_REPLY_SIZE,
std::string("/dev/i2c-0"));
IMTQHandler* imtqHandler = new IMTQHandler(objects::IMTQ_HANDLER, objects::I2C_COM_IF, imtqI2cCookie);
imtqHandler->setStartUpImmediately();
#if TE0720 == 1 && TEST_LIBGPIOD == 1 #if TE0720 == 1 && TEST_LIBGPIOD == 1
/* Configure MIO0 as input */ /* Configure MIO0 as input */
GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0, GpiodRegular gpioConfigMio0(std::string("gpiochip0"), 0,
@ -424,13 +565,55 @@ void ObjectFactory::produce(){
GpioCookie* gpioCookie = new GpioCookie; GpioCookie* gpioCookie = new GpioCookie;
gpioCookie->addGpio(gpioIds::TEST_ID_0, gpioConfigMio0); gpioCookie->addGpio(gpioIds::TEST_ID_0, gpioConfigMio0);
new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie); new LibgpiodTest(objects::LIBGPIOD_TEST, objects::GPIO_IF, gpioCookie);
#elif TE0720 == 1 #endif
#if TE0720 == 1 && TEST_SUS_HANDLER == 1
GpioCookie* gpioCookieSus = new GpioCookie;
GpiodRegular* chipSelectSus = new GpiodRegular(std::string("gpiochip1"), 9,
std::string("Chip Select Sus Sensor"), gpio::OUT, 1);
gpioCookieSus->addGpio(gpioIds::CS_SUS_1, chipSelectSus);
gpioComIF->addGpios(gpioCookieSus);
SpiCookie* spiCookieSus = new SpiCookie(addresses::SUS_1, std::string("/dev/spidev1.0"),
SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE, spi::DEFAULT_MAX_1227_SPEED);
SusHandler* sus1 = new SusHandler(objects::SUS_1, objects::SPI_COM_IF, spiCookieSus, gpioComIF,
gpioIds::CS_SUS_1);
sus1->setStartUpImmediately();
#endif
#if TE0720 == 1 && TEST_RADIATION_SENSOR_HANDLER == 1
GpioCookie* gpioCookieRadSensor = new GpioCookie;
GpiodRegular* chipSelectRadSensor = new GpiodRegular(std::string("gpiochip1"), 0,
std::string("Chip select radiation sensor"), gpio::OUT, 1);
gpioCookieRadSensor->addGpio(gpioIds::CS_RAD_SENSOR, chipSelectRadSensor);
gpioComIF->addGpios(gpioCookieRadSensor);
SpiCookie* spiCookieRadSensor = new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR,
std::string("/dev/spidev1.0"), SUS::MAX_CMD_SIZE, spi::DEFAULT_MAX_1227_MODE,
spi::DEFAULT_MAX_1227_SPEED);
RadiationSensorHandler* radSensor = new RadiationSensorHandler(objects::RAD_SENSOR,
objects::SPI_COM_IF, spiCookieRadSensor);
radSensor->setStartUpImmediately();
#endif
#if TE0720 == 1 && TEST_PLOC_HANDLER == 1
UartCookie* plocUartCookie = new UartCookie(std::string("/dev/ttyPS1"), 115200,
PLOC::MAX_REPLY_SIZE);
/* Testing PlocHandler on TE0720-03-1CFA */
PlocHandler* plocHandler = new PlocHandler(objects::PLOC_HANDLER, objects::UART_COM_IF,
plocUartCookie);
plocHandler->setStartUpImmediately();
#endif
#if TE0720 == 1 && TE0720_HEATER_TEST == 1
/* Configuration for MIO0 on TE0720-03-1CFA */ /* Configuration for MIO0 on TE0720-03-1CFA */
GpiodRegular gpioConfigForDummyHeater(std::string("gpiochip0"), 0, GpiodRegular* heaterGpio = new GpiodRegular(std::string("gpiochip0"), 0, std::string("MIO0"), gpio::IN, 0);
std::string("Heater0"), gpio::OUT, 0); GpioCookie* gpioCookie = new GpioCookie;
heaterGpiosCookie->addGpio(gpioIds::HEATER_0, gpioConfigForDummyHeater); gpioCookie->addGpio(gpioIds::HEATER_0, heaterGpio);
new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, gpioCookie, objects::PCDU_HANDLER,
objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN); pcduSwitches::TCS_BOARD_8V_HEATER_IN);
#endif #endif
#if Q7S_ADD_SPI_TEST == 1 #if Q7S_ADD_SPI_TEST == 1

View File

@ -58,8 +58,9 @@ ReturnValue_t HeaterHandler::initialize() {
if(mainLineSwitcherObjectId != objects::NO_OBJECT) { if(mainLineSwitcherObjectId != objects::NO_OBJECT) {
mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId); mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId);
if (mainLineSwitcher == nullptr) { if (mainLineSwitcher == nullptr) {
sif::error << "HeaterHandler::initialize: Main line switcher failed to fetch object" sif::error
<< "from object ID." << std::endl; << "HeaterHandler::initialize: Failed to get main line switcher. Make sure "
<< "main line switcher object is initialized." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
} }

View File

@ -10,31 +10,32 @@ namespace gpioCallbacks {
GpioIF* gpioComInterface; GpioIF* gpioComInterface;
void initTcsBoardDecoder(GpioIF* gpioComIF) { void initSpiCsDecoder(GpioIF* gpioComIF) {
ReturnValue_t result; ReturnValue_t result;
if (gpioComIF == nullptr) { if (gpioComIF == nullptr) {
sif::debug << "initTcsBoardDecoder: Invalid gpioComIF" << std::endl; sif::debug << "initSpiCsDecoder: Invalid gpioComIF" << std::endl;
return; return;
} }
gpioComInterface = gpioComIF; gpioComInterface = gpioComIF;
GpioCookie* spiMuxGpios = new GpioCookie; GpioCookie* spiMuxGpios = new GpioCookie;
/**
* Initial values of the spi mux gpios can all be set to an arbitrary value expect for spi mux /** Setting mux bit 1 to low will disable IC21 on the interface board */
* bit 1. Setting spi mux bit 1 to high will pull all decoder outputs to high voltage level.
*/
GpiodRegular* spiMuxBit1 = new GpiodRegular(std::string("gpiochip7"), 13, GpiodRegular* spiMuxBit1 = new GpiodRegular(std::string("gpiochip7"), 13,
std::string("SPI Mux Bit 1"), gpio::OUT, 1); std::string("SPI Mux Bit 1"), gpio::OUT, 0);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_1, spiMuxBit1); spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_1, spiMuxBit1);
/** Setting mux bit 2 to low disables IC1 on the TCS board */
GpiodRegular* spiMuxBit2 = new GpiodRegular(std::string("gpiochip7"), 14, GpiodRegular* spiMuxBit2 = new GpiodRegular(std::string("gpiochip7"), 14,
std::string("SPI Mux Bit 2"), gpio::OUT, 0); std::string("SPI Mux Bit 2"), gpio::OUT, 0);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_2, spiMuxBit2); spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_2, spiMuxBit2);
/** Setting mux bit 3 to low disables IC2 on the TCS board and IC22 on the interface board */
GpiodRegular* spiMuxBit3 = new GpiodRegular(std::string("gpiochip7"), 15, GpiodRegular* spiMuxBit3 = new GpiodRegular(std::string("gpiochip7"), 15,
std::string("SPI Mux Bit 3"), gpio::OUT, 0); std::string("SPI Mux Bit 3"), gpio::OUT, 0);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_3, spiMuxBit3); spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_3, spiMuxBit3);
/** The following gpios can take arbitrary initial values */
GpiodRegular* spiMuxBit4 = new GpiodRegular(std::string("gpiochip7"), 16, GpiodRegular* spiMuxBit4 = new GpiodRegular(std::string("gpiochip7"), 16,
std::string("SPI Mux Bit 4"), gpio::OUT, 0); std::string("SPI Mux Bit 4"), gpio::OUT, 0);
spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_4, spiMuxBit4); spiMuxGpios->addGpio(gpioIds::SPI_MUX_BIT_4, spiMuxBit4);
@ -47,175 +48,261 @@ void initTcsBoardDecoder(GpioIF* gpioComIF) {
result = gpioComInterface->addGpios(spiMuxGpios); result = gpioComInterface->addGpios(spiMuxGpios);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "initTcsBoardDecoder: Failed to add mux bit gpios to gpioComIF" sif::error << "initSpiCsDecoder: Failed to add mux bit gpios to gpioComIF"
<< std::endl; << std::endl;
return; return;
} }
} }
void tcsBoardDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void spiCsDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value,
void* args) { void* args) {
if (gpioComInterface == nullptr) { if (gpioComInterface == nullptr) {
sif::debug << "tcsBoardDecoderCallback: No gpioComIF specified. Call initTcsBoardDecoder " sif::debug << "spiCsDecoderCallback: No gpioComIF specified. Call initSpiCsDecoder "
<< "to specify gpioComIF" << std::endl; << "to specify gpioComIF" << std::endl;
return; return;
} }
/* Read is not supported by the callback function */ /* Reading is not supported by the callback function */
if (gpioOp == gpio::GpioOperation::READ) { if (gpioOp == gpio::GpioOperation::READ) {
return; return;
} }
if (value == 1) { if (value == 1) {
/* This will pull all 16 decoder outputs to high */ disableAllDecoder();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
} }
else if (value == 0) { else if (value == 0) {
switch (gpioId) { switch (gpioId) {
case(gpioIds::RTD_IC3): { case(gpioIds::RTD_IC3): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY7();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC4): { case(gpioIds::RTD_IC4): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY6();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC5): { case(gpioIds::RTD_IC5): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY5();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC6): { case(gpioIds::RTD_IC6): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY4();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC7): { case(gpioIds::RTD_IC7): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY3();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC8): { case(gpioIds::RTD_IC8): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY2();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC9): { case(gpioIds::RTD_IC9): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY1();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC10): { case(gpioIds::RTD_IC10): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2); selectY0();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC11): { case(gpioIds::RTD_IC11): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY7();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC12): { case(gpioIds::RTD_IC12): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY6();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC13): { case(gpioIds::RTD_IC13): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY5();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC14): { case(gpioIds::RTD_IC14): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY4();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC15): { case(gpioIds::RTD_IC15): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY3();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC16): { case(gpioIds::RTD_IC16): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY2();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC17): { case(gpioIds::RTD_IC17): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY1();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
break; break;
} }
case(gpioIds::RTD_IC18): { case(gpioIds::RTD_IC18): {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1); enableDecoderTcsIc2();
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3); selectY0();
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4); break;
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5); }
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6); case(gpioIds::CS_SUS_1): {
enableDecoderInterfaceBoardIc1();
selectY0();
break;
}
case(gpioIds::CS_SUS_2): {
enableDecoderInterfaceBoardIc1();
selectY1();
break;
}
case(gpioIds::CS_SUS_3): {
enableDecoderInterfaceBoardIc2();
selectY0();
break;
}
case(gpioIds::CS_SUS_4): {
enableDecoderInterfaceBoardIc2();
selectY1();
break;
}
case(gpioIds::CS_SUS_5): {
enableDecoderInterfaceBoardIc2();
selectY2();
break;
}
case(gpioIds::CS_SUS_6): {
enableDecoderInterfaceBoardIc1();
selectY2();
break;
}
case(gpioIds::CS_SUS_7): {
enableDecoderInterfaceBoardIc1();
selectY3();
break;
}
case(gpioIds::CS_SUS_8): {
enableDecoderInterfaceBoardIc2();
selectY3();
break;
}
case(gpioIds::CS_SUS_9): {
enableDecoderInterfaceBoardIc1();
selectY4();
break;
}
case(gpioIds::CS_SUS_10): {
enableDecoderInterfaceBoardIc1();
selectY5();
break;
}
case(gpioIds::CS_SUS_11): {
enableDecoderInterfaceBoardIc2();
selectY4();
break;
}
case(gpioIds::CS_SUS_12): {
enableDecoderInterfaceBoardIc2();
selectY5();
break;
}
case(gpioIds::CS_SUS_13): {
enableDecoderInterfaceBoardIc1();
selectY6();
break; break;
} }
default: default:
sif::debug << "tcsBoardDecoderCallback: Invalid gpioid " << gpioId << std::endl; sif::debug << "spiCsDecoderCallback: Invalid gpio id " << gpioId << std::endl;
} }
} }
else { else {
sif::debug << "tcsBoardDecoderCallback: Invalid value. Must be 0 or 1" << std::endl; sif::debug << "spiCsDecoderCallback: Invalid value. Must be 0 or 1" << std::endl;
} }
} }
void enableDecoderTcsIc1() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
}
void enableDecoderTcsIc2() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
}
void enableDecoderInterfaceBoardIc1() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
}
void enableDecoderInterfaceBoardIc2() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_3);
}
void selectY0() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
}
void selectY1() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
}
void selectY2() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
}
void selectY3() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_6);
}
void selectY4() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
}
void selectY5() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
}
void selectY6() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
}
void selectY7() {
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_4);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_5);
gpioComInterface->pullHigh(gpioIds::SPI_MUX_BIT_6);
}
void disableAllDecoder() {
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_1);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_2);
gpioComInterface->pullLow(gpioIds::SPI_MUX_BIT_3);
}
} }

View File

@ -9,15 +9,54 @@ namespace gpioCallbacks {
/** /**
* @brief This function initializes the GPIOs used to control the SN74LVC138APWR decoders on * @brief This function initializes the GPIOs used to control the SN74LVC138APWR decoders on
* the TCS Board. * the TCS Board and the interface board.
*/ */
void initTcsBoardDecoder(GpioIF* gpioComIF); void initSpiCsDecoder(GpioIF* gpioComIF);
/** /**
* @brief This function implements the decoding to multiply gpios by using the two decoder * @brief This function implements the decoding to multiply gpios by using the decoder
* chips SN74LVC138APWR on the TCS board. * chips SN74LVC138APWR on the TCS board and the interface board.
*/ */
void tcsBoardDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args); void spiCsDecoderCallback(gpioId_t gpioId, gpio::GpioOperation gpioOp, int value, void* args);
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the TCS board which is named to IC1 in the schematic.
*/
void enableDecoderTcsIc1();
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the TCS board which is named to IC2 in the schematic.
*/
void enableDecoderTcsIc2();
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the inteface board board which is named to IC21 in the schematic.
*/
void enableDecoderInterfaceBoardIc1();
/**
* @brief This function sets mux bits 1-3 to a state which will only enable the decoder
* on the inteface board board which is named to IC22 in the schematic.
*/
void enableDecoderInterfaceBoardIc2();
/**
* @brief This function disables all decoder.
*/
void disableAllDecoder();
/** The following functions enable the appropriate channel of the currently enabled decoder */
void selectY0();
void selectY1();
void selectY2();
void selectY3();
void selectY4();
void selectY5();
void selectY6();
void selectY7();
} }
#endif /* LINUX_GPIO_GPIOCALLBACKS_H_ */ #endif /* LINUX_GPIO_GPIOCALLBACKS_H_ */

View File

@ -1,6 +1,7 @@
#include "InitMission.h" #include "InitMission.h"
#include <OBSWVersion.h> #include <OBSWVersion.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include "OBSWConfig.h"
#include <iostream> #include <iostream>
@ -13,7 +14,11 @@
int main(void) int main(void)
{ {
std::cout << "-- EIVE OBSW --" << std::endl; std::cout << "-- EIVE OBSW --" << std::endl;
#if TE0720 == 0
std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl; std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl;
#else
std::cout << "-- Compiled for Linux (TE0720) --" << std::endl;
#endif
std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "." std::cout << "-- Software version " << SW_NAME << " v" << SW_VERSION << "."
<< SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl; << SW_SUBVERSION << "." << SW_SUBSUBVERSION << " -- " << std::endl;
std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl;

1
etl Submodule

@ -0,0 +1 @@
Subproject commit ae06e6417702b770c49289c9e7162cb3f4a5a217

2
fsfw

@ -1 +1 @@
Subproject commit d7d24bd9aac7522eb096ea9138eb61559fde9012 Subproject commit ac027e3ff22b609fe63096275a135babc8f76253

View File

@ -16,19 +16,25 @@
/* These defines should be disabled for mission code but are useful for /* These defines should be disabled for mission code but are useful for
debugging. */ debugging. */
#define OBSW_VERBOSE_LEVEL 1 #define OBSW_VERBOSE_LEVEL 1
#define OBSW_PRINT_MISSED_DEADLINES 1 #define OBSW_PRINT_MISSED_DEADLINES 1
#define OBSW_ADD_TEST_CODE 1 #define OBSW_ADD_TEST_CODE 1
#define TEST_LIBGPIOD 0 #define TEST_LIBGPIOD 0
#define TEST_RADIATION_SENSOR_HANDLER 1
#define TEST_SUS_HANDLER 1
#define TEST_PLOC_HANDLER 0
#define TE0720 0 #define TE0720 0
#define TE0720_HEATER_TEST 0
#define P60DOCK_DEBUG 0 #define P60DOCK_DEBUG 0
#define PDU1_DEBUG 0 #define PDU1_DEBUG 0
#define PDU2_DEBUG 0 #define PDU2_DEBUG 0
#define ACU_DEBUG 0 #define ACU_DEBUG 0
#define SYRLINKS_DEBUG 0 #define SYRLINKS_DEBUG 0
#define IMQT_DEBUG 1 #define IMQT_DEBUG 0
#define DEBUG_RAD_SENSOR 1
#define DEBUG_SUS 1
#include "OBSWVersion.h" #include "OBSWVersion.h"

View File

@ -19,6 +19,22 @@ namespace addresses {
GYRO_1_L3G = objects::GYRO_1_L3G_HANDLER, GYRO_1_L3G = objects::GYRO_1_L3G_HANDLER,
GYRO_2_L3G = objects::GYRO_2_L3G_HANDLER, GYRO_2_L3G = objects::GYRO_2_L3G_HANDLER,
RAD_SENSOR = objects::RAD_SENSOR,
SUS_1 = objects::SUS_1,
SUS_2 = objects::SUS_2,
SUS_3 = objects::SUS_3,
SUS_4 = objects::SUS_4,
SUS_5 = objects::SUS_5,
SUS_6 = objects::SUS_6,
SUS_7 = objects::SUS_7,
SUS_8 = objects::SUS_8,
SUS_9 = objects::SUS_9,
SUS_10 = objects::SUS_10,
SUS_11 = objects::SUS_11,
SUS_12 = objects::SUS_12,
SUS_13 = objects::SUS_13,
/* Dummy and Test Addresses */ /* Dummy and Test Addresses */
DUMMY_ECHO = 129, DUMMY_ECHO = 129,
DUMMY_GPS0 = 130, DUMMY_GPS0 = 130,

View File

@ -44,12 +44,28 @@ namespace gpioIds {
RTD_IC17, RTD_IC17,
RTD_IC18, RTD_IC18,
CS_SUS_1,
CS_SUS_2,
CS_SUS_3,
CS_SUS_4,
CS_SUS_5,
CS_SUS_6,
CS_SUS_7,
CS_SUS_8,
CS_SUS_9,
CS_SUS_10,
CS_SUS_11,
CS_SUS_12,
CS_SUS_13,
SPI_MUX_BIT_1, SPI_MUX_BIT_1,
SPI_MUX_BIT_2, SPI_MUX_BIT_2,
SPI_MUX_BIT_3, SPI_MUX_BIT_3,
SPI_MUX_BIT_4, SPI_MUX_BIT_4,
SPI_MUX_BIT_5, SPI_MUX_BIT_5,
SPI_MUX_BIT_6 SPI_MUX_BIT_6,
CS_RAD_SENSOR
}; };
} }

View File

@ -20,6 +20,9 @@ static constexpr spi::SpiModes DEFAULT_RM3100_MODE = spi::SpiModes::MODE_3;
static constexpr uint32_t DEFAULT_L3G_SPEED = 3'900'000; static constexpr uint32_t DEFAULT_L3G_SPEED = 3'900'000;
static constexpr spi::SpiModes DEFAULT_L3G_MODE = spi::SpiModes::MODE_3; static constexpr spi::SpiModes DEFAULT_L3G_MODE = spi::SpiModes::MODE_3;
static constexpr uint32_t DEFAULT_MAX_1227_SPEED = 3'900'000;
static constexpr spi::SpiModes DEFAULT_MAX_1227_MODE = spi::SpiModes::MODE_3;
} }

View File

@ -21,7 +21,8 @@ enum: uint8_t {
MGM_RM3100, MGM_RM3100,
PCDU_HANDLER, PCDU_HANDLER,
HEATER_HANDLER, HEATER_HANDLER,
SA_DEPL_HANDLER SA_DEPL_HANDLER,
PLOC_HANDLER
}; };
} }

View File

@ -52,6 +52,22 @@ namespace objects {
GYRO_2_L3G_HANDLER = 0x44000013, GYRO_2_L3G_HANDLER = 0x44000013,
IMTQ_HANDLER = 0x44000014, IMTQ_HANDLER = 0x44000014,
PLOC_HANDLER = 0x44000015,
SUS_1 = 0x44000016,
SUS_2 = 0x44000017,
SUS_3 = 0x44000018,
SUS_4 = 0x44000019,
SUS_5 = 0x4400001A,
SUS_6 = 0x4400001B,
SUS_7 = 0x4400001C,
SUS_8 = 0x4400001D,
SUS_9 = 0x4400001E,
SUS_10 = 0x4400001F,
SUS_11 = 0x44000021,
SUS_12 = 0x44000022,
SUS_13 = 0x44000023,
/* Custom device handler */ /* Custom device handler */
PCDU_HANDLER = 0x44001000, PCDU_HANDLER = 0x44001000,
@ -81,6 +97,8 @@ namespace objects {
RTD_IC17 = 0x5400003F, RTD_IC17 = 0x5400003F,
RTD_IC18 = 0x5400004F, RTD_IC18 = 0x5400004F,
RAD_SENSOR = 0x54000050,
/* 0x54 ('T') for test handlers */ /* 0x54 ('T') for test handlers */
TEST_TASK = 0x54694269, TEST_TASK = 0x54694269,
LIBGPIOD_TEST = 0x54123456, LIBGPIOD_TEST = 0x54123456,

View File

@ -5,13 +5,14 @@
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/tasks/FixedTimeslotTaskIF.h> #include <fsfw/tasks/FixedTimeslotTaskIF.h>
#include <fsfwconfig/objects/systemObjectList.h> #include <fsfwconfig/objects/systemObjectList.h>
#include <fsfwconfig/OBSWConfig.h>
#include <mission/devices/SusHandler.h>
ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
{ {
/* Length of a communication cycle */ /* Length of a communication cycle */
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0,
DeviceHandlerIF::PERFORM_OPERATION); DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0,
@ -40,6 +41,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE);
@ -64,6 +66,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE);
@ -85,9 +88,11 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
thisSequence->addSlot(objects::RTD_IC16, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::RTD_IC16, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RTD_IC17, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::RTD_IC17, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RTD_IC18, length * 0.4, DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::RTD_IC18, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ);
@ -111,6 +116,7 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ);
@ -135,6 +141,276 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence)
#endif /* Q7S_ADD_RTD_DEVICES */ #endif /* Q7S_ADD_RTD_DEVICES */
thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::IMTQ_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
/* Radiation sensor */
thisSequence->addSlot(objects::RAD_SENSOR, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.6, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::RAD_SENSOR, length * 0.8, DeviceHandlerIF::GET_READ);
if (length != 3000) {
sif::warning << "pollingSequenceInitDefault: Frequency changed. Make sure timing critical "
<< "SUS sensors still produce correct values" << std::endl;
}
/**
* The sun sensor will be shutdown as soon as the chip select is pulled high. Thus all
* requests to a sun sensor must be performed consecutively. Another reason for calling multiple
* device handler cycles is that the ADC conversions take some time. Thus first the ADC
* conversions are initiated and in a next step the results can be read from the internal FIFO.
* One sun sensor communication sequence also blocks the SPI bus. So other devices can not be
* inserted between the device handler cycles of one SUS.
*/
/* Write setup */
thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_1, length * 0.9, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_1, length * 0.9, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_1, length * 0.901, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_1, length * 0.902, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_1, length * 0.902, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_2, length * 0.903, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_2, length * 0.903, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_2, length * 0.904, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_2, length * 0.904, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_2, length * 0.905, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_2, length * 0.905, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_3, length * 0.906, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_3, length * 0.906, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_3, length * 0.906, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_3, length * 0.906, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_3, length * 0.906, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_3, length * 0.907, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_3, length * 0.907, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_3, length * 0.907, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_3, length * 0.907, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_3, length * 0.907, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_3, length * 0.908, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_3, length * 0.908, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_3, length * 0.908, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_3, length * 0.908, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_3, length * 0.908, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_4, length * 0.909, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_4, length * 0.909, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_4, length * 0.91, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_4, length * 0.91, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_4, length * 0.911, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_4, length * 0.911, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_5, length * 0.912, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_5, length * 0.912, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_5, length * 0.913, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_5, length * 0.913, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_5, length * 0.914, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_5, length * 0.914, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_6, length * 0.915, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_6, length * 0.915, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_6, length * 0.916, DeviceHandlerIF::GET_READ);
/* Read ADC conversions from inernal FIFO */
thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_6, length * 0.917, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_7, length * 0.918, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_7, length * 0.918, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_7, length * 0.919, DeviceHandlerIF::GET_READ);
/* Read ADC conversions from inernal FIFO */
thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_7, length * 0.92, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_8, length * 0.921, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_8, length * 0.921, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_8, length * 0.922, DeviceHandlerIF::GET_READ);
/* Read ADC conversions from inernal FIFO */
thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_8, length * 0.923, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_9, length * 0.924, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_9, length * 0.924, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_9, length * 0.925, DeviceHandlerIF::GET_READ);
/* Read ADC conversions */
thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_9, length * 0.926, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_10, length * 0.927, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_10, length * 0.927, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_10, length * 0.928, DeviceHandlerIF::GET_READ);
/* Read ADC conversions */
thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_10, length * 0.929, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_11, length * 0.93, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_11, length * 0.93, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_11, length * 0.931, DeviceHandlerIF::GET_READ);
/* Read ADC conversions */
thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_11, length * 0.932, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_12, length * 0.933, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_12, length * 0.933, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_12, length * 0.934, DeviceHandlerIF::GET_READ);
/* Read ADC conversions */
thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_12, length * 0.935, DeviceHandlerIF::GET_READ);
/* Write setup */
thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_13, length * 0.936, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_13, length * 0.936, DeviceHandlerIF::GET_READ);
/* Start ADC conversions */
thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_13, length * 0.937, DeviceHandlerIF::GET_READ);
/* Read ADC conversions */
thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_13, length * 0.938, DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -196,27 +472,27 @@ ReturnValue_t pst::gomspacePstInit(FixedTimeslotTaskIF *thisSequence){
length * 0.8, DeviceHandlerIF::GET_READ); length * 0.8, DeviceHandlerIF::GET_READ);
#if OBSW_ADD_ACS_BOARD == 1 #if OBSW_ADD_ACS_BOARD == 1
// thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0,
// DeviceHandlerIF::PERFORM_OPERATION); DeviceHandlerIF::PERFORM_OPERATION);
// thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.2, thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.2,
// DeviceHandlerIF::SEND_WRITE); DeviceHandlerIF::SEND_WRITE);
// thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.4, thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.4,
// DeviceHandlerIF::GET_WRITE); DeviceHandlerIF::GET_WRITE);
// thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.6, thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.6,
// DeviceHandlerIF::SEND_READ); DeviceHandlerIF::SEND_READ);
// thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.8, thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.8,
// DeviceHandlerIF::GET_READ); DeviceHandlerIF::GET_READ);
//
// thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0, thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0,
// DeviceHandlerIF::PERFORM_OPERATION); DeviceHandlerIF::PERFORM_OPERATION);
// thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.2, thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.2,
// DeviceHandlerIF::SEND_WRITE); DeviceHandlerIF::SEND_WRITE);
// thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.4, thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.4,
// DeviceHandlerIF::GET_WRITE); DeviceHandlerIF::GET_WRITE);
// thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.6, thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.6,
// DeviceHandlerIF::SEND_READ); DeviceHandlerIF::SEND_READ);
// thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.8, thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.8,
// DeviceHandlerIF::GET_READ); DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0, thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION); DeviceHandlerIF::PERFORM_OPERATION);
@ -229,16 +505,42 @@ ReturnValue_t pst::gomspacePstInit(FixedTimeslotTaskIF *thisSequence){
thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.8, thisSequence->addSlot(objects::MGM_2_LIS3_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ); DeviceHandlerIF::GET_READ);
// thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0,
// DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0,
// thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.2, DeviceHandlerIF::PERFORM_OPERATION);
// DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.2,
// thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.4, DeviceHandlerIF::SEND_WRITE);
// DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.4,
// thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.6, DeviceHandlerIF::GET_WRITE);
// DeviceHandlerIF::SEND_READ); thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.6,
// thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.8, DeviceHandlerIF::SEND_READ);
// DeviceHandlerIF::GET_READ); thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::GYRO_2_L3G_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_2_L3G_HANDLER, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_2_L3G_HANDLER, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_2_L3G_HANDLER, length * 0.6,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_2_L3G_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.6,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_3_RM3100_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
#endif #endif
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
@ -248,44 +550,52 @@ ReturnValue_t pst::gomspacePstInit(FixedTimeslotTaskIF *thisSequence){
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t pst::pollingSequenceAcsTest(FixedTimeslotTaskIF *thisSequence) { ReturnValue_t pst::pollingSequenceTE0720(FixedTimeslotTaskIF *thisSequence) {
uint32_t length = thisSequence->getPeriodMs(); uint32_t length = thisSequence->getPeriodMs();
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0, #if TEST_PLOC_HANDLER == 1
DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::PLOC_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.2, thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.4, thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::PLOC_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.6, #endif
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_0_LIS3_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0, #if TEST_RADIATION_SENSOR_HANDLER == 1
DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::RAD_SENSOR, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.2, thisSequence->addSlot(objects::RAD_SENSOR, length * 0.2, DeviceHandlerIF::SEND_WRITE);
DeviceHandlerIF::SEND_WRITE); thisSequence->addSlot(objects::RAD_SENSOR, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.4, thisSequence->addSlot(objects::RAD_SENSOR, length * 0.6, DeviceHandlerIF::SEND_READ);
DeviceHandlerIF::GET_WRITE); thisSequence->addSlot(objects::RAD_SENSOR, length * 0.8, DeviceHandlerIF::GET_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.6, #endif
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::MGM_1_RM3100_HANDLER, length * 0.8, #if TEST_SUS_HANDLER == 1
DeviceHandlerIF::GET_READ); /* Write setup */
thisSequence->addSlot(objects::SUS_1, length * 0.901, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_1, length * 0.902, SusHandler::FIRST_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.903, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.904, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_1, length * 0.905, DeviceHandlerIF::GET_READ);
/* Start conversion*/
thisSequence->addSlot(objects::SUS_1, length * 0.906, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_1, length * 0.907, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.908, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.909, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_1, length * 0.91, DeviceHandlerIF::GET_READ);
/* Read conversions */
thisSequence->addSlot(objects::SUS_1, length * 0.911, DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::SUS_1, length * 0.912, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.913, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::SUS_1, length * 0.914, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::SUS_1, length * 0.915, DeviceHandlerIF::GET_READ);
#endif
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.6,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::GYRO_1_L3G_HANDLER, length * 0.8,
DeviceHandlerIF::GET_READ);
if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Initialization of ACS Board PST failed" << std::endl; sif::error << "Initialization of TE0720 PST failed" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -35,6 +35,11 @@ ReturnValue_t pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence);
ReturnValue_t gomspacePstInit(FixedTimeslotTaskIF *thisSequence); ReturnValue_t gomspacePstInit(FixedTimeslotTaskIF *thisSequence);
ReturnValue_t pollingSequenceAcsTest(FixedTimeslotTaskIF* thisSequence); ReturnValue_t pollingSequenceAcsTest(FixedTimeslotTaskIF* thisSequence);
/**
* @brief This polling sequence will be created when the software is compiled for the TE0720.
*/
ReturnValue_t pollingSequenceTE0720(FixedTimeslotTaskIF* thisSequence);
} }

View File

@ -20,6 +20,8 @@ enum {
SA_DEPL_HANDLER, SA_DEPL_HANDLER,
SYRLINKS_HANDLER, SYRLINKS_HANDLER,
IMTQ_HANDLER, IMTQ_HANDLER,
PLOC_HANDLER,
SUS_HANDLER
}; };
} }

View File

@ -363,6 +363,9 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF *cookie,
*buffer = uartDeviceMapIter->second.replyBuffer.data(); *buffer = uartDeviceMapIter->second.replyBuffer.data();
*size = uartDeviceMapIter->second.replyLen; *size = uartDeviceMapIter->second.replyLen;
/* Length is reset to 0 to prevent reading the same data twice */
uartDeviceMapIter->second.replyLen = 0;
return RETURN_OK; return RETURN_OK;
} }

View File

@ -13,6 +13,9 @@ target_sources(${TARGET_NAME} PUBLIC
SyrlinksHkHandler.cpp SyrlinksHkHandler.cpp
Max31865PT1000Handler.cpp Max31865PT1000Handler.cpp
IMTQHandler.cpp IMTQHandler.cpp
PlocHandler.cpp
RadiationSensorHandler.cpp
SusHandler.cpp
) )

View File

@ -6,7 +6,8 @@
#include <fsfwconfig/OBSWConfig.h> #include <fsfwconfig/OBSWConfig.h>
IMTQHandler::IMTQHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : IMTQHandler::IMTQHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) :
DeviceHandlerBase(objectId, comIF, comCookie), engHkDataset(this) { DeviceHandlerBase(objectId, comIF, comCookie), engHkDataset(this), calMtmMeasurementSet(
this), rawMtmMeasurementSet(this) {
if (comCookie == NULL) { if (comCookie == NULL) {
sif::error << "IMTQHandler: Invalid com cookie" << std::endl; sif::error << "IMTQHandler: Invalid com cookie" << std::endl;
} }
@ -20,6 +21,7 @@ void IMTQHandler::doStartUp(){
if(mode == _MODE_START_UP){ if(mode == _MODE_START_UP){
//TODO: Set to MODE_ON again //TODO: Set to MODE_ON again
setMode(MODE_NORMAL); setMode(MODE_NORMAL);
communicationStep = CommunicationStep::SELF_TEST;
} }
} }
@ -29,7 +31,34 @@ void IMTQHandler::doShutDown(){
ReturnValue_t IMTQHandler::buildNormalDeviceCommand( ReturnValue_t IMTQHandler::buildNormalDeviceCommand(
DeviceCommandId_t * id) { DeviceCommandId_t * id) {
*id = IMTQ::GET_ENG_HK_DATA; switch (communicationStep) {
case CommunicationStep::SELF_TEST:
// *id = IMTQ::SELF_TEST;
//TODO: Implementing self test command. On-hold because of issue with humidity in clean
// room
communicationStep = CommunicationStep::GET_ENG_HK_DATA;
break;
case CommunicationStep::GET_ENG_HK_DATA:
*id = IMTQ::GET_ENG_HK_DATA;
communicationStep = CommunicationStep::START_MTM_MEASUREMENT;
break;
case CommunicationStep::START_MTM_MEASUREMENT:
*id = IMTQ::START_MTM_MEASUREMENT;
communicationStep = CommunicationStep::GET_CAL_MTM_MEASUREMENT;
break;
case CommunicationStep::GET_CAL_MTM_MEASUREMENT:
*id = IMTQ::GET_CAL_MTM_MEASUREMENT;
communicationStep = CommunicationStep::GET_RAW_MTM_MEASUREMENT;
break;
case CommunicationStep::GET_RAW_MTM_MEASUREMENT:
*id = IMTQ::GET_RAW_MTM_MEASUREMENT;
communicationStep = CommunicationStep::GET_ENG_HK_DATA;
break;
default:
sif::debug << "IMTQHandler::buildNormalDeviceCommand: Invalid communication step"
<< std::endl;
break;
}
return buildCommandFromCommand(*id, NULL, 0); return buildCommandFromCommand(*id, NULL, 0);
} }
@ -42,25 +71,49 @@ ReturnValue_t IMTQHandler::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t * commandData, DeviceCommandId_t deviceCommand, const uint8_t * commandData,
size_t commandDataLen) { size_t commandDataLen) {
switch(deviceCommand) { switch(deviceCommand) {
case(IMTQ::START_ACTUATION_DIPOLE): {
/* IMTQ expects low byte first */
commandBuffer[0] = IMTQ::CC::START_ACTUATION_DIPOLE;
commandBuffer[1] = *(commandData + 1);
commandBuffer[2] = *(commandData);
commandBuffer[3] = *(commandData + 3);
commandBuffer[4] = *(commandData + 2);
commandBuffer[5] = *(commandData + 5);
commandBuffer[6] = *(commandData + 4);
commandBuffer[7] = *(commandData + 7);
commandBuffer[8] = *(commandData + 6);
rawPacket = commandBuffer;
rawPacketLen = 9;
return RETURN_OK;
}
case(IMTQ::GET_ENG_HK_DATA): { case(IMTQ::GET_ENG_HK_DATA): {
commandBuffer[0] = IMTQ::CC::GET_ENG_HK_DATA; commandBuffer[0] = IMTQ::CC::GET_ENG_HK_DATA;
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 1; rawPacketLen = 1;
return RETURN_OK; return RETURN_OK;
} }
case(IMTQ::START_ACTUATION_DIPOLE): { case(IMTQ::GET_COMMANDED_DIPOLE): {
/* IMTQ expects low byte first */ commandBuffer[0] = IMTQ::CC::GET_COMMANDED_DIPOLE;
commandBuffer[0] = IMTQ::CC::START_ACTUATION_DIPOLE;
commandBuffer[1] = *(commandData + 1);
commandBuffer[2] = *(commandData);
commandBuffer[3] = *(commandData + 3);
commandBuffer[4] = *(commandData + 2);
commandBuffer[5] = *(commandData + 5);
commandBuffer[6] = *(commandData + 4);
commandBuffer[7] = *(commandData + 7);
commandBuffer[8] = *(commandData + 6);
rawPacket = commandBuffer; rawPacket = commandBuffer;
rawPacketLen = 9; rawPacketLen = 1;
return RETURN_OK;
}
case(IMTQ::START_MTM_MEASUREMENT): {
commandBuffer[0] = IMTQ::CC::START_MTM_MEASUREMENT;
rawPacket = commandBuffer;
rawPacketLen = 1;
return RETURN_OK;
}
case(IMTQ::GET_CAL_MTM_MEASUREMENT): {
commandBuffer[0] = IMTQ::CC::GET_CAL_MTM_MEASUREMENT;
rawPacket = commandBuffer;
rawPacketLen = 1;
return RETURN_OK;
}
case(IMTQ::GET_RAW_MTM_MEASUREMENT): {
commandBuffer[0] = IMTQ::CC::GET_RAW_MTM_MEASUREMENT;
rawPacket = commandBuffer;
rawPacketLen = 1;
return RETURN_OK; return RETURN_OK;
} }
default: default:
@ -70,8 +123,18 @@ ReturnValue_t IMTQHandler::buildCommandFromCommand(
} }
void IMTQHandler::fillCommandAndReplyMap() { void IMTQHandler::fillCommandAndReplyMap() {
this->insertInCommandAndReplyMap(IMTQ::START_ACTUATION_DIPOLE, 1, nullptr,
IMTQ::SIZE_STATUS_REPLY);
this->insertInCommandAndReplyMap(IMTQ::GET_ENG_HK_DATA, 1, &engHkDataset, this->insertInCommandAndReplyMap(IMTQ::GET_ENG_HK_DATA, 1, &engHkDataset,
IMTQ::SIZE_ENG_HK_DATA_REPLY, false, true, IMTQ::SIZE_ENG_HK_DATA_REPLY); IMTQ::SIZE_ENG_HK_DATA_REPLY);
this->insertInCommandAndReplyMap(IMTQ::GET_COMMANDED_DIPOLE, 1, nullptr,
IMTQ::SIZE_GET_COMMANDED_DIPOLE_REPLY);
this->insertInCommandAndReplyMap(IMTQ::START_MTM_MEASUREMENT, 1, nullptr,
IMTQ::SIZE_STATUS_REPLY);
this->insertInCommandAndReplyMap(IMTQ::GET_CAL_MTM_MEASUREMENT, 1, &calMtmMeasurementSet,
IMTQ::SIZE_GET_CAL_MTM_MEASUREMENT);
this->insertInCommandAndReplyMap(IMTQ::GET_RAW_MTM_MEASUREMENT, 1, &rawMtmMeasurementSet,
IMTQ::SIZE_GET_RAW_MTM_MEASUREMENT);
} }
ReturnValue_t IMTQHandler::scanForReply(const uint8_t *start, ReturnValue_t IMTQHandler::scanForReply(const uint8_t *start,
@ -80,10 +143,30 @@ ReturnValue_t IMTQHandler::scanForReply(const uint8_t *start,
ReturnValue_t result = RETURN_OK; ReturnValue_t result = RETURN_OK;
switch(*start) { switch(*start) {
case(IMTQ::CC::START_ACTUATION_DIPOLE):
*foundLen = IMTQ::SIZE_STATUS_REPLY;
*foundId = IMTQ::START_ACTUATION_DIPOLE;
break;
case(IMTQ::CC::START_MTM_MEASUREMENT):
*foundLen = IMTQ::SIZE_STATUS_REPLY;
*foundId = IMTQ::START_MTM_MEASUREMENT;
break;
case(IMTQ::CC::GET_ENG_HK_DATA): case(IMTQ::CC::GET_ENG_HK_DATA):
*foundLen = IMTQ::SIZE_ENG_HK_DATA_REPLY; *foundLen = IMTQ::SIZE_ENG_HK_DATA_REPLY;
*foundId = IMTQ::GET_ENG_HK_DATA; *foundId = IMTQ::GET_ENG_HK_DATA;
break; break;
case(IMTQ::CC::GET_COMMANDED_DIPOLE):
*foundLen = IMTQ::SIZE_GET_COMMANDED_DIPOLE_REPLY;
*foundId = IMTQ::GET_COMMANDED_DIPOLE;
break;
case(IMTQ::CC::GET_CAL_MTM_MEASUREMENT):
*foundLen = IMTQ::SIZE_GET_CAL_MTM_MEASUREMENT;
*foundId = IMTQ::GET_CAL_MTM_MEASUREMENT;
break;
case(IMTQ::CC::GET_RAW_MTM_MEASUREMENT):
*foundLen = IMTQ::SIZE_GET_RAW_MTM_MEASUREMENT;
*foundId = IMTQ::GET_RAW_MTM_MEASUREMENT;
break;
default: default:
sif::debug << "IMTQHandler::scanForReply: Reply contains invalid command code" << std::endl; sif::debug << "IMTQHandler::scanForReply: Reply contains invalid command code" << std::endl;
result = IGNORE_REPLY_DATA; result = IGNORE_REPLY_DATA;
@ -105,9 +188,22 @@ ReturnValue_t IMTQHandler::interpretDeviceReply(DeviceCommandId_t id,
} }
switch (id) { switch (id) {
case (IMTQ::START_ACTUATION_DIPOLE):
case (IMTQ::START_MTM_MEASUREMENT):
/* Replies only the status byte which is already handled with parseStatusByte */
break;
case (IMTQ::GET_ENG_HK_DATA): case (IMTQ::GET_ENG_HK_DATA):
fillEngHkDataset(packet); fillEngHkDataset(packet);
break; break;
case (IMTQ::GET_COMMANDED_DIPOLE):
handleGetCommandedDipoleReply(packet);
break;
case (IMTQ::GET_CAL_MTM_MEASUREMENT):
fillCalibratedMtmDataset(packet);
break;
case (IMTQ::GET_RAW_MTM_MEASUREMENT):
fillRawMtmDataset(packet);
break;
default: { default: {
sif::debug << "IMTQHandler::interpretDeviceReply: Unknown device reply id" << std::endl; sif::debug << "IMTQHandler::interpretDeviceReply: Unknown device reply id" << std::endl;
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
@ -117,22 +213,68 @@ ReturnValue_t IMTQHandler::interpretDeviceReply(DeviceCommandId_t id,
return RETURN_OK; return RETURN_OK;
} }
void IMTQHandler::setNormalDatapoolEntriesInvalid(){
}
uint32_t IMTQHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){
return 500;
}
ReturnValue_t IMTQHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
/** Entries of engineering housekeeping dataset */
localDataPoolMap.emplace(IMTQ::DIGITAL_VOLTAGE_MV, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::ANALOG_VOLTAGE_MV, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::DIGITAL_CURRENT, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::ANALOG_CURRENT, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_X_CURRENT, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Y_CURRENT, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Z_CURRENT, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_X_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Y_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Z_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::MCU_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
/** Entries of calibrated MTM measurement dataset */
localDataPoolMap.emplace(IMTQ::MTM_CAL_X, new PoolEntry<uint32_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::MTM_CAL_Y, new PoolEntry<uint32_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::MTM_CAL_Z, new PoolEntry<uint32_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::ACTUATION_CAL_STATUS, new PoolEntry<uint8_t>( { 0 }));
/** Entries of raw MTM measurement dataset */
localDataPoolMap.emplace(IMTQ::MTM_RAW_X, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::MTM_RAW_Y, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::MTM_RAW_Z, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::ACTUATION_RAW_STATUS, new PoolEntry<uint8_t>( { 0 }));
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t IMTQHandler::parseStatusByte(const uint8_t* packet) { ReturnValue_t IMTQHandler::parseStatusByte(const uint8_t* packet) {
uint8_t cmdErrorField = *(packet + 1) & 0xF; uint8_t cmdErrorField = *(packet + 1) & 0xF;
switch (cmdErrorField) { switch (cmdErrorField) {
case 0: case 0:
return RETURN_OK; return RETURN_OK;
case 1: case 1:
sif::error << "IMTQHandler::parseStatusByte: Command rejected without reason" << std::endl;
return REJECTED_WITHOUT_REASON; return REJECTED_WITHOUT_REASON;
case 2: case 2:
sif::error << "IMTQHandler::parseStatusByte: Command has invalid command code" << std::endl;
return INVALID_COMMAND_CODE; return INVALID_COMMAND_CODE;
case 3: case 3:
sif::error << "IMTQHandler::parseStatusByte: Command has missing parameter" << std::endl;
return PARAMETER_MISSING; return PARAMETER_MISSING;
case 4: case 4:
sif::error << "IMTQHandler::parseStatusByte: Command has invalid parameter" << std::endl;
return PARAMETER_INVALID; return PARAMETER_INVALID;
case 5: case 5:
sif::error << "IMTQHandler::parseStatusByte: CC unavailable" << std::endl;
return CC_UNAVAILABLE; return CC_UNAVAILABLE;
case 7: case 7:
sif::error << "IMTQHandler::parseStatusByte: IMQT replied internal processing error"
<< std::endl;
return INTERNAL_PROCESSING_ERROR; return INTERNAL_PROCESSING_ERROR;
default: default:
sif::error << "IMTQHandler::parseStatusByte: CMD Error field contains unknown error code " sif::error << "IMTQHandler::parseStatusByte: CMD Error field contains unknown error code "
@ -143,36 +285,36 @@ ReturnValue_t IMTQHandler::parseStatusByte(const uint8_t* packet) {
void IMTQHandler::fillEngHkDataset(const uint8_t* packet) { void IMTQHandler::fillEngHkDataset(const uint8_t* packet) {
uint8_t offset = 2; uint8_t offset = 2;
engHkDataset.digitalVoltageMv = *(packet + offset + 1) | *(packet + offset); engHkDataset.digitalVoltageMv = *(packet + offset + 1) << 8 | *(packet + offset);
offset += 2; offset += 2;
engHkDataset.analogVoltageMv = *(packet + offset + 1) | *(packet + offset); engHkDataset.analogVoltageMv = *(packet + offset + 1) << 8 | *(packet + offset);
offset += 2; offset += 2;
engHkDataset.digitalCurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; engHkDataset.digitalCurrentmA = (*(packet + offset + 1) << 8 | *(packet + offset)) * 0.1;
offset += 2; offset += 2;
engHkDataset.analogCurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; engHkDataset.analogCurrentmA = (*(packet + offset + 1) << 8 | *(packet + offset)) * 0.1;
offset += 2; offset += 2;
engHkDataset.coilXcurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; engHkDataset.coilXCurrentmA = (*(packet + offset + 1) << 8 | *(packet + offset)) * 0.1;
offset += 2; offset += 2;
engHkDataset.coilYcurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; engHkDataset.coilYCurrentmA = (*(packet + offset + 1) << 8 | *(packet + offset)) * 0.1;
offset += 2; offset += 2;
engHkDataset.coilZcurrentA = (*(packet + offset + 1) | *(packet + offset)) * 0.0001; engHkDataset.coilZCurrentmA = (*(packet + offset + 1) << 8 | *(packet + offset)) * 0.1;
offset += 2; offset += 2;
engHkDataset.coilXTemperature = (*(packet + offset + 1) | *(packet + offset)); engHkDataset.coilXTemperature = (*(packet + offset + 1) << 8 | *(packet + offset));
offset += 2; offset += 2;
engHkDataset.coilYTemperature = (*(packet + offset + 1) | *(packet + offset)); engHkDataset.coilYTemperature = (*(packet + offset + 1) << 8 | *(packet + offset));
offset += 2; offset += 2;
engHkDataset.coilZTemperature = (*(packet + offset + 1) | *(packet + offset)); engHkDataset.coilZTemperature = (*(packet + offset + 1) << 8 | *(packet + offset));
offset += 2; offset += 2;
engHkDataset.mcuTemperature = (*(packet + offset + 1) | *(packet + offset)); engHkDataset.mcuTemperature = (*(packet + offset + 1) << 8 | *(packet + offset));
#if OBSW_VERBOSE_LEVEL >= 1 && IMQT_DEBUG == 1 #if OBSW_VERBOSE_LEVEL >= 1 && IMQT_DEBUG == 1
sif::info << "IMTQ digital voltage: " << engHkDataset.digitalVoltageMv << " mV" << std::endl; sif::info << "IMTQ digital voltage: " << engHkDataset.digitalVoltageMv << " mV" << std::endl;
sif::info << "IMTQ analog voltage: " << engHkDataset.analogVoltageMv << " mV" << std::endl; sif::info << "IMTQ analog voltage: " << engHkDataset.analogVoltageMv << " mV" << std::endl;
sif::info << "IMTQ digital current: " << engHkDataset.digitalCurrentA << " A" << std::endl; sif::info << "IMTQ digital current: " << engHkDataset.digitalCurrentmA << " mA" << std::endl;
sif::info << "IMTQ analog current: " << engHkDataset.analogCurrentA << " A" << std::endl; sif::info << "IMTQ analog current: " << engHkDataset.analogCurrentmA << " mA" << std::endl;
sif::info << "IMTQ coil X current: " << engHkDataset.coilXcurrentA << " A" << std::endl; sif::info << "IMTQ coil X current: " << engHkDataset.coilXCurrentmA << " mA" << std::endl;
sif::info << "IMTQ coil Y current: " << engHkDataset.coilYcurrentA << " A" << std::endl; sif::info << "IMTQ coil Y current: " << engHkDataset.coilYCurrentmA << " mA" << std::endl;
sif::info << "IMTQ coil Z current: " << engHkDataset.coilZcurrentA << " A" << std::endl; sif::info << "IMTQ coil Z current: " << engHkDataset.coilZCurrentmA << " mA" << std::endl;
sif::info << "IMTQ coil X temperature: " << engHkDataset.coilXTemperature << " °C" sif::info << "IMTQ coil X temperature: " << engHkDataset.coilXTemperature << " °C"
<< std::endl; << std::endl;
sif::info << "IMTQ coil Y temperature: " << engHkDataset.coilYTemperature << " °C" sif::info << "IMTQ coil Y temperature: " << engHkDataset.coilYTemperature << " °C"
@ -184,33 +326,93 @@ void IMTQHandler::fillEngHkDataset(const uint8_t* packet) {
#endif #endif
} }
void IMTQHandler::setNormalDatapoolEntriesInvalid(){
}
uint32_t IMTQHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){
return 500;
}
ReturnValue_t IMTQHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(IMTQ::DIGITAL_VOLTAGE_MV, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::ANALOG_VOLTAGE_MV, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::DIGITAL_CURRENT_A, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::ANALOG_CURRENT_A, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_X_CURRENT_A, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Y_CURRENT_A, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Z_CURRENT_A, new PoolEntry<float>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_X_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Y_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::COIL_Z_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(IMTQ::MCU_TEMPERATURE, new PoolEntry<uint16_t>( { 0 }));
return HasReturnvaluesIF::RETURN_OK;
}
void IMTQHandler::setModeNormal() { void IMTQHandler::setModeNormal() {
mode = MODE_NORMAL; mode = MODE_NORMAL;
} }
void IMTQHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) {
if (wiretappingMode == RAW) {
/* Data already sent in doGetRead() */
return;
}
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
sif::debug << "IMTQHandler::handleDeviceTM: Unknown reply id" << std::endl;
return;
}
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
if (queueId == NO_COMMANDER) {
return;
}
ReturnValue_t result = actionHelper.reportData(queueId, replyId, data, dataSize);
if (result != RETURN_OK) {
sif::debug << "IMTQHandler::handleDeviceTM: Failed to report data" << std::endl;
return;
}
}
void IMTQHandler::handleGetCommandedDipoleReply(const uint8_t* packet) {
uint8_t tmData[6];
/* Switching endianess of received dipole values */
tmData[0] = *(packet + 3);
tmData[1] = *(packet + 2);
tmData[2] = *(packet + 5);
tmData[3] = *(packet + 4);
tmData[4] = *(packet + 7);
tmData[5] = *(packet + 6);
handleDeviceTM(tmData, sizeof(tmData), IMTQ::GET_COMMANDED_DIPOLE);
}
void IMTQHandler::fillCalibratedMtmDataset(const uint8_t* packet) {
int8_t offset = 2;
calMtmMeasurementSet.mtmXnT = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
| *(packet + offset + 1) << 8 | *(packet + offset);
offset += 4;
calMtmMeasurementSet.mtmYnT = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
| *(packet + offset + 1) << 8 | *(packet + offset);
offset += 4;
calMtmMeasurementSet.mtmZnT = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
| *(packet + offset + 1) << 8 | *(packet + offset);
offset += 4;
calMtmMeasurementSet.coilActuationStatus = (*(packet + offset + 3) << 24)
| (*(packet + offset + 2) << 16) | (*(packet + offset + 1) << 8) | (*(packet + offset));
#if OBSW_VERBOSE_LEVEL >= 1 && IMQT_DEBUG == 1
sif::info << "IMTQ calibrated MTM measurement X: " << calMtmMeasurementSet.mtmXnT << " nT"
<< std::endl;
sif::info << "IMTQ calibrated MTM measurement Y: " << calMtmMeasurementSet.mtmYnT << " nT"
<< std::endl;
sif::info << "IMTQ calibrated MTM measurement Z: " << calMtmMeasurementSet.mtmZnT << " nT"
<< std::endl;
sif::info << "IMTQ coil actuation status during MTM measurement: "
<< (unsigned int) calMtmMeasurementSet.coilActuationStatus.value << std::endl;
#endif
}
void IMTQHandler::fillRawMtmDataset(const uint8_t* packet) {
int8_t offset = 2;
rawMtmMeasurementSet.mtmXnT = (*(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
| *(packet + offset + 1) << 8 | *(packet + offset)) * 7.5;
offset += 4;
rawMtmMeasurementSet.mtmYnT = (*(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
| *(packet + offset + 1) << 8 | *(packet + offset)) * 7.5;
offset += 4;
rawMtmMeasurementSet.mtmZnT = (*(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
| *(packet + offset + 1) << 8 | *(packet + offset)) * 7.5;
offset += 4;
rawMtmMeasurementSet.coilActuationStatus = (*(packet + offset + 3) << 24)
| (*(packet + offset + 2) << 16) | (*(packet + offset + 1) << 8) | (*(packet + offset));
#if OBSW_VERBOSE_LEVEL >= 1 && IMQT_DEBUG == 1
sif::info << "IMTQ raw MTM measurement X: " << rawMtmMeasurementSet.mtmXnT << " nT"
<< std::endl;
sif::info << "IMTQ raw MTM measurement Y: " << rawMtmMeasurementSet.mtmYnT << " nT"
<< std::endl;
sif::info << "IMTQ raw MTM measurement Z: " << rawMtmMeasurementSet.mtmZnT << " nT"
<< std::endl;
sif::info << "IMTQ coil actuation status during MTM measurement: "
<< (unsigned int) rawMtmMeasurementSet.coilActuationStatus.value << std::endl;
#endif
}

View File

@ -52,9 +52,21 @@ private:
IMTQ::EngHkDataset engHkDataset; IMTQ::EngHkDataset engHkDataset;
IMTQ::CalibratedMtmMeasurementSet calMtmMeasurementSet;
IMTQ::RawMtmMeasurementSet rawMtmMeasurementSet;
uint8_t commandBuffer[IMTQ::MAX_COMMAND_SIZE]; uint8_t commandBuffer[IMTQ::MAX_COMMAND_SIZE];
enum class CommunicationStep {
SELF_TEST,
GET_ENG_HK_DATA,
START_MTM_MEASUREMENT,
GET_CAL_MTM_MEASUREMENT,
GET_RAW_MTM_MEASUREMENT
};
CommunicationStep communicationStep = CommunicationStep::GET_ENG_HK_DATA;
/** /**
* @brief Each reply contains a status byte giving information about a request. This function * @brief Each reply contains a status byte giving information about a request. This function
* parses this byte and returns the associated failure message. * parses this byte and returns the associated failure message.
@ -72,6 +84,36 @@ private:
* *
*/ */
void fillEngHkDataset(const uint8_t* packet); void fillEngHkDataset(const uint8_t* packet);
/**
* @brief This function sends a command reply to the requesting queue.
*
* @param data Pointer to the data to send.
* @param dataSize Size of the data to send.
* @param relplyId Reply id which will be inserted at the beginning of the action message.
*/
void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief This function handles the reply containing the commanded dipole.
*
* @param packet Pointer to the reply data.
*/
void handleGetCommandedDipoleReply(const uint8_t* packet);
/**
* @brief This function parses the reply containing the calibrated MTM measurement and writes
* the values to the appropriate dataset.
* @param packet Pointer to the reply data.
*/
void fillCalibratedMtmDataset(const uint8_t* packet);
/**
* @brief This function copies the raw MTM measurements to the MTM raw dataset.
* @param packet Pointer to the reply data requested with the GET_RAW_MTM_MEASUREMENTS
* command.
*/
void fillRawMtmDataset(const uint8_t* packet);
}; };
#endif /* MISSION_DEVICES_IMTQHANDLER_H_ */ #endif /* MISSION_DEVICES_IMTQHANDLER_H_ */

View File

@ -0,0 +1,498 @@
#include "PlocHandler.h"
#include <fsfwconfig/OBSWConfig.h>
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfwconfig/OBSWConfig.h>
PlocHandler::PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) :
DeviceHandlerBase(objectId, comIF, comCookie) {
if (comCookie == NULL) {
sif::error << "PlocHandler: Invalid com cookie" << std::endl;
}
}
PlocHandler::~PlocHandler() {
}
void PlocHandler::doStartUp(){
if(mode == _MODE_START_UP){
setMode(MODE_ON);
}
}
void PlocHandler::doShutDown(){
}
ReturnValue_t PlocHandler::buildNormalDeviceCommand(
DeviceCommandId_t * id) {
return RETURN_OK;
}
ReturnValue_t PlocHandler::buildTransitionDeviceCommand(
DeviceCommandId_t * id){
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PlocHandler::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t * commandData,
size_t commandDataLen) {
switch(deviceCommand) {
case(PLOC::TC_MEM_WRITE): {
return prepareTcMemWriteCommand(commandData, commandDataLen);
}
case(PLOC::TC_MEM_READ): {
return prepareTcMemReadCommand(commandData, commandDataLen);
}
default:
sif::debug << "PlocHandler::buildCommandFromCommand: Command not implemented" << std::endl;
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return HasReturnvaluesIF::RETURN_FAILED;
}
void PlocHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(PLOC::TC_MEM_WRITE);
this->insertInCommandMap(PLOC::TC_MEM_READ);
this->insertInReplyMap(PLOC::ACK_REPORT, 1, nullptr, PLOC::SIZE_ACK_REPORT);
this->insertInReplyMap(PLOC::EXE_REPORT, 3, nullptr, PLOC::SIZE_EXE_REPORT);
this->insertInReplyMap(PLOC::TM_MEMORY_READ_REPORT, 2, nullptr, PLOC::SIZE_TM_MEM_READ_REPORT);
}
ReturnValue_t PlocHandler::scanForReply(const uint8_t *start,
size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) {
ReturnValue_t result = RETURN_OK;
uint16_t apid = (*(start) << 8 | *(start + 1)) & APID_MASK;
switch(apid) {
case(PLOC::APID_ACK_SUCCESS):
*foundLen = PLOC::SIZE_ACK_REPORT;
*foundId = PLOC::ACK_REPORT;
break;
case(PLOC::APID_ACK_FAILURE):
*foundLen = PLOC::SIZE_ACK_REPORT;
*foundId = PLOC::ACK_REPORT;
break;
case(PLOC::APID_TM_MEMORY_READ_REPORT):
*foundLen = PLOC::SIZE_TM_MEM_READ_REPORT;
*foundId = PLOC::TM_MEMORY_READ_REPORT;
break;
case(PLOC::APID_EXE_SUCCESS):
*foundLen = PLOC::SIZE_EXE_REPORT;
*foundId = PLOC::EXE_REPORT;
break;
case(PLOC::APID_EXE_FAILURE):
*foundLen = PLOC::SIZE_EXE_REPORT;
*foundId = PLOC::EXE_REPORT;
break;
default: {
sif::debug << "PlocHandler::scanForReply: Reply has invalid apid" << std::endl;
*foundLen = remainingSize;
return INVALID_APID;
}
}
/**
* This should normally never fail. However, this function is also responsible for incrementing
* the packet sequence count why it is called here.
*/
result = checkPacketSequenceCount(start);
return result;
}
ReturnValue_t PlocHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
ReturnValue_t result = RETURN_OK;
switch (id) {
case PLOC::ACK_REPORT: {
result = handleAckReport(packet);
break;
}
case (PLOC::TM_MEMORY_READ_REPORT): {
result = handleMemoryReadReport(packet);
break;
}
case (PLOC::EXE_REPORT): {
result = handleExecutionReport(packet);
break;
}
default: {
sif::debug << "PlocHandler::interpretDeviceReply: Unknown device reply id" << std::endl;
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
}
}
return result;
}
void PlocHandler::setNormalDatapoolEntriesInvalid(){
}
uint32_t PlocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){
return 500;
}
ReturnValue_t PlocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
return HasReturnvaluesIF::RETURN_OK;
}
void PlocHandler::setModeNormal() {
mode = MODE_NORMAL;
}
ReturnValue_t PlocHandler::prepareTcMemWriteCommand(const uint8_t * commandData,
size_t commandDataLen) {
const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16
| *(commandData + 2) << 8 | *(commandData + 3);
const uint32_t memoryData = *(commandData + 4) << 24 | *(commandData + 5) << 16
| *(commandData + 6) << 8 | *(commandData + 7);
packetSequenceCount = (packetSequenceCount + 1) & PACKET_SEQUENCE_COUNT_MASK;
PLOC::TcMemWrite tcMemWrite(memoryAddress, memoryData, packetSequenceCount);
if (tcMemWrite.getFullSize() > PLOC::MAX_COMMAND_SIZE) {
sif::debug << "PlocHandler::prepareTcMemWriteCommand: Command too big" << std::endl;
return RETURN_FAILED;
}
memcpy(commandBuffer, tcMemWrite.getWholeData(), tcMemWrite.getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tcMemWrite.getFullSize();
nextReplyId = PLOC::ACK_REPORT;
return RETURN_OK;
}
ReturnValue_t PlocHandler::prepareTcMemReadCommand(const uint8_t * commandData,
size_t commandDataLen) {
const uint32_t memoryAddress = *(commandData) << 24 | *(commandData + 1) << 16
| *(commandData + 2) << 8 | *(commandData + 3);
packetSequenceCount = (packetSequenceCount + 1) & PACKET_SEQUENCE_COUNT_MASK;
PLOC::TcMemRead tcMemRead(memoryAddress, packetSequenceCount);
if (tcMemRead.getFullSize() > PLOC::MAX_COMMAND_SIZE) {
sif::debug << "PlocHandler::prepareTcMemReadCommand: Command too big" << std::endl;
return RETURN_FAILED;
}
memcpy(commandBuffer, tcMemRead.getWholeData(), tcMemRead.getFullSize());
rawPacket = commandBuffer;
rawPacketLen = tcMemRead.getFullSize();
nextReplyId = PLOC::ACK_REPORT;
return RETURN_OK;
}
ReturnValue_t PlocHandler::verifyPacket(const uint8_t* start, size_t foundLen) {
uint16_t receivedCrc = *(start + foundLen - 2) << 8 | *(start + foundLen - 1);
uint16_t recalculatedCrc = CRC::crc16ccitt(start, foundLen - 2);
if (receivedCrc != recalculatedCrc) {
return CRC_FAILURE;
}
return RETURN_OK;
}
ReturnValue_t PlocHandler::handleAckReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
result = verifyPacket(data, PLOC::SIZE_ACK_REPORT);
if(result == CRC_FAILURE) {
sif::error << "PlocHandler::handleAckReport: CRC failure" << std::endl;
nextReplyId = PLOC::NONE;
replyRawReplyIfnotWiretapped(data, PLOC::SIZE_ACK_REPORT);
triggerEvent(CRC_FAILURE_EVENT);
sendFailureReport(PLOC::ACK_REPORT, CRC_FAILURE);
disableAllReplies();
return IGNORE_REPLY_DATA;
}
uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK;
switch(apid) {
case PLOC::APID_ACK_FAILURE: {
//TODO: Interpretation of status field in acknowledgment report
sif::debug << "PlocHandler::handleAckReport: Received Ack failure report" << std::endl;
DeviceCommandId_t commandId = getPendingCommand();
if (commandId != DeviceHandlerIF::NO_COMMAND_ID) {
triggerEvent(ACK_FAILURE, commandId);
}
sendFailureReport(PLOC::ACK_REPORT, RECEIVED_ACK_FAILURE);
disableAllReplies();
nextReplyId = PLOC::NONE;
result = IGNORE_REPLY_DATA;
break;
}
case PLOC::APID_ACK_SUCCESS: {
setNextReplyId();
break;
}
default: {
sif::debug << "PlocHandler::handleAckReport: Invalid APID in Ack report" << std::endl;
result = RETURN_FAILED;
break;
}
}
return result;
}
ReturnValue_t PlocHandler::handleExecutionReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
result = verifyPacket(data, PLOC::SIZE_EXE_REPORT);
if(result == CRC_FAILURE) {
sif::error << "PlocHandler::handleExecutionReport: CRC failure" << std::endl;
nextReplyId = PLOC::NONE;
return result;
}
uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK;
switch (apid) {
case (PLOC::APID_EXE_SUCCESS): {
break;
}
case (PLOC::APID_EXE_FAILURE): {
//TODO: Interpretation of status field in execution report
sif::error << "PlocHandler::handleExecutionReport: Received execution failure report"
<< std::endl;
DeviceCommandId_t commandId = getPendingCommand();
if (commandId != DeviceHandlerIF::NO_COMMAND_ID) {
triggerEvent(EXE_FAILURE, commandId);
}
else {
sif::debug << "PlocHandler::handleExecutionReport: Unknown command id" << std::endl;
}
sendFailureReport(PLOC::EXE_REPORT, RECEIVED_EXE_FAILURE);
disableExeReportReply();
result = IGNORE_REPLY_DATA;
break;
}
default: {
sif::error << "PlocHandler::handleExecutionReport: Unknown APID" << std::endl;
result = RETURN_FAILED;
break;
}
}
nextReplyId = PLOC::NONE;
return result;
}
ReturnValue_t PlocHandler::handleMemoryReadReport(const uint8_t* data) {
ReturnValue_t result = RETURN_OK;
result = verifyPacket(data, PLOC::SIZE_TM_MEM_READ_REPORT);
if(result == CRC_FAILURE) {
sif::error << "PlocHandler::handleMemoryReadReport: Memory read report has invalid crc"
<< std::endl;
}
/** Send data to commanding queue */
handleDeviceTM(data + PLOC::DATA_FIELD_OFFSET, PLOC::SIZE_MEM_READ_REPORT_DATA,
PLOC::TM_MEMORY_READ_REPORT);
nextReplyId = PLOC::EXE_REPORT;
return result;
}
ReturnValue_t PlocHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies, bool useAlternateId,
DeviceCommandId_t alternateReplyID) {
ReturnValue_t result = RETURN_OK;
uint8_t enabledReplies = 0;
switch (command->first) {
case PLOC::TC_MEM_WRITE:
enabledReplies = 2;
break;
case PLOC::TC_MEM_READ: {
enabledReplies = 3;
result = DeviceHandlerBase::enableReplyInReplyMap(command, enabledReplies, true,
PLOC::TM_MEMORY_READ_REPORT);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id "
<< PLOC::TM_MEMORY_READ_REPORT << " not in replyMap" << std::endl;
}
break;
}
default:
sif::debug << "PlocHandler::enableReplyInReplyMap: Unknown command id" << std::endl;
break;
}
/**
* Every command causes at least one acknowledgment and one execution report. Therefore both
* replies will be enabled here.
*/
result = DeviceHandlerBase::enableReplyInReplyMap(command,
enabledReplies, true, PLOC::ACK_REPORT);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " << PLOC::ACK_REPORT
<< " not in replyMap" << std::endl;
}
result = DeviceHandlerBase::enableReplyInReplyMap(command,
enabledReplies, true, PLOC::EXE_REPORT);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::enableReplyInReplyMap: Reply with id " << PLOC::EXE_REPORT
<< " not in replyMap" << std::endl;
}
return RETURN_OK;
}
void PlocHandler::setNextReplyId() {
switch(getPendingCommand()) {
case PLOC::TC_MEM_READ:
nextReplyId = PLOC::TM_MEMORY_READ_REPORT;
break;
default:
/* If no telemetry is expected the next reply is always the execution report */
nextReplyId = PLOC::EXE_REPORT;
break;
}
}
size_t PlocHandler::getNextReplyLength(DeviceCommandId_t commandId){
size_t replyLen = 0;
if (nextReplyId == PLOC::NONE) {
return replyLen;
}
DeviceReplyIter iter = deviceReplyMap.find(nextReplyId);
if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles == 0) {
/* Reply inactive */
return replyLen;
}
replyLen = iter->second.replyLen;
}
else {
sif::debug << "PlocHandler::getNextReplyLength: No entry for reply with reply id "
<< std::hex << nextReplyId << " in deviceReplyMap" << std::endl;
}
return replyLen;
}
void PlocHandler::handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) {
ReturnValue_t result = RETURN_OK;
if (wiretappingMode == RAW) {
/* Data already sent in doGetRead() */
return;
}
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
sif::debug << "PlocHandler::handleDeviceTM: Unknown reply id" << std::endl;
return;
}
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
if (queueId == NO_COMMANDER) {
return;
}
result = actionHelper.reportData(queueId, replyId, data, dataSize);
if (result != RETURN_OK) {
sif::debug << "PlocHandler::handleDeviceTM: Failed to report data" << std::endl;
}
}
void PlocHandler::disableAllReplies() {
DeviceReplyMap::iterator iter;
/* Disable ack reply */
iter = deviceReplyMap.find(PLOC::ACK_REPORT);
DeviceReplyInfo *info = &(iter->second);
info->delayCycles = 0;
info->command = deviceCommandMap.end();
DeviceCommandId_t commandId = getPendingCommand();
/* If the command expects a telemetry packet the appropriate tm reply will be disabled here */
switch (commandId) {
case PLOC::TC_MEM_WRITE:
break;
case PLOC::TC_MEM_READ: {
iter = deviceReplyMap.find(PLOC::TM_MEMORY_READ_REPORT);
info = &(iter->second);
info->delayCycles = 0;
info->command = deviceCommandMap.end();
break;
}
default: {
sif::debug << "PlocHandler::disableAllReplies: Unknown command id" << commandId
<< std::endl;
break;
}
}
/* We must always disable the execution report reply here */
disableExeReportReply();
}
void PlocHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) {
DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
sif::debug << "PlocHandler::sendFailureReport: Reply not in reply map" << std::endl;
return;
}
DeviceCommandInfo* info = &(iter->second.command->second);
if (info == nullptr) {
sif::debug << "PlocHandler::sendFailureReport: Reply has no active command" << std::endl;
return;
}
if (info->sendReplyTo != NO_COMMANDER) {
actionHelper.finish(false, info->sendReplyTo, iter->first, status);
}
info->isExecuting = false;
}
void PlocHandler::disableExeReportReply() {
DeviceReplyIter iter = deviceReplyMap.find(PLOC::EXE_REPORT);
DeviceReplyInfo *info = &(iter->second);
info->delayCycles = 0;
info->command = deviceCommandMap.end();
/* Expected replies is set to one here. The value will set to 0 in replyToReply() */
info->command->second.expectedReplies = 0;
}
ReturnValue_t PlocHandler::checkPacketSequenceCount(const uint8_t* data) {
uint16_t receivedSequenceCount = (*(data + 2) << 8 | *(data + 3)) & PACKET_SEQUENCE_COUNT_MASK;
uint16_t expectedPacketSequenceCount = ((packetSequenceCount + 1) & PACKET_SEQUENCE_COUNT_MASK);
if (receivedSequenceCount != expectedPacketSequenceCount) {
sif::debug
<< "PlocHandler::checkPacketSequenceCount: Packet sequence count mismatch. "
<< std::endl;
sif::debug << "Received sequence count: " << receivedSequenceCount << ". OBSW sequence "
<< "count: " << expectedPacketSequenceCount << std::endl;
}
packetSequenceCount = receivedSequenceCount;
return RETURN_OK;
}

View File

@ -0,0 +1,201 @@
#ifndef MISSION_DEVICES_PLOCHANDLER_H_
#define MISSION_DEVICES_PLOCHANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/devices/devicedefinitions/PlocDefinitions.h>
#include <string.h>
/**
* @brief This is the device handler for the PLOC.
*
* @details The PLOC uses the space packet protocol for communication. To each command the PLOC
* answers with at least one acknowledgment and one execution report.
*
* @author J. Meier
*/
class PlocHandler: public DeviceHandlerBase {
public:
PlocHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie);
virtual ~PlocHandler();
/**
* @brief Sets mode to MODE_NORMAL. Can be used for debugging.
*/
void setModeNormal();
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData,size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0) override;
size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_HANDLER;
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); //!> Space Packet received from PLOC has invalid CRC
static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); //!> Received ACK failure reply from PLOC
static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); //!> Received execution failure reply from PLOC
static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); //!> Received space packet with invalid APID from PLOC
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_HANDLER;
static const Event MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); //!> PLOC crc failure in telemetry packet
static const Event ACK_FAILURE = MAKE_EVENT(2, severity::LOW); //!> PLOC receive acknowledgment failure report
static const Event EXE_FAILURE = MAKE_EVENT(3, severity::LOW); //!> PLOC receive execution failure report
static const Event CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW); //!> PLOC reply has invalid crc
static const uint16_t APID_MASK = 0x7FF;
static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF;
uint8_t commandBuffer[PLOC::MAX_COMMAND_SIZE];
/**
* @brief This object is incremented each time a packet is sent or received. By checking the
* packet sequence count of a received packet, no packets can be lost without noticing
* it. Only the least significant 14 bits represent the packet sequence count in a
* space packet. Thus the maximum value amounts to 16383 (0x3FFF).
* @note Normally this should never happen because the PLOC replies are always sent in a
* fixed order. However, the PLOC software checks this value and will return an ACK
* failure report in case the sequence count is not incremented with each transferred
* space packet.
*/
uint16_t packetSequenceCount = 0x3FFF;
/**
* This variable is used to store the id of the next reply to receive. This is necessary
* because the PLOC sends as reply to each command at least one acknowledgment and execution
* report.
*/
DeviceCommandId_t nextReplyId = PLOC::NONE;
/**
* @brief This function fills the commandBuffer to initiate the write memory command.
*
* @param commandData Pointer to action command data.
* @param commanDataLen Size of command data in bytes.
*
* @return RETURN_OK if successful, else RETURN_FAILURE.
*/
ReturnValue_t prepareTcMemWriteCommand(const uint8_t * commandData, size_t commandDataLen);
/**
* @brief This function fills the commandBuffer to initiate the write reads command.
*
* @param commandData Pointer to action command data.
* @param commanDataLen Size of command data in bytes.
*
* @return RETURN_OK if successful, else RETURN_FAILURE.
*/
ReturnValue_t prepareTcMemReadCommand(const uint8_t * commandData, size_t commandDataLen);
/**
* @brief This function checks the crc of the received PLOC reply.
*
* @param start Pointer to the first byte of the reply.
* @param foundLen Pointer to the length of the whole packet.
*
* @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE.
*/
ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen);
/**
* @brief This function handles the acknowledgment report.
*
* @param data Pointer to the data holding the acknowledgment report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleAckReport(const uint8_t* data);
/**
* @brief This function handles the data of a execution report.
*
* @param data Pointer to the received data packet.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleExecutionReport(const uint8_t* data);
/**
* @brief This function handles the memory read report.
*
* @param data Pointer to the data buffer holding the memory read report.
*
* @return RETURN_OK if successful, otherwise an error code.
*/
ReturnValue_t handleMemoryReadReport(const uint8_t* data);
/**
* @brief Depending on the current active command, this function sets the reply id of the
* next reply after a successful acknowledgment report has been received. This is
* required by the function getNextReplyLength() to identify the length of the next
* reply to read.
*/
void setNextReplyId();
/**
* @brief This function handles action message replies in case the telemetry has been
* requested by another object.
*
* @param data Pointer to the telemetry data.
* @param dataSize Size of telemetry in bytes.
* @param replyId Id of the reply. This will be added to the ActionMessage.
*/
void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId);
/**
* @brief In case an acknowledgment failure reply has been received this function disables
* all previously enabled commands and resets the exepected replies variable of an
* active command.
*/
void disableAllReplies();
/**
* @brief This function sends a failure report if the active action was commanded by an other
* object.
*
* @param replyId The id of the reply which signals a failure.
* @param status A status byte which gives information about the failure type.
*/
void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status);
/**
* @brief This function disables the execution report reply. Within this function also the
* the variable expectedReplies of an active command will be set to 0.
*/
void disableExeReportReply();
/**
* @brief This function checks and increments the packet sequence count of a received space
* packet.
*
* @param data Pointer to a space packet.
*
* @return RETURN_OK if successful
*
* @details There should be never a case in which a wrong packet sequence count is received
* because the communication scheme between PLOC and OBC always follows a strict
* procedure. Thus this function mainly serves for debugging purposes to detected an
* invalid handling of the packet sequence count.
*/
ReturnValue_t checkPacketSequenceCount(const uint8_t* data);
};
#endif /* MISSION_DEVICES_PLOCHANDLER_H_ */

View File

@ -0,0 +1,158 @@
#include <fsfw/datapool/PoolReadGuard.h>
#include <mission/devices/RadiationSensorHandler.h>
#include <OBSWConfig.h>
RadiationSensorHandler::RadiationSensorHandler(object_id_t objectId, object_id_t comIF,
CookieIF * comCookie) :
DeviceHandlerBase(objectId, comIF, comCookie), dataset(
this) {
if (comCookie == NULL) {
sif::error << "RadiationSensorHandler: Invalid com cookie" << std::endl;
}
}
RadiationSensorHandler::~RadiationSensorHandler() {
}
void RadiationSensorHandler::doStartUp(){
if (internalState == InternalState::CONFIGURED) {
#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1
setMode(MODE_NORMAL);
#else
setMode(_MODE_TO_ON);
#endif
}
}
void RadiationSensorHandler::doShutDown(){
setMode(_MODE_POWER_DOWN);
}
ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(
DeviceCommandId_t * id) {
switch (communicationStep) {
case CommunicationStep::START_CONVERSION: {
*id = RAD_SENSOR::START_CONVERSION;
communicationStep = CommunicationStep::READ_CONVERSIONS;
break;
}
case CommunicationStep::READ_CONVERSIONS: {
*id = RAD_SENSOR::READ_CONVERSIONS;
communicationStep = CommunicationStep::START_CONVERSION;
break;
}
default: {
sif::debug << "RadiationSensorHandler::buildNormalDeviceCommand: Unknwon communication "
<< "step" << std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
}
return buildCommandFromCommand(*id, nullptr, 0);
}
ReturnValue_t RadiationSensorHandler::buildTransitionDeviceCommand(
DeviceCommandId_t * id){
if (internalState == InternalState::SETUP) {
*id = RAD_SENSOR::WRITE_SETUP;
}
else {
return HasReturnvaluesIF::RETURN_OK;
}
return buildCommandFromCommand(*id, nullptr, 0);
}
ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t * commandData,
size_t commandDataLen) {
switch(deviceCommand) {
case(RAD_SENSOR::WRITE_SETUP): {
cmdBuffer[0] = RAD_SENSOR::SETUP_DEFINITION;
rawPacket = cmdBuffer;
rawPacketLen = 1;
internalState = InternalState::CONFIGURED;
return RETURN_OK;
}
case(RAD_SENSOR::START_CONVERSION): {
/* First the fifo will be reset here */
cmdBuffer[0] = RAD_SENSOR::RESET_DEFINITION;
cmdBuffer[1] = RAD_SENSOR::CONVERSION_DEFINITION;
rawPacket = cmdBuffer;
rawPacketLen = 2;
return RETURN_OK;
}
case(RAD_SENSOR::READ_CONVERSIONS): {
cmdBuffer[0] = RAD_SENSOR::DUMMY_BYTE;
cmdBuffer[1] = RAD_SENSOR::DUMMY_BYTE;
cmdBuffer[2] = RAD_SENSOR::DUMMY_BYTE;
cmdBuffer[3] = RAD_SENSOR::DUMMY_BYTE;
cmdBuffer[4] = RAD_SENSOR::DUMMY_BYTE;
cmdBuffer[5] = RAD_SENSOR::DUMMY_BYTE;
rawPacket = cmdBuffer;
rawPacketLen = RAD_SENSOR::READ_SIZE;
return RETURN_OK;
}
default:
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return HasReturnvaluesIF::RETURN_FAILED;
}
void RadiationSensorHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(RAD_SENSOR::WRITE_SETUP);
this->insertInCommandMap(RAD_SENSOR::START_CONVERSION);
this->insertInCommandAndReplyMap(RAD_SENSOR::READ_CONVERSIONS, 1, &dataset,
RAD_SENSOR::READ_SIZE);
}
ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start,
size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) {
*foundId = this->getPendingCommand();
*foundLen = remainingSize;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
switch (id) {
case RAD_SENSOR::READ_CONVERSIONS: {
PoolReadGuard readSet(&dataset);
dataset.temperatureCelcius = (*(packet) << 8 | *(packet + 1)) * 0.125;
dataset.channel0 = (*(packet + 2) << 8 | *(packet + 3));
dataset.channel1 = (*(packet + 4) << 8 | *(packet + 5));
#if OBSW_VERBOSE_LEVEL >= 1 && DEBUG_RAD_SENSOR
sif::info << "Radiation sensor temperature: " << dataset.temperatureCelcius << " °C"
<< std::endl;
sif::info << "Radiation sensor temperature ADC value channel 0: " << dataset.channel0
<< std::endl;
sif::info << "Radiation sensor temperature ADC value channel 1: " << dataset.channel1
<< std::endl;
#endif
break;
}
default: {
sif::debug << "RadiationSensorHandler::interpretDeviceReply: Unknown reply id" << std::endl;
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void RadiationSensorHandler::setNormalDatapoolEntriesInvalid(){
}
uint32_t RadiationSensorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){
return 5000;
}
ReturnValue_t RadiationSensorHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(RAD_SENSOR::TEMPERATURE_C, new PoolEntry<float>( { 0.0 }));
localDataPoolMap.emplace(RAD_SENSOR::CHANNEL_0, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(RAD_SENSOR::CHANNEL_1, new PoolEntry<uint16_t>( { 0 }));
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,60 @@
#ifndef MISSION_DEVICES_RADIATIONSENSORHANDLER_H_
#define MISSION_DEVICES_RADIATIONSENSORHANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/devices/devicedefinitions/RadSensorDefinitions.h>
/**
* @brief This is the device handler class for radiation sensor on the OBC IF Board. The sensor
* is based on the MAX1227 ADC converter.
*
* @details Datasheet of MAX1227: https://datasheets.maximintegrated.com/en/ds/MAX1227-MAX1231.pdf
*
* @author J. Meier
*/
class RadiationSensorHandler: public DeviceHandlerBase {
public:
RadiationSensorHandler(object_id_t objectId, object_id_t comIF,
CookieIF * comCookie);
virtual ~RadiationSensorHandler();
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData,size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
private:
enum class CommunicationStep {
START_CONVERSION,
READ_CONVERSIONS
};
enum class InternalState {
SETUP,
CONFIGURED
};
RAD_SENSOR::RadSensorDataset dataset;
static const uint8_t MAX_CMD_LEN = RAD_SENSOR::READ_SIZE;
uint8_t cmdBuffer[MAX_CMD_LEN];
InternalState internalState = InternalState::SETUP;
CommunicationStep communicationStep = CommunicationStep::START_CONVERSION;
};
#endif /* MISSION_DEVICES_RADIATIONSENSORHANDLER_H_ */

View File

@ -0,0 +1,229 @@
#include <fsfw/datapool/PoolReadGuard.h>
#include <mission/devices/SusHandler.h>
#include <OBSWConfig.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
SusHandler::SusHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie,
LinuxLibgpioIF* gpioComIF, gpioId_t chipSelectId) :
DeviceHandlerBase(objectId, comIF, comCookie), gpioComIF(gpioComIF), chipSelectId(
chipSelectId), dataset(this) {
if (comCookie == NULL) {
sif::error << "SusHandler: Invalid com cookie" << std::endl;
}
if (gpioComIF == NULL) {
sif::error << "SusHandler: Invalid GpioComIF" << std::endl;
}
}
SusHandler::~SusHandler() {
}
ReturnValue_t SusHandler::performOperation(uint8_t counter) {
if (counter != FIRST_WRITE) {
DeviceHandlerBase::performOperation(counter);
return RETURN_OK;
}
if (mode != MODE_NORMAL) {
DeviceHandlerBase::performOperation(DeviceHandlerIF::SEND_WRITE);
return RETURN_OK;
}
/* If device is in normale mode the communication sequence is initiated here */
if (communicationStep == CommunicationStep::IDLE) {
communicationStep = CommunicationStep::WRITE_SETUP;
}
DeviceHandlerBase::performOperation(DeviceHandlerIF::SEND_WRITE);
return RETURN_OK;
}
ReturnValue_t SusHandler::initialize() {
ReturnValue_t result = RETURN_OK;
result = DeviceHandlerBase::initialize();
if (result != RETURN_OK) {
return result;
}
auto spiComIF = dynamic_cast<SpiComIF*>(communicationInterface);
if (spiComIF == nullptr) {
sif::debug << "SusHandler::initialize: Invalid communication interface" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
spiMutex = spiComIF->getMutex();
if (spiMutex == nullptr) {
sif::debug << "SusHandler::initialize: Failed to get spi mutex" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return RETURN_OK;
}
void SusHandler::doStartUp(){
#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1
setMode(MODE_NORMAL);
#else
setMode(_MODE_TO_ON);
#endif
}
void SusHandler::doShutDown(){
setMode(_MODE_POWER_DOWN);
}
ReturnValue_t SusHandler::buildNormalDeviceCommand(
DeviceCommandId_t * id) {
if (communicationStep == CommunicationStep::IDLE) {
return NOTHING_TO_SEND;
}
if (communicationStep == CommunicationStep::WRITE_SETUP) {
*id = SUS::WRITE_SETUP;
communicationStep = CommunicationStep::START_CONVERSIONS;
}
else if (communicationStep == CommunicationStep::START_CONVERSIONS) {
*id = SUS::START_CONVERSIONS;
communicationStep = CommunicationStep::READ_CONVERSIONS;
}
else if (communicationStep == CommunicationStep::READ_CONVERSIONS) {
*id = SUS::READ_CONVERSIONS;
communicationStep = CommunicationStep::IDLE;
}
return buildCommandFromCommand(*id, nullptr, 0);
}
ReturnValue_t SusHandler::buildTransitionDeviceCommand(
DeviceCommandId_t * id){
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t SusHandler::buildCommandFromCommand(
DeviceCommandId_t deviceCommand, const uint8_t * commandData,
size_t commandDataLen) {
switch(deviceCommand) {
case(SUS::WRITE_SETUP): {
/**
* The sun sensor ADC is shutdown when CS is pulled high, so each time requesting a
* measurement the setup has to be rewritten. There must also be a little delay between
* the transmission of the setup byte and the first conversion. Thus the conversion
* will be performed in an extra step.
* Because the chip select is driven manually by the SusHandler the SPI bus must be
* protected with a mutex here.
*/
ReturnValue_t result = spiMutex->lockMutex(timeoutType, timeoutMs);
if(result == MutexIF::MUTEX_TIMEOUT) {
sif::error << "SusHandler::buildCommandFromCommand: Mutex timeout" << std::endl;
return ERROR_LOCK_MUTEX;
}
else if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "SusHandler::buildCommandFromCommand: Failed to lock spi mutex"
<< std::endl;
return ERROR_LOCK_MUTEX;
}
gpioComIF->pullLow(chipSelectId);
cmdBuffer[0] = SUS::SETUP;
rawPacket = cmdBuffer;
rawPacketLen = 1;
return RETURN_OK;
}
case(SUS::START_CONVERSIONS): {
std::memset(cmdBuffer, 0, sizeof(cmdBuffer));
cmdBuffer[0] = SUS::CONVERSION;
rawPacket = cmdBuffer;
rawPacketLen = 2;
return RETURN_OK;
}
case(SUS::READ_CONVERSIONS): {
std::memset(cmdBuffer, 0, sizeof(cmdBuffer));
rawPacket = cmdBuffer;
rawPacketLen = SUS::SIZE_READ_CONVERSIONS;
return RETURN_OK;
}
default:
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return HasReturnvaluesIF::RETURN_FAILED;
}
void SusHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(SUS::WRITE_SETUP);
this->insertInCommandMap(SUS::START_CONVERSIONS);
this->insertInCommandAndReplyMap(SUS::READ_CONVERSIONS, 1, &dataset, SUS::SIZE_READ_CONVERSIONS);
}
ReturnValue_t SusHandler::scanForReply(const uint8_t *start,
size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) {
*foundId = this->getPendingCommand();
*foundLen = remainingSize;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t SusHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
switch (id) {
case SUS::READ_CONVERSIONS: {
PoolReadGuard readSet(&dataset);
dataset.temperatureCelcius = (*(packet) << 8 | *(packet + 1)) * 0.125;
dataset.ain0 = (*(packet + 2) << 8 | *(packet + 3));
dataset.ain1 = (*(packet + 4) << 8 | *(packet + 5));
dataset.ain2 = (*(packet + 6) << 8 | *(packet + 7));
dataset.ain3 = (*(packet + 8) << 8 | *(packet + 9));
dataset.ain4 = (*(packet + 10) << 8 | *(packet + 11));
dataset.ain5 = (*(packet + 12) << 8 | *(packet + 13));
#if OBSW_VERBOSE_LEVEL >= 1 && DEBUG_SUS
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", Temperature: "
<< dataset.temperatureCelcius << " °C" << std::endl;
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", AIN0: "
<< std::dec << dataset.ain0 << std::endl;
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", AIN1: "
<< std::dec << dataset.ain1 << std::endl;
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", AIN2: "
<< std::dec << dataset.ain2 << std::endl;
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", AIN3: "
<< std::dec << dataset.ain3 << std::endl;
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", AIN4: "
<< std::dec << dataset.ain4 << std::endl;
sif::info << "SUS object id 0x" << std::hex << this->getObjectId() << ", AIN5: "
<< std::dec << dataset.ain5 << std::endl;
#endif
/** SUS can now be shutdown and thus the SPI bus released again */
gpioComIF->pullHigh(chipSelectId);
ReturnValue_t result = spiMutex->unlockMutex();
if (result != RETURN_OK) {
sif::error << "SusHandler::interpretDeviceReply: Failed to unlock spi mutex"
<< std::endl;
return ERROR_UNLOCK_MUTEX;
}
break;
}
default: {
sif::debug << "SusHandler::interpretDeviceReply: Unknown reply id" << std::endl;
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void SusHandler::setNormalDatapoolEntriesInvalid(){
}
uint32_t SusHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){
return 1000;
}
ReturnValue_t SusHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(SUS::TEMPERATURE_C, new PoolEntry<float>( { 0.0 }));
localDataPoolMap.emplace(SUS::AIN0, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(SUS::AIN1, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(SUS::AIN2, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(SUS::AIN3, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(SUS::AIN4, new PoolEntry<uint16_t>( { 0 }));
localDataPoolMap.emplace(SUS::AIN5, new PoolEntry<uint16_t>( { 0 }));
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,81 @@
#ifndef MISSION_DEVICES_SUSHANDLER_H_
#define MISSION_DEVICES_SUSHANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/devices/devicedefinitions/SusDefinitions.h>
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include <fsfw/ipc/MutexGuard.h>
/**
* @brief This is the device handler class for the SUS sensor. The sensor is
* based on the MAX1227 ADC. Details about the SUS electronic can be found at
* https://egit.irs.uni-stuttgart.de/eive/eive_dokumente/src/branch/master/400_Raumsegment/443_SunSensorDocumentation/release
*
* @details Datasheet of MAX1227: https://datasheets.maximintegrated.com/en/ds/MAX1227-MAX1231.pdf
*
* @note When adding a SusHandler to the polling sequence table make sure to add a slot with
* the executionStep FIRST_WRITE. Otherwise the communication sequence will never be
* started.
*
* @author J. Meier
*/
class SusHandler: public DeviceHandlerBase {
public:
static const uint8_t FIRST_WRITE = 7;
SusHandler(object_id_t objectId, object_id_t comIF,
CookieIF * comCookie, LinuxLibgpioIF* gpioComIF, gpioId_t chipSelectId);
virtual ~SusHandler();
virtual ReturnValue_t performOperation(uint8_t counter) override;
virtual ReturnValue_t initialize() override;
protected:
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
void fillCommandAndReplyMap() override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData,size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) override;
void setNormalDatapoolEntriesInvalid() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
private:
static const uint8_t INTERFACE_ID = CLASS_ID::SUS_HANDLER;
static const ReturnValue_t ERROR_UNLOCK_MUTEX = MAKE_RETURN_CODE(0xA0);
static const ReturnValue_t ERROR_LOCK_MUTEX = MAKE_RETURN_CODE(0xA1);
enum class CommunicationStep {
IDLE,
WRITE_SETUP,
START_CONVERSIONS,
READ_CONVERSIONS
};
LinuxLibgpioIF* gpioComIF = nullptr;
gpioId_t chipSelectId = gpio::NO_GPIO;
SUS::SusDataset dataset;
uint8_t cmdBuffer[SUS::MAX_CMD_SIZE];
CommunicationStep communicationStep = CommunicationStep::IDLE;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
MutexIF* spiMutex = nullptr;
};
#endif /* MISSION_DEVICES_SUSHANDLER_H_ */

View File

@ -6,46 +6,74 @@ namespace IMTQ {
static const DeviceCommandId_t NONE = 0x0; static const DeviceCommandId_t NONE = 0x0;
static const DeviceCommandId_t GET_ENG_HK_DATA = 0x1; static const DeviceCommandId_t GET_ENG_HK_DATA = 0x1;
static const DeviceCommandId_t START_ACTUATION_DIPOLE = 0x2; static const DeviceCommandId_t START_ACTUATION_DIPOLE = 0x2;
static const DeviceCommandId_t GET_COMMANDED_DIPOLE = 0x3;
/** Generates new measurement of the magnetic field */
static const DeviceCommandId_t START_MTM_MEASUREMENT = 0x4;
/** Requests the calibrated magnetometer measurement */
static const DeviceCommandId_t GET_CAL_MTM_MEASUREMENT = 0x5;
/** Requests the raw values measured by the built-in MTM XEN1210 */
static const DeviceCommandId_t GET_RAW_MTM_MEASUREMENT = 0x6;
static const DeviceCommandId_t SELF_TEST = 0x7;
static const uint8_t GET_TEMP_REPLY_SIZE = 2; static const uint8_t GET_TEMP_REPLY_SIZE = 2;
static const uint8_t CFGR_CMD_SIZE = 3; static const uint8_t CFGR_CMD_SIZE = 3;
static const uint8_t POINTER_REG_SIZE = 1; static const uint8_t POINTER_REG_SIZE = 1;
static const uint32_t ENG_HK_DATA_SET_ID = GET_ENG_HK_DATA; static const uint32_t ENG_HK_DATA_SET_ID = GET_ENG_HK_DATA;
static const uint32_t CAL_MTM_SET = GET_CAL_MTM_MEASUREMENT;
static const uint8_t SIZE_ENG_HK_COMMAND = 1; static const uint8_t SIZE_ENG_HK_COMMAND = 1;
static const uint8_t SIZE_STATUS_REPLY = 2;
static const uint8_t SIZE_ENG_HK_DATA_REPLY = 24; static const uint8_t SIZE_ENG_HK_DATA_REPLY = 24;
static const uint8_t SIZE_GET_COMMANDED_DIPOLE_REPLY = 8;
static const uint8_t SIZE_GET_CAL_MTM_MEASUREMENT = 15;
static const uint8_t SIZE_GET_RAW_MTM_MEASUREMENT = 15;
static const uint8_t MAX_REPLY_SIZE = SIZE_ENG_HK_DATA_REPLY; static const uint8_t MAX_REPLY_SIZE = SIZE_ENG_HK_DATA_REPLY;
static const uint8_t MAX_COMMAND_SIZE = 9; static const uint8_t MAX_COMMAND_SIZE = 9;
static const uint8_t POOL_ENTRIES = 11; /** Define entries in IMTQ specific dataset */
static const uint8_t ENG_HK_SET_POOL_ENTRIES = 11;
static const uint8_t CAL_MTM_POOL_ENTRIES = 4;
/** /**
* Command code definitions. Each command or reply of an IMTQ request will begin with one of * Command code definitions. Each command or reply of an IMTQ request will begin with one of
* the following command codes. * the following command codes.
*/ */
namespace CC { namespace CC {
static const uint8_t START_MTM_MEASUREMENT = 0x4;
static const uint8_t START_ACTUATION_DIPOLE = 0x6; static const uint8_t START_ACTUATION_DIPOLE = 0x6;
static const uint8_t SOFTWARE_RESET = 0xAA; static const uint8_t SOFTWARE_RESET = 0xAA;
static const uint8_t GET_ENG_HK_DATA = 0x4A; static const uint8_t GET_ENG_HK_DATA = 0x4A;
static const uint8_t GET_COMMANDED_DIPOLE = 0x46;
static const uint8_t GET_RAW_MTM_MEASUREMENT = 0x42;
static const uint8_t GET_CAL_MTM_MEASUREMENT = 0x43;
}; };
enum IMTQPoolIds: lp_id_t { enum IMTQPoolIds: lp_id_t {
DIGITAL_VOLTAGE_MV, DIGITAL_VOLTAGE_MV,
ANALOG_VOLTAGE_MV, ANALOG_VOLTAGE_MV,
DIGITAL_CURRENT_A, DIGITAL_CURRENT,
ANALOG_CURRENT_A, ANALOG_CURRENT,
COIL_X_CURRENT_A, COIL_X_CURRENT,
COIL_Y_CURRENT_A, COIL_Y_CURRENT,
COIL_Z_CURRENT_A, COIL_Z_CURRENT,
COIL_X_TEMPERATURE, COIL_X_TEMPERATURE,
COIL_Y_TEMPERATURE, COIL_Y_TEMPERATURE,
COIL_Z_TEMPERATURE, COIL_Z_TEMPERATURE,
MCU_TEMPERATURE MCU_TEMPERATURE,
MTM_CAL_X,
MTM_CAL_Y,
MTM_CAL_Z,
ACTUATION_CAL_STATUS,
MTM_RAW_X,
MTM_RAW_Y,
MTM_RAW_Z,
ACTUATION_RAW_STATUS
}; };
class EngHkDataset: class EngHkDataset:
public StaticLocalDataSet<POOL_ENTRIES> { public StaticLocalDataSet<ENG_HK_SET_POOL_ENTRIES> {
public: public:
EngHkDataset(HasLocalDataPoolIF* owner): EngHkDataset(HasLocalDataPoolIF* owner):
@ -60,16 +88,16 @@ public:
DIGITAL_VOLTAGE_MV, this); DIGITAL_VOLTAGE_MV, this);
lp_var_t<uint16_t> analogVoltageMv = lp_var_t<uint16_t>(sid.objectId, lp_var_t<uint16_t> analogVoltageMv = lp_var_t<uint16_t>(sid.objectId,
ANALOG_VOLTAGE_MV, this); ANALOG_VOLTAGE_MV, this);
lp_var_t<float> digitalCurrentA = lp_var_t<float>(sid.objectId, lp_var_t<float> digitalCurrentmA = lp_var_t<float>(sid.objectId,
DIGITAL_CURRENT_A, this); DIGITAL_CURRENT, this);
lp_var_t<float> analogCurrentA = lp_var_t<float>(sid.objectId, lp_var_t<float> analogCurrentmA = lp_var_t<float>(sid.objectId,
ANALOG_CURRENT_A, this); ANALOG_CURRENT, this);
lp_var_t<float> coilXcurrentA = lp_var_t<float>(sid.objectId, lp_var_t<float> coilXCurrentmA = lp_var_t<float>(sid.objectId,
COIL_X_CURRENT_A, this); COIL_X_CURRENT, this);
lp_var_t<float> coilYcurrentA = lp_var_t<float>(sid.objectId, lp_var_t<float> coilYCurrentmA = lp_var_t<float>(sid.objectId,
COIL_Y_CURRENT_A, this); COIL_Y_CURRENT, this);
lp_var_t<float> coilZcurrentA = lp_var_t<float>(sid.objectId, lp_var_t<float> coilZCurrentmA = lp_var_t<float>(sid.objectId,
COIL_Z_CURRENT_A, this); COIL_Z_CURRENT, this);
/** All temperatures in [°C] */ /** All temperatures in [°C] */
lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId, lp_var_t<uint16_t> coilXTemperature = lp_var_t<uint16_t>(sid.objectId,
COIL_X_TEMPERATURE, this); COIL_X_TEMPERATURE, this);
@ -81,6 +109,60 @@ public:
MCU_TEMPERATURE, this); MCU_TEMPERATURE, this);
}; };
/**
* @brief This dataset holds the raw MTM measurements.
*/
class CalibratedMtmMeasurementSet:
public StaticLocalDataSet<CAL_MTM_POOL_ENTRIES> {
public:
CalibratedMtmMeasurementSet(HasLocalDataPoolIF* owner):
StaticLocalDataSet(owner, CAL_MTM_SET) {
}
CalibratedMtmMeasurementSet(object_id_t objectId):
StaticLocalDataSet(sid_t(objectId, CAL_MTM_SET)) {
}
/** The unit of all measurements is nT */
lp_var_t<int32_t> mtmXnT = lp_var_t<int32_t>(sid.objectId,
MTM_CAL_X, this);
lp_var_t<int32_t> mtmYnT = lp_var_t<int32_t>(sid.objectId,
MTM_CAL_Y, this);
lp_var_t<int32_t> mtmZnT = lp_var_t<int32_t>(sid.objectId,
MTM_CAL_Z, this);
/** 1 if coils were actuating during measurement otherwise 0 */
lp_var_t<uint8_t> coilActuationStatus = lp_var_t<uint8_t>(sid.objectId,
ACTUATION_CAL_STATUS, this);
};
/**
* @brief This dataset holds the last calibrated MTM measurement.
*/
class RawMtmMeasurementSet:
public StaticLocalDataSet<CAL_MTM_POOL_ENTRIES> {
public:
RawMtmMeasurementSet(HasLocalDataPoolIF* owner):
StaticLocalDataSet(owner, CAL_MTM_SET) {
}
RawMtmMeasurementSet(object_id_t objectId):
StaticLocalDataSet(sid_t(objectId, CAL_MTM_SET)) {
}
/** The unit of all measurements is nT */
lp_var_t<float> mtmXnT = lp_var_t<float>(sid.objectId,
MTM_RAW_X, this);
lp_var_t<float> mtmYnT = lp_var_t<float>(sid.objectId,
MTM_RAW_Y, this);
lp_var_t<float> mtmZnT = lp_var_t<float>(sid.objectId,
MTM_RAW_Z, this);
/** 1 if coils were actuating during measurement otherwise 0 */
lp_var_t<uint8_t> coilActuationStatus = lp_var_t<uint8_t>(sid.objectId,
ACTUATION_RAW_STATUS, this);
};
/** /**
* @brief This class can be used to ease the generation of an action message commanding the * @brief This class can be used to ease the generation of an action message commanding the
* IMTQHandler to configure the magnettorquer with the desired dipoles. * IMTQHandler to configure the magnettorquer with the desired dipoles.

View File

@ -12,7 +12,7 @@ namespace RM3100 {
/* Actually 10, we round up a little bit */ /* Actually 10, we round up a little bit */
static constexpr size_t MAX_BUFFER_SIZE = 12; static constexpr size_t MAX_BUFFER_SIZE = 12;
static constexpr uint8_t READ_MASK = 0b1000'0000; static constexpr uint8_t READ_MASK = 0x80;
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/* CMM Register */ /* CMM Register */
@ -45,7 +45,7 @@ static constexpr uint8_t TMRC_75HZ_VALUE = 0x95;
static constexpr uint8_t TMRC_DEFAULT_37HZ_VALUE = 0x96; static constexpr uint8_t TMRC_DEFAULT_37HZ_VALUE = 0x96;
static constexpr uint8_t TMRC_REGISTER = 0x0B; static constexpr uint8_t TMRC_REGISTER = 0x0B;
static constexpr uint8_t TMRC_DEFAULT_VALUE = TMRC_75HZ_VALUE; static constexpr uint8_t TMRC_DEFAULT_VALUE = TMRC_DEFAULT_37HZ_VALUE;
static constexpr uint8_t MEASUREMENT_REG_START = 0x24; static constexpr uint8_t MEASUREMENT_REG_START = 0x24;
static constexpr uint8_t BIST_REGISTER = 0x33; static constexpr uint8_t BIST_REGISTER = 0x33;

View File

@ -0,0 +1,172 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_
#include <fsfw/tmtcpacket/SpacePacket.h>
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/serialize/SerializeAdapter.h>
namespace PLOC {
static const DeviceCommandId_t NONE = 0x0;
static const DeviceCommandId_t TC_MEM_WRITE = 0x1;
static const DeviceCommandId_t TC_MEM_READ = 0x2;
static const DeviceCommandId_t ACK_REPORT = 0x3;
static const DeviceCommandId_t EXE_REPORT = 0x5;
static const DeviceCommandId_t TM_MEMORY_READ_REPORT = 0x6;
static const uint16_t SIZE_ACK_REPORT = 14;
static const uint16_t SIZE_EXE_REPORT = 14;
static const uint16_t SIZE_TM_MEM_READ_REPORT = 18;
/**
* SpacePacket apids of PLOC telecommands and telemetry.
*/
static const uint16_t APID_TC_MEM_WRITE = 0x714;
static const uint16_t APID_TC_MEM_READ = 0x715;
static const uint16_t APID_TM_MEMORY_READ_REPORT = 0x404;
static const uint16_t APID_ACK_SUCCESS = 0x400;
static const uint16_t APID_ACK_FAILURE = 0x401;
static const uint16_t APID_EXE_SUCCESS = 0x402;
static const uint16_t APID_EXE_FAILURE = 0x403;
/** Offset from first byte in Space packet to first byte of data field */
static const uint8_t DATA_FIELD_OFFSET = 6;
/**
* The size of payload data which will be forwarded to the requesting object. e.g. PUS Service
* 8.
*/
static const uint8_t SIZE_MEM_READ_REPORT_DATA = 10;
/**
* PLOC space packet length for fixed size packets. This is the size of the whole packet data
* field. For the length field in the space packet this size will be substracted by one.
*/
static const uint16_t LENGTH_TC_MEM_WRITE = 12;
static const uint16_t LENGTH_TC_MEM_READ = 8;
static const size_t MAX_REPLY_SIZE = SIZE_TM_MEM_READ_REPORT;
static const size_t MAX_COMMAND_SIZE = 18;
/**
* @brief This class helps to build the memory read command for the PLOC.
*
* @details The last two bytes of the packet data field contain a CRC calculated over the whole
* space packet. This is the CRC-16-CCITT as specified in
* ECSS-E-ST-70-41C Telemetry and telecommand packet utilization.
*/
class TcMemRead : public SpacePacket {
public:
/**
* @brief Constructor
*
* @param memAddr The memory address to read from.
*/
TcMemRead(const uint32_t memAddr, uint16_t sequenceCount) :
SpacePacket(LENGTH_TC_MEM_READ - 1, true, APID_TC_MEM_READ, sequenceCount) {
fillPacketDataField(&memAddr);
}
private:
/**
* @brief This function builds the packet data field for the mem read command.
*
* @param memAddrPtr Pointer to the memory address to read from.
*/
void fillPacketDataField(const uint32_t* memAddrPtr) {
/* Add memAddr to packet data field */
size_t serializedSize = 0;
uint8_t* memoryAddressPos = this->localData.fields.buffer;
SerializeAdapter::serialize<uint32_t>(memAddrPtr, &memoryAddressPos, &serializedSize,
sizeof(*memAddrPtr), SerializeIF::Endianness::LITTLE);
/* Add memLen to packet data field */
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD] = 1;
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD + 1] = 0;
/* Calculate crc */
uint16_t crc = CRC::crc16ccitt(this->localData.byteStream,
sizeof(CCSDSPrimaryHeader) + LENGTH_TC_MEM_READ - CRC_SIZE);
/* Add crc to packet data field of space packet */
serializedSize = 0;
uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET;
SerializeAdapter::serialize<uint16_t>(&crc, &crcPos, &serializedSize,
sizeof(crc), SerializeIF::Endianness::BIG);
}
static const uint8_t OFFSET_MEM_LEN_FIELD = 4;
static const uint8_t CRC_OFFSET = 6;
};
/**
* @brief This class helps to generate the space packet to write to a memory address within
* the PLOC.
* @details The last two bytes of the packet data field contain a CRC calculated over the whole
* space packet. This is the CRC-16-CCITT as specified in
* ECSS-E-ST-70-41C Telemetry and telecommand packet utilization.
*/
class TcMemWrite : public SpacePacket {
public:
/**
* @brief Constructor
*
* @param memAddr The PLOC memory address where to write to.
* @param memoryData The data to write to the specified memory address.
* @param sequenceCount The subsequence count. Must be incremented with each new packet.
*/
TcMemWrite(const uint32_t memAddr, const uint32_t memoryData, uint16_t sequenceCount) :
SpacePacket(LENGTH_TC_MEM_WRITE - 1, true, APID_TC_MEM_WRITE, sequenceCount) {
fillPacketDataField(&memAddr, &memoryData);
}
private:
/**
* @brief This function builds the packet data field for the mem write command.
*
* @param memAddrPtr Pointer to the PLOC memory address where to write to.
* @param memoryDataPtr Pointer to the memoryData to write
*/
void fillPacketDataField(const uint32_t* memAddrPtr, const uint32_t* memoryDataPtr) {
/* Add memAddr to packet data field */
size_t serializedSize = 0;
uint8_t* memoryAddressPos = this->localData.fields.buffer;
SerializeAdapter::serialize<uint32_t>(memAddrPtr, &memoryAddressPos, &serializedSize,
sizeof(*memAddrPtr), SerializeIF::Endianness::BIG);
/* Add memLen to packet data field */
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD] = 1;
this->localData.fields.buffer[OFFSET_MEM_LEN_FIELD + 1] = 0;
/* Add memData to packet data field */
serializedSize = 0;
uint8_t* memoryDataPos = this->localData.fields.buffer + OFFSET_MEM_DATA_FIELD;
SerializeAdapter::serialize<uint32_t>(memoryDataPtr, &memoryDataPos, &serializedSize,
sizeof(*memoryDataPtr), SerializeIF::Endianness::BIG);
/* Calculate crc */
uint16_t crc = CRC::crc16ccitt(this->localData.byteStream,
sizeof(CCSDSPrimaryHeader) + LENGTH_TC_MEM_WRITE - CRC_SIZE);
serializedSize = 0;
uint8_t* crcPos = this->localData.fields.buffer + CRC_OFFSET;
/* Add crc to packet data field of space packet */
SerializeAdapter::serialize<uint16_t>(&crc, &crcPos, &serializedSize,
sizeof(crc), SerializeIF::Endianness::BIG);
}
/** Offsets from base address of packet data field */
static const uint8_t OFFSET_MEM_LEN_FIELD = 4;
static const uint8_t OFFSET_MEM_DATA_FIELD = 6;
static const uint8_t CRC_OFFSET = 10;
};
}
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCDEFINITIONS_H_ */

View File

@ -0,0 +1,76 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_
namespace RAD_SENSOR {
static const DeviceCommandId_t NONE = 0x0; // Set when no command is pending
/**
* This command initiates the ADC conversion for all channels including the internal
* temperature sensor.
*/
static const DeviceCommandId_t WRITE_SETUP = 0x1;
static const DeviceCommandId_t START_CONVERSION = 0x2;
static const DeviceCommandId_t READ_CONVERSIONS = 0x3;
/**
* @brief This is the configuration byte which will be written to the setup register after
* power on.
*
* @note Bit1 (DIFFSEL1) - Bit0 (DIFFSEL0): 0b00, no data follows the setup byte
* Bit3 (REFSEL1) - Bit2 (REFSEL0): 0b10, internal reference, no wake-up delay
* Bit5 (CLKSEL1) - Bit4 (CLKSEL0): 0b10, MAX1227 uses internal oscillator for timing
* Bit7 - Bit6: 0b01, tells MAX1227 that this is the setup register
*
*/
static const uint8_t SETUP_DEFINITION = 0b01101000;
/**
* @brief This value will always be written to the ADC conversion register to specify the
* conversions to perform.
* @details Bit0: 1 - Enables temperature conversion
* Bit2 (SCAN1) and Bit1 (SCAN0): 0b00 (channel conversion from 0 to N)
* Bit6 - Bit3 defines N: 0b0001 (N = 1)
* Bit7: Always 1. Tells the ADC that this is the conversion register.
*/
static const uint8_t CONVERSION_DEFINITION = 0b10001001;
/**
* @brief Writing this value resets the fifo of the MAX1227.
*/
static const uint8_t RESET_DEFINITION = 0b00011000;
static const uint8_t DUMMY_BYTE = 0xFF;
static const uint8_t RAD_SENSOR_DATA_SET_ID = READ_CONVERSIONS;
/**
* One temperature value, conversion of channel 0 and conversion of channel 1
*/
static const uint8_t READ_SIZE = 6;
enum Max1227PoolIds: lp_id_t {
TEMPERATURE_C,
CHANNEL_0,
CHANNEL_1,
};
class RadSensorDataset: public StaticLocalDataSet<sizeof(float)> {
public:
RadSensorDataset(HasLocalDataPoolIF* owner) :
StaticLocalDataSet(owner, RAD_SENSOR_DATA_SET_ID) {
}
RadSensorDataset(object_id_t objectId) :
StaticLocalDataSet(sid_t(objectId, RAD_SENSOR_DATA_SET_ID)) {
}
lp_var_t<float> temperatureCelcius = lp_var_t<float>(sid.objectId, TEMPERATURE_C, this);
lp_var_t<uint16_t> channel0 = lp_var_t<uint16_t>(sid.objectId, CHANNEL_0, this);
lp_var_t<uint16_t> channel1 = lp_var_t<uint16_t>(sid.objectId, CHANNEL_1, this);
};
}
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_ */

View File

@ -0,0 +1,90 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SUS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_SUS_H_
namespace SUS {
/**
* Some MAX1227 could not be reached with frequencies around 4 MHz. Maybe this is caused by
* the decoder and buffer circuits. Thus frequency is here defined to 1 MHz.
*/
static const uint32_t MAX1227_SPI_FREQ = 1000000;
static const DeviceCommandId_t NONE = 0x0; // Set when no command is pending
static const DeviceCommandId_t WRITE_SETUP = 0x1;
/**
* This command initiates the ADC conversion for all channels including the internal
* temperature sensor.
*/
static const DeviceCommandId_t START_CONVERSIONS = 0x2;
/**
* This command reads the internal fifo which holds the temperature and the channel
* conversions.
*/
static const DeviceCommandId_t READ_CONVERSIONS = 0x3;
/**
* @brief This is the configuration byte which will be written to the setup register after
* power on.
*
* @note Bit1 (DIFFSEL1) - Bit0 (DIFFSEL0): 0b00, No byte is following the setup byte
* Bit3 (REFSEL1) - Bit2 (REFSEL0): 0b10, Internal reference, no wake-up delay
* Bit5 (CLKSEL1) - Bit4 (CLKSEL0): 0b10, Internally clocked
* Bit7 - Bit6: 0b01, Tells MAX1227 that this byte should be
* written to the setup register
*
*/
static const uint8_t SETUP = 0b01101000;
/**
* @brief This values will always be written to the ADC conversion register to specify the
* conversions to perform.
* @details Bit0: 1 - Enables temperature conversion
* Bit2 (SCAN1) and Bit1 (SCAN0): 0b00, Scans channels 0 through N
* Bit6 - Bit3 defines N: 0b0101 (N = 5)
* Bit7: Always 1. Tells the ADC that this is the conversion register.
*/
static const uint8_t CONVERSION = 0b10101001;
static const uint8_t SUS_DATA_SET_ID = READ_CONVERSIONS;
/** Size of data replies. Temperature and 6 channel convesions (AIN0 - AIN5) */
static const uint8_t SIZE_READ_CONVERSIONS = 14;
static const uint8_t MAX_CMD_SIZE = SIZE_READ_CONVERSIONS;
static const uint8_t POOL_ENTRIES = 7;
enum Max1227PoolIds: lp_id_t {
TEMPERATURE_C,
AIN0,
AIN1,
AIN2,
AIN3,
AIN4,
AIN5,
};
class SusDataset: public StaticLocalDataSet<POOL_ENTRIES> {
public:
SusDataset(HasLocalDataPoolIF* owner) :
StaticLocalDataSet(owner, SUS_DATA_SET_ID) {
}
SusDataset(object_id_t objectId) :
StaticLocalDataSet(sid_t(objectId, SUS_DATA_SET_ID)) {
}
lp_var_t<float> temperatureCelcius = lp_var_t<float>(sid.objectId, TEMPERATURE_C, this);
lp_var_t<uint16_t> ain0 = lp_var_t<uint16_t>(sid.objectId, AIN0, this);
lp_var_t<uint16_t> ain1 = lp_var_t<uint16_t>(sid.objectId, AIN1, this);
lp_var_t<uint16_t> ain2 = lp_var_t<uint16_t>(sid.objectId, AIN2, this);
lp_var_t<uint16_t> ain3 = lp_var_t<uint16_t>(sid.objectId, AIN3, this);
lp_var_t<uint16_t> ain4 = lp_var_t<uint16_t>(sid.objectId, AIN4, this);
lp_var_t<uint16_t> ain5 = lp_var_t<uint16_t>(sid.objectId, AIN5, this);
};
}
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_SUS_H_ */

2
thirdparty/etl vendored

@ -1 +1 @@
Subproject commit ae06e6417702b770c49289c9e7162cb3f4a5a217 Subproject commit c308dc427b7a34e54f33860fb2e244564b2740b4

2
tmtc

@ -1 +1 @@
Subproject commit 7cc06ef0e0882d286bab8156ca756e0211e5ebae Subproject commit a82e6b2e64e271eecc23fdbe3c403c417bb65e39