Merge remote-tracking branch 'origin/main' into relax-sus-fdir
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good

This commit is contained in:
Robin Müller 2023-08-03 13:37:36 +02:00
commit 05fbff2e6d
Signed by: muellerr
GPG Key ID: 407F9B00F858F270
140 changed files with 3972 additions and 2030 deletions

View File

@ -2,7 +2,7 @@
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Q7S" GENERATION_OPTIONS="-DTGT_BSP=&quot;arm/q7s&quot;" NO_GENERATOR="true">
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Default" GENERATION_OPTIONS="-DTGT_BSP=&quot;arm/q7s&quot;" NO_GENERATOR="true">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ZYNQ_7020_ROOTFS" value="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi" />
@ -10,6 +10,7 @@
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" NO_GENERATOR="true" />
</configurations>
</component>
</project>

View File

@ -16,9 +16,277 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
# [v4.0.0] to be released
## Changed
# [v3.1.0] to be released
- Relaxed SUS FDIR. The devices have shown to be glitchy in orbit, but still seem to deliver
sensible raw values most of the time. Some further testing is necessary, but some changes in the
code should cause the SUS devices to remain healthy for now.
# [v6.3.0] 2023-08-03
## Fixed
- Small SCEX fix: The temperatur check option was not passed
on for commands with a user data size larger than 1.
- SCEX: Properly check whether filesystem is usable for filesystem checks.
- ACS Controller strategy is now actually written to the dataset for detumbling.
- During detumble the fused rotation rate is now calculated.
- Detumbling is now exited when its exit value is undercut and not its entry value.
- Rotation rate of last cycle is now stored in all cases for the fused rotational rate
calculation.
- Fused rotation rate estimation during eclipse can be disabled. This will also prevent
detumbling during eclipse, as no relevant rotational rate is available for now.
- `EiveSystem`: Add a small delay between triggering an event for FDIR reboots and sending the
command to the core controller.
- PL PDU: Fixed bounds checking logic. Bound checks will only be performed for modules which are
enabled.
## Changed
- SCEX: Only perform filesystem checks when not in OFF mode.
- The `EiveSystem` now only sends reboot commands targetting the same image.
- Added 200 ms delay between switching HPA/MPA/TX/X8 and DRO GPIO pin OFF.
- PL PCDU ADC set is now automatically enabled for `NORMAL` mode transitions. It is automatically
disabled for `OFF` mode transitions.
## Added
- PL PCDU for EM build.
- SCEX: Add warning event if filesystem is unusable.
# [v6.2.0] 2023-07-26
- `eive-tmtc`: v5.3.1
## Changed
- STR missed reply handling is now moved to DHB rather than the COM interface. The COM IF will
still trigger an event if a reply is taking too long, and FDIR should still work via reply
timeouts.
- Re-ordered some functions of the core controller in the initialize function.
- Rad sensor is now only polled every 30 minutes instead of every device cycle to reduce wear of
the RADFET electronics.
- The SD cards will still be switched OFF on a reboot, but this is done in a non-blocking manner
now with a timeout of 10 seconds where the reboot will be performed in any case.
- ACS Controller now includes the safe mode from FLP, which will calculate its rotational rate
from SUS and MGM measurements. To accommodate these changes, low-pass filters for SUS
measurements and rates as well as MGM measurements and rates are included. Usage of the new
controller as well as settings of the low-pass filters can be handled via parameter commands.
- Simplify and fix the chip and copy protection functions in the core controller. This mechanism
now is always performed for the target chip and target copy in the reboot handlers.
- Improvement in FSFW: HK generation is now countdown based.
## Added
- 5 ms delay after pulling RADFET enable pin high before starting
the ADC conversion.
- Set STR time in configuration sequence to firmware mode.
- The STR `AutoThreshold` parameters are now set from the configuration JSON file at STR
startup.
- The STR handler can now handle the COM error reply and triggers an low severity event accordingly.
- Add SCEX handler for EM.
- Radiation sensor handler dummy for the EM.
- Added event for SD card information in core controller initialize function. This event will also
be triggered after the SD state machine has run, so the event will generally be triggered twice
at system boot, and once after commanding SD card switches.
## Fixed
- General bugs in the SD card state machine. This might fix some other known bugs for certain
combinations of switching ON and OFF SD cards and also makes the whole state machine a lot more
robust against hanging up.
- SUS dummy handler went to `MODE_NORMAL` for ON commands.
- PL PCDU dummy went to `MODE_NORMAL` for ON commands.
# [v6.1.0] 2023-07-13
- `eive-tmtc`: v5.2.0
## Changed
- TCS: Remove OBC IF board thermal module, which is exactly identical to OBC module and therefore
obsolete.
- Swapped PL and PS I2C, BPX battery and MGT are connected to PS I2C now for firmware versions
equal or above v4. However, this software version is compatible to both v3 and v4 of the firmware.
- The firmware version variables are global statics inititalized early during the program
runtime now. This makes it possible to check the firmware version earlier.
- The TCS controller will now always command heaters OFF when being blind for thermal
components (no sensors available), irrespective of current switch state.
- Make OBSW compatible to prospective FW version v5.0.0, where the Q7 I2C devices were
moved to a PL I2C block and the TMP sensor devices were moved to the PS I2C0.
- Made `Xadc` code a little bit more robust against errors.
## Fixed
- TMP1075: Set dataset invalid on shutdown explicitely
- Small fixes for TMP1075 FDIR: Use strange and missed reply counters.
- TCS controller: Last heater (S-band heater) was skipped for transition completion
checks.
- TCS controller: A helper member to track the elapsed heater control cycles was not reset
properly, which could lead to switch transitions being completed immediately. This can
lead to weird bugs like heaters being commanded ON twice and can potentially lead to
other bugs.
- TMP1075: Devices did not go to OFF mode when being set faulty.
- Update PL PCDU 1 in TCS mode tree on the EM.
- TMP1075: Possibly ignored health commands.
- Bugfix in FSFW where certain packet types could only be sent with source data fields with a
maximum size of 255 bytes.
- TCS CTRL: Limit number of heater handler messages sent in case there are not sensors available
anymore.
- Fix to allow adding real STR device for EM.
# Added
- Two events for heaters being commanded ON and OFF by the TCS controller
- Upper limit for burn time of TCS heaters. Currently set to 1 hour for each heater.
This mechanism will only track the burn time for heaters which were commanded by the
TCS controller.
- TCS controller is now observable by introducing a new HK dataset which exposes some internal
fields related to TCS control.
# [v6.0.0] 2023-07-02
- `q7s-package` version v3.2.0
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
## Changed
- Added back PTME busy bit polling. This is necessary due to changes to the AXI APB interface
to the PTME core.
## Fixed
- For the live channel (VC0), telemetry was still only dumped if the transmitter is active.
Please note that this fix will lead to crashes for FW versions below v3.2.
However, it might not be an issue for the oldest firmware on the satellite (v2.5.1).
# [v5.2.0] 2023-07-02
## Fixed
- The firmware information event was not triggered even when possible because of an ordering
bug in the initializer function.
- Empty dumps (no TM in time range) will now correctly be completed immediately
## Changed
- PTME was always reset on submode changes. The reset will now only be performed if the actual data
rate changes.
- Add back ACS board code for the EM. Now that the radiation sensor was removed, the image switching
issue has disappeared and adding back the ACS board is worth it for the GPS timekeeping.
# [v5.1.0] 2023-06-28
- `eive-tmtc` version v5.1.0
## Changed
- Persistent TM store dumps are now performed in chronological order.
- Increase Syrlinks RX HK rate to 5.0 seconds during a pass.
- Various robustness improvements for the heater handler. The heater handler will now only
process the command queue if it is not busy with switch commanding which reduces the amount
of possible bugs.
- The heater handler is only able to process messages stricly sequentially now but is scheduled
twice in a 0.5 second slot so something like a consecutive heater ON or OFF command can still
be handled relatively quickly.
## Added
- Sequence counters for PUS and CFDP packets are now stored persistently across graceful reboots.
- The PUS packet message type counter will now be incremented properly for each PUS service.
- Internal error reporter set is now enabled by default and generated every 120 seconds.
# [v5.0.0] 2023-06-26
v3.3.1 and all following version will now be moved to v5.0.0 with the additional changes listed
here. This was done because the firmware update (v4.0.0) is not working right now and it is not
known when and how it will be fixed. Because of that, all updates to make the SW work with the new
firmware, which are limited to a few files will be moved to a dev branch so regular development
compatible to the old firmware can continue.
TLDR: This version is compatible to the old firmware and some changes which only work with the new
firmware have been reverted.
## Changed
- Added `sync` syscall in graceful shutdown handler
- Graceful shutdown is now performed by the reboot watchdog
- There is now a separate file for the total reboot counter. The reboot watchdog has its own local
counters to determine whether a reboot is necessary.
# [v4.0.1] 2023-06-24
## Fixed
- `PusLiveDemux` packet demultiplexing bugfix where the demultiplexing did not work when there was
only one destination available.
# [v4.0.0] 2023-06-22
- `eive-tmtc` version v5.0.0
- `q7s-package` version v3.1.1
## Fixed
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
- TCS fixes: Set temperature values to invalid value for MAX31865 RTD handler, SUS handler
and STR handler. Also set dataset to invakid for RTD handler.
- Fixed H parameter in SUS converter from 1 mm to 2.5 mm.
## Changed
- Removed PTME busy/ready signals. Those were not used anyway because register reads are used now.
- APB bus access busy checking is not done anymore as this is performed by the bus itself now.
- Core controller will now announce version and image information event in addition to reboot
event in the `inititalize` function.
- Core controller will now try to request and announce the firmware version in addition to the
OBSW version as well.
- Added core controller action to read reboot mechansm information
- GNSS reset pin will now only be asserted for 5 ms instead of 100 ms.
## Added
- Added PL I2C reset pin. It is not used/connected for now but could be used for FDIR procedures to
restore the PL I2C.
- Core controller now announces firmware version as well when requesting a version info event
# [v3.3.1] 2023-06-22
## Fixed
- `PusLiveDemux` packet demultiplexing bugfix where the demultiplexing did not work when there was
only one destination available.
## Fixed
- Fixed H parameter in SUS converter from 1 mm to 2.5 mm.
# [v3.3.0] 2023-06-21
Like v3.2.0 but without the custom FM changes related to VC0.
# [v3.2.0] 2023-06-21
## Fixed
- Fix sun vector calculation
- SUS total vector was not reset to being a zero vector during eclipse due to a wrong memcpy
length.
## Changed
- Reverted all changes related to VC0 handling to avoid FM bug possibly related to FPGA bug.
# [v3.1.1] 2023-06-14
## Fixed
- TMP1075 bugfix where negative temperatures could not be measured because of a two's-complement
conversion bug.
# [v3.1.0] 2023-06-14
- `eive-tmtc` version v4.1.0
## Fixed
@ -27,11 +295,12 @@ will consitute of a breaking change warranting a new major release:
## Changed
- Relaxed SUS FDIR. The devices have shown to be glitchy in orbit, but still seem to deliver
sensible raw values most of the time. Some further testing is necessary, but some changes in the
code should cause the SUS devices to remain healthy for now.
- Increase number of allowed parallel HK commands to 16
## Added
- Added `CONFIG_SET`, `MAN_HEATER_ON` and `MAN_HEATER_OFF` support for the BPX battery handler
# [v3.0.0] 2023-06-11
- `eive-tmtc` version v4.0.0

View File

@ -9,8 +9,8 @@
# ##############################################################################
cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 3)
set(OBSW_VERSION_MINOR 0)
set(OBSW_VERSION_MAJOR 6)
set(OBSW_VERSION_MINOR 3)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
@ -93,7 +93,7 @@ set(OBSW_ADD_BPX_BATTERY_HANDLER
1
CACHE STRING "Add BPX battery module")
set(OBSW_ADD_STAR_TRACKER
${INIT_VAL}
1
CACHE STRING "Add Startracker module")
set(OBSW_ADD_SUN_SENSORS
${INIT_VAL}
@ -105,7 +105,7 @@ set(OBSW_ADD_THERMAL_TEMP_INSERTER
${OBSW_Q7S_EM}
CACHE STRING "Add thermal sensor temperature inserter")
set(OBSW_ADD_ACS_BOARD
${INIT_VAL}
1
CACHE STRING "Add ACS board module")
set(OBSW_ADD_GPS_CTRL
${INIT_VAL}
@ -144,13 +144,13 @@ set(OBSW_ADD_RAD_SENSORS
${INIT_VAL}
CACHE STRING "Add Rad Sensor module")
set(OBSW_ADD_PL_PCDU
${INIT_VAL}
1
CACHE STRING "Add Payload PCDU modukle")
set(OBSW_ADD_SYRLINKS
1
CACHE STRING "Add Syrlinks module")
set(OBSW_ADD_TMP_DEVICES
${INIT_VAL}
1
CACHE STRING "Add TMP devices")
set(OBSW_ADD_GOMSPACE_PCDU
1
@ -162,7 +162,7 @@ set(OBSW_ADD_RW
${INIT_VAL}
CACHE STRING "Add RW modules")
set(OBSW_ADD_SCEX_DEVICE
${INIT_VAL}
1
CACHE STRING "Add Solar Cell Experiment module")
set(OBSW_SYRLINKS_SIMULATED
0

View File

@ -964,6 +964,12 @@ used by other software components to read the current chip and copy.
This is a configuration scripts which runs after the Network Time Protocol has run. This script
currently sets the static IP address `192.168.133.10` and starts the `can` interface.
## Initial boot delay
You can create a file named `boot_delays_secs.txt` inside the home folder to delay the OBSW boot
for 6 seconds if the file is empty of for the number of seconds specified inside the file. This
can be helpful if something inside the OBSW leads to an immediate crash of the OBC.
## PCDU
Connect to serial console of P60 Dock

View File

@ -68,7 +68,7 @@ void ObjectFactory::produce(void* args) {
#endif
auto sdcMan = new DummySdCardManager("/tmp");
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
&tmStore, persistentStores, 120);
&tmStore, persistentStores, 120, enableHkSets);
new TmFunnelHandler(objects::LIVE_TM_TASK, *pusFunnel, *cfdpFunnel);
auto* dummyGpioIF = new DummyGpioIF();
@ -113,7 +113,7 @@ void ObjectFactory::produce(void* args) {
if (heaterHandler == nullptr) {
sif::error << "HeaterHandler could not be created" << std::endl;
} else {
ObjectFactory::createThermalController(*heaterHandler);
ObjectFactory::createThermalController(*heaterHandler, true);
}
new TestTask(objects::TEST_TASK);
}

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 296 translations.
* @brief Auto-generated event translation file. Contains 303 translations.
* @details
* Generated on: 2023-06-13 07:54:32
* Generated on: 2023-08-03 13:36:37
*/
#include "translateEvents.h"
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
@ -260,6 +261,7 @@ const char *TX_OFF_STRING = "TX_OFF";
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
@ -277,6 +279,8 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -285,6 +289,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -572,6 +579,8 @@ const char *translateEvents(Event event) {
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
case (11902):
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
case (11903):
return COM_ERROR_REPLY_RECEIVED_STRING;
case (12001):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (12002):
@ -814,6 +823,8 @@ const char *translateEvents(Event event) {
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
case (13803):
return FS_UNUSABLE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
@ -848,6 +859,10 @@ const char *translateEvents(Event event) {
return I2C_REBOOT_STRING;
case (14012):
return PDEC_REBOOT_STRING;
case (14013):
return FIRMWARE_INFO_STRING;
case (14014):
return ACTIVE_SD_INFO_STRING;
case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):
@ -864,6 +879,12 @@ const char *translateEvents(Event event) {
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
case (14108):
return MGT_OVERHEATING_STRING;
case (14109):
return TCS_SWITCHING_HEATER_ON_STRING;
case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201):
return TX_TIMER_EXPIRED_STRING;
case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 171 translations.
* Generated on: 2023-06-13 07:54:32
* Generated on: 2023-08-03 13:36:37
*/
#include "translateObjects.h"

View File

@ -7,7 +7,8 @@ target_link_libraries(${SIMPLE_OBSW_NAME} PUBLIC ${LIB_FSFW_NAME})
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
add_subdirectory(simple)
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp)
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp scheduling.cpp
objectFactory.cpp)
add_subdirectory(boardtest)

View File

@ -12,6 +12,9 @@ static constexpr char SPI_RW_DEV[] = "/dev/spi_rw";
static constexpr char I2C_PL_EIVE[] = "/dev/i2c_pl";
//! I2C bus using the I2C peripheral of the ARM processing system (PS)
static constexpr char I2C_PS_EIVE[] = "/dev/i2c_ps";
//! I2C bus using the first I2C peripheral of the ARM processing system (PS).
//! Named like this because it is used by default for the Q7 devices.
static constexpr char I2C_Q7_EIVE[] = "/dev/i2c_q7";
static constexpr char UART_GNSS_DEV[] = "/dev/gps0";
static constexpr char UART_PLOC_MPSOC_DEV[] = "/dev/ul_plmpsoc";
@ -23,6 +26,7 @@ static constexpr char UART_SCEX_DEV[] = "/dev/scex";
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio_pdec_regs";
static constexpr char UIO_PTME[] = "/dev/uio_ptme";
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio_pdec_cfg_mem";
static constexpr char UIO_SYS_ROM[] = "/dev/uio_sys_rom";
static constexpr char UIO_PDEC_RAM[] = "/dev/uio_pdec_ram";
static constexpr char UIO_PDEC_IRQ[] = "/dev/uio_pdec_irq";
static constexpr int MAP_ID_PTME_CONFIG = 3;
@ -57,6 +61,7 @@ static constexpr char GYRO_0_ENABLE[] = "enable_gyro_0";
static constexpr char GYRO_2_ENABLE[] = "enable_gyro_2";
static constexpr char GNSS_SELECT[] = "gnss_mux_select";
static constexpr char GNSS_MUX_SELECT[] = "gnss_mux_select";
static constexpr char PL_I2C_ARESETN[] = "pl_i2c_aresetn";
static constexpr char HEATER_0[] = "heater0";
static constexpr char HEATER_1[] = "heater1";
@ -82,14 +87,12 @@ static constexpr char EN_RW_4[] = "enable_rw_4";
static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select";
static constexpr char ENABLE_RADFET[] = "enable_radfet";
static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0";
static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0";
static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1";
static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1";
static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2";
static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2";
static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3";
static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3";
static constexpr char PTME_RESETN[] = "ptme_resetn";
static constexpr char RS485_EN_TX_CLOCK[] = "tx_clock_enable_ltc2872";

View File

@ -218,15 +218,30 @@ void Q7STestTask::testProtHandler() {
bool opPerformed = false;
ReturnValue_t result = returnvalue::OK;
// If any chips are unlocked, lock them here
result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_0,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_1,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_0,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
// unlock own copy
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
xsc::Copy::SELF_COPY, false);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
@ -239,8 +254,8 @@ void Q7STestTask::testProtHandler() {
}
// lock own copy
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
xsc::Copy::SELF_COPY, true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
@ -253,8 +268,8 @@ void Q7STestTask::testProtHandler() {
}
// unlock specific copy
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
false);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
@ -267,8 +282,8 @@ void Q7STestTask::testProtHandler() {
}
// lock specific copy
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}

View File

@ -1,4 +1 @@
target_sources(${OBSW_NAME} PRIVATE CoreController.cpp scheduling.cpp
ObjectFactory.cpp WatchdogHandler.cpp)
target_sources(${SIMPLE_OBSW_NAME} PRIVATE scheduling.cpp)
target_sources(${OBSW_NAME} PRIVATE CoreController.cpp WatchdogHandler.cpp)

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,13 @@
#ifndef BSP_Q7S_CORE_CORECONTROLLER_H_
#define BSP_Q7S_CORE_CORECONTROLLER_H_
#include <bsp_q7s/core/defs.h>
#include <fsfw/container/DynamicFIFO.h>
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw/parameters/ParameterHelper.h>
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
#include <fsfw_hal/linux/uio/UioMapper.h>
#include <libxiphos.h>
#include <mission/acs/archive/GPSDefinitions.h>
#include <mission/utility/trace.h>
@ -13,7 +15,6 @@
#include <atomic>
#include <cstddef>
#include "CoreDefinitions.h"
#include "OBSWConfig.h"
#include "bsp_q7s/fs/SdCardManager.h"
#include "events/subsystemIdRanges.h"
@ -23,7 +24,7 @@
class Timer;
class SdCardManager;
struct RebootFile {
struct RebootWatchdogFile {
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
bool enabled = true;
@ -44,6 +45,93 @@ struct RebootFile {
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
};
class RebootWatchdogPacket : public SerialLinkedListAdapter<SerializeIF> {
public:
RebootWatchdogPacket(RebootWatchdogFile& rf) {
enabled = rf.enabled;
maxCount = rf.maxCount;
img00Count = rf.img00Cnt;
img01Count = rf.img01Cnt;
img10Count = rf.img10Cnt;
img11Count = rf.img11Cnt;
img00Lock = rf.img00Lock;
img01Lock = rf.img01Lock;
img10Lock = rf.img10Lock;
img11Lock = rf.img11Lock;
lastChip = static_cast<uint8_t>(rf.lastChip);
lastCopy = static_cast<uint8_t>(rf.lastCopy);
nextChip = static_cast<uint8_t>(rf.mechanismNextChip);
nextCopy = static_cast<uint8_t>(rf.mechanismNextCopy);
setLinks();
}
private:
void setLinks() {
setStart(&enabled);
enabled.setNext(&maxCount);
maxCount.setNext(&img00Count);
img00Count.setNext(&img01Count);
img01Count.setNext(&img10Count);
img10Count.setNext(&img11Count);
img11Count.setNext(&img00Lock);
img00Lock.setNext(&img01Lock);
img01Lock.setNext(&img10Lock);
img10Lock.setNext(&img11Lock);
img11Lock.setNext(&lastChip);
lastChip.setNext(&lastCopy);
lastCopy.setNext(&nextChip);
nextChip.setNext(&nextCopy);
setLast(&nextCopy);
}
SerializeElement<uint8_t> enabled = false;
SerializeElement<uint32_t> maxCount = 0;
SerializeElement<uint32_t> img00Count = 0;
SerializeElement<uint32_t> img01Count = 0;
SerializeElement<uint32_t> img10Count = 0;
SerializeElement<uint32_t> img11Count = 0;
SerializeElement<uint8_t> img00Lock = false;
SerializeElement<uint8_t> img01Lock = false;
SerializeElement<uint8_t> img10Lock = false;
SerializeElement<uint8_t> img11Lock = false;
SerializeElement<uint8_t> lastChip = 0;
SerializeElement<uint8_t> lastCopy = 0;
SerializeElement<uint8_t> nextChip = 0;
SerializeElement<uint8_t> nextCopy = 0;
};
struct RebootCountersFile {
// 16 bit values so all boot counters fit into one event.
uint16_t img00Cnt = 0;
uint16_t img01Cnt = 0;
uint16_t img10Cnt = 0;
uint16_t img11Cnt = 0;
};
class RebootCountersPacket : public SerialLinkedListAdapter<SerializeIF> {
RebootCountersPacket(RebootCountersFile& rf) {
img00Count = rf.img00Cnt;
img01Count = rf.img01Cnt;
img10Count = rf.img10Cnt;
img11Count = rf.img11Cnt;
setLinks();
}
private:
void setLinks() {
setStart(&img00Count);
img00Count.setNext(&img01Count);
img01Count.setNext(&img10Count);
img10Count.setNext(&img11Count);
setLast(&img11Count);
}
SerializeElement<uint16_t> img00Count = 0;
SerializeElement<uint16_t> img01Count = 0;
SerializeElement<uint16_t> img10Count = 0;
SerializeElement<uint16_t> img11Count = 0;
};
class CoreController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
public:
enum ParamId : uint8_t { PREF_SD = 0, NUM_IDS };
@ -57,10 +145,15 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
const std::string VERSION_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::VERSION_FILE_NAME);
const std::string REBOOT_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_FILE_NAME);
const std::string LEGACY_REBOOT_WATCHDOG_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" +
std::string(core::LEGACY_REBOOT_WATCHDOG_FILE_NAME);
const std::string REBOOT_WATCHDOG_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_WATCHDOG_FILE_NAME);
const std::string BACKUP_TIME_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME);
const std::string REBOOT_COUNTERS_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_COUNTER_FILE_NAME);
static constexpr char CHIP_0_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
@ -106,8 +199,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
* @param updateProtFile Specify whether the protection info file is updated
* @return
*/
ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool updateProtFile = true);
ReturnValue_t setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip, xsc::Copy targetCopy,
bool protect);
bool sdInitFinished() const;
@ -142,6 +235,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
static constexpr bool BLOCKING_SD_INIT = false;
uint32_t* mappedSysRomAddr = nullptr;
SdCardManager* sdcMan = nullptr;
MessageQueueIF* eventQueue = nullptr;
@ -191,7 +285,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
std::array<uint8_t, 1024> dirListingBuf{};
DirListingDumpContext dumpContext{};
RebootFile rebootFile = {};
RebootWatchdogFile rebootWatchdogFile = {};
RebootCountersFile rebootCountersFile = {};
CommandExecutor cmdExecutor;
SimpleRingBuffer cmdReplyBuf;
@ -209,12 +304,10 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
Countdown sdCardCheckCd = Countdown(INIT_SD_CARD_CHECK_TIMEOUT);
/**
* Index 0: Chip 0 Copy 0
* Index 1: Chip 0 Copy 1
* Index 2: Chip 1 Copy 0
* Index 3: Chip 1 Copy 1
* First index: Chip.
* Second index: Copy.
*/
std::array<bool, 4> protArray;
bool protArray[2][2]{};
PeriodicOperationDivider opDivider5;
PeriodicOperationDivider opDivider10;
@ -261,12 +354,14 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
void executeNextExternalSdCommand();
void checkExternalSdCommandStatus();
void performRebootFileHandling(bool recreateFile);
void performRebootWatchdogHandling(bool recreateFile);
void performRebootCountersHandling(bool recreateFile);
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
ReturnValue_t actionListDirectoryDumpDirectly(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
ReturnValue_t performGracefulShutdown(xsc::Chip targetChip, xsc::Copy targetCopy);
ReturnValue_t actionListDirectoryCommonCommandCreator(const uint8_t* data, size_t size,
std::ostringstream& oss);
@ -277,16 +372,20 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
ReturnValue_t gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool& protOpPerformed);
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool selfChip, bool selfCopy,
bool allChips, bool allCopies, uint8_t arrIdx);
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
ReturnValue_t handleSwitchingSdCardsOffNonBlocking();
bool handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect);
void rebootWatchdogAlgorithm(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy);
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
bool parseRebootFile(std::string path, RebootFile& file);
void rewriteRebootFile(RebootFile file);
bool parseRebootWatchdogFile(std::string path, RebootWatchdogFile& file);
bool parseRebootCountersFile(std::string path, RebootCountersFile& file);
void rewriteRebootWatchdogFile(RebootWatchdogFile file);
void rewriteRebootCountersFile(RebootCountersFile file);
void announceBootCounts();
void announceVersionInfo();
void announceCurrentImageInfo();
void announceSdInfo(SdCardManager::SdStatePair sdStates);
void readHkData();
void dirListingDumpHandler();
bool isNumber(const std::string& s);

View File

@ -1,10 +1,16 @@
#ifndef BSP_Q7S_CORE_COREDEFINITIONS_H_
#define BSP_Q7S_CORE_COREDEFINITIONS_H_
#ifndef BSP_Q7S_CORE_DEFS_H_
#define BSP_Q7S_CORE_DEFS_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
namespace core {
extern uint8_t FW_VERSION_MAJOR;
extern uint8_t FW_VERSION_MINOR;
extern uint8_t FW_VERSION_REVISION;
extern bool FW_VERSION_HAS_SHA;
extern char FW_VERSION_GIT_SHA[4];
static const uint8_t HK_SET_ENTRIES = 3;
static const uint32_t HK_SET_ID = 5;
@ -36,4 +42,4 @@ class HkSet : public StaticLocalDataSet<HK_SET_ENTRIES> {
} // namespace core
#endif /* BSP_Q7S_CORE_COREDEFINITIONS_H_ */
#endif /* BSP_Q7S_CORE_DEFS_H_ */

View File

@ -1,4 +1,5 @@
#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
#include <bsp_q7s/objectFactory.h>
#include <dummies/ComCookieDummy.h>
#include <dummies/PcduHandlerDummy.h>
#include <fsfw/health/HealthTableIF.h>
@ -10,8 +11,8 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "busConf.h"
#include "common/config/devices/addresses.h"
#include "devConf.h"
#include "dummies/helperFactory.h"
#include "eive/objects.h"
@ -35,18 +36,20 @@ void ObjectFactory::produce(void* args) {
#endif
PersistentTmStores stores;
readFirmwareVersion();
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
200);
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
enableHkSets);
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;
SpiComIF* spiMainComIF = nullptr;
I2cComIF* i2cComIF = nullptr;
createCommunicationInterfaces(&gpioComIF, &uartComIF, &spiMainComIF, &i2cComIF);
/* Adding gpios for chip select decoding to the gpioComIf */
// Adding GPIOs for chip select decoding and initializing them.
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF);
createPlI2cResetGpio(gpioComIF);
// Hardware is usually not connected to EM, so we need to create dummies which replace lower
// level components.
@ -59,17 +62,41 @@ void ObjectFactory::produce(void* args) {
#if OBSW_ADD_PLOC_SUPERVISOR == 1 || OBSW_ADD_PLOC_MPSOC == 1
dummyCfg.addPlocDummies = false;
#endif
#if OBSW_ADD_TMP_DEVICES == 1
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd = {{
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
{objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
}};
createTmpComponents(tmpDevsToAdd);
dummy::Tmp1075Cfg tmpCfg{};
tmpCfg.addTcsBrd0 = true;
tmpCfg.addTcsBrd1 = true;
tmpCfg.addPlPcdu0 = false;
tmpCfg.addPlPcdu1 = false;
tmpCfg.addIfBrd = false;
dummyCfg.tmp1075Cfg = tmpCfg;
#endif
#if OBSW_ADD_GOMSPACE_PCDU == 1
dummyCfg.addPowerDummies = false;
// The ACU broke.
dummyCfg.addOnlyAcuDummy = true;
#endif
#if OBSW_ADD_STAR_TRACKER == 1
dummyCfg.addStrDummy = false;
#endif
#if OBSW_ADD_SCEX_DEVICE == 0
dummyCfg.addScexDummy = true;
#endif
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
dummyCfg.addBpxBattDummy = false;
#endif
#if OBSW_ADD_ACS_BOARD == 1
dummyCfg.addAcsBoardDummies = false;
#endif
#if OBSW_ADD_PL_PCDU == 0
dummyCfg.addPlPcduDummy = true;
#endif
PowerSwitchIF* pwrSwitcher = nullptr;
#if OBSW_ADD_GOMSPACE_PCDU == 0
@ -83,24 +110,12 @@ void ObjectFactory::produce(void* args) {
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
// Regular FM code, does not work for EM if the hardware is not connected
// createPcduComponents(gpioComIF, &pwrSwitcher);
// createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher);
// createSyrlinksComponents(pwrSwitcher);
// createSunSensorComponents(gpioComIF, spiMainComIF, pwrSwitcher, q7s::SPI_DEFAULT_DEV);
// createRtdComponents(q7s::SPI_DEFAULT_DEV, gpioComIF, pwrSwitcher, spiMainComIF);
// createTmpComponents();
// createSolarArrayDeploymentComponents();
// createPayloadComponents(gpioComIF);
// createHeaterComponents(gpioComIF, pwrSwitcher, healthTable);
auto* stackHandler = new Stack5VHandler(*pwrSwitcher);
// TODO: Careful! Switching this on somehow messes with the communication with the ProASIC
// and will cause xsc_boot_copy commands to always boot to 0 0
// createRadSensorComponent(gpioComIF);
// Initialize chip select to avoid SPI bus issues.
createRadSensorChipSelect(gpioComIF);
#if OBSW_ADD_ACS_BOARD == 1
// Still initialize chip select to avoid SPI bus issues.
createRadSensorChipSelect(gpioComIF);
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
adis1650x::Type::ADIS16507);
#else
@ -110,8 +125,14 @@ void ObjectFactory::produce(void* args) {
gpioChecker(gpioComIF->addGpios(acsBoardGpios), "ACS Board");
#endif
const char* battAndImtqI2cDev = q7s::I2C_PL_EIVE;
if (core::FW_VERSION_MAJOR >= 4) {
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
}
static_cast<void>(battAndImtqI2cDev);
#if OBSW_ADD_MGT == 1
createImtqComponents(pwrSwitcher, enableHkSets);
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_SYRLINKS == 1
@ -123,13 +144,16 @@ void ObjectFactory::produce(void* args) {
#endif
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
createBpxBatteryComponent(enableHkSets);
createBpxBatteryComponent(enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_STAR_TRACKER == 1
createStrComponents(pwrSwitcher);
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_PL_PCDU == 1
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
#endif
createPayloadComponents(gpioComIF, *pwrSwitcher);
#if OBSW_ADD_CCSDS_IP_CORES == 1
@ -155,6 +179,6 @@ void ObjectFactory::produce(void* args) {
createAcsController(true, enableHkSets);
HeaterHandler* heaterHandler;
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
createThermalController(*heaterHandler);
satsystem::init();
createThermalController(*heaterHandler, true);
satsystem::init(true);
}

View File

@ -1,4 +1,5 @@
#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
#include <bsp_q7s/objectFactory.h>
#include <devices/gpioIds.h>
#include <fsfw/storagemanager/LocalPool.h>
#include <fsfw/storagemanager/PoolManager.h>
@ -7,9 +8,9 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "busConf.h"
#include "devConf.h"
#include "devices/addresses.h"
#include "eive/objects.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "linux/ObjectFactory.h"
@ -32,9 +33,10 @@ void ObjectFactory::produce(void* args) {
#endif
PersistentTmStores stores;
readFirmwareVersion();
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
200);
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
true);
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;
@ -45,6 +47,7 @@ void ObjectFactory::produce(void* args) {
/* Adding gpios for chip select decoding to the gpioComIf */
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF);
createPlI2cResetGpio(gpioComIF);
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets);
@ -66,23 +69,38 @@ void ObjectFactory::produce(void* args) {
HeaterHandler* heaterHandler;
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
#if OBSW_ADD_TMP_DEVICES == 1
createTmpComponents();
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd = {{
{objects::TMP1075_HANDLER_TCS_0, addresses::TMP1075_TCS_0},
{objects::TMP1075_HANDLER_TCS_1, addresses::TMP1075_TCS_1},
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
// damaged
// {objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
}};
createTmpComponents(tmpDevsToAdd);
#endif
createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF);
#if OBSW_ADD_PL_PCDU == 1
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
#endif
#if OBSW_ADD_SYRLINKS == 1
createSyrlinksComponents(pwrSwitcher);
#endif /* OBSW_ADD_SYRLINKS == 1 */
createRtdComponents(q7s::SPI_DEFAULT_DEV, gpioComIF, pwrSwitcher, spiMainComIF);
createPayloadComponents(gpioComIF, *pwrSwitcher);
const char* battAndImtqI2cDev = q7s::I2C_PL_EIVE;
if (core::FW_VERSION_MAJOR >= 4) {
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
}
#if OBSW_ADD_MGT == 1
createImtqComponents(pwrSwitcher, enableHkSets);
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
#endif
createReactionWheelComponents(gpioComIF, pwrSwitcher);
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
createBpxBatteryComponent(enableHkSets);
createBpxBatteryComponent(enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_STAR_TRACKER == 1
@ -112,7 +130,7 @@ void ObjectFactory::produce(void* args) {
#endif /* OBSW_ADD_TEST_CODE == 1 */
createMiscComponents();
createThermalController(*heaterHandler);
createThermalController(*heaterHandler, false);
createAcsController(true, enableHkSets);
satsystem::init();
satsystem::init(false);
}

View File

@ -125,13 +125,8 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar
return mountSdCard(sdCard);
}
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard,
SdStatePair* statusPair) {
std::pair<sd::SdState, sd::SdState> active;
ReturnValue_t result = getSdCardsStatus(active);
if (result != returnvalue::OK) {
return result;
}
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates,
bool doUnmountSdCard) {
if (doUnmountSdCard) {
if (not blocking) {
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
@ -147,17 +142,17 @@ ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSd
return returnvalue::FAILED;
}
if (sdCard == sd::SdCard::SLOT_0) {
if (active.first == sd::SdState::OFF) {
if (sdStates.first == sd::SdState::OFF) {
return ALREADY_OFF;
}
} else if (sdCard == sd::SdCard::SLOT_1) {
if (active.second == sd::SdState::OFF) {
if (sdStates.second == sd::SdState::OFF) {
return ALREADY_OFF;
}
}
if (doUnmountSdCard) {
result = unmountSdCard(sdCard);
ReturnValue_t result = unmountSdCard(sdCard);
if (result != returnvalue::OK) {
return result;
}
@ -189,7 +184,7 @@ ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) {
command << "q7hw sd set " << sdstring << " " << statestring;
cmdExecutor.load(command.str(), blocking, printCmdOutput);
ReturnValue_t result = cmdExecutor.execute();
if (blocking and result != returnvalue::OK) {
if (result != returnvalue::OK) {
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
}
return result;
@ -204,6 +199,7 @@ ReturnValue_t SdCardManager::getSdCardsStatus(SdStatePair& sdStates) {
ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) {
using namespace std;
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
sif::warning << "SdCardManager::mountSdCard: Command still pending" << std::endl;
return CommandExecutor::COMMAND_PENDING;
}
if (sdCard == sd::SdCard::BOTH) {

View File

@ -114,8 +114,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
* @return - returnvalue::OK on success, ALREADY_ON if it is already on,
* SYSTEM_CALL_ERROR on system error
*/
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
SdStatePair* statusPair = nullptr);
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates, bool doUnmountSdCard);
/**
* Get the state of the SD cards. If the state file does not exist, this function will

View File

@ -1,7 +1,9 @@
#include "ObjectFactory.h"
#include "objectFactory.h"
#include <fsfw/devicehandlers/HealthDevice.h>
#include <fsfw/subsystem/Subsystem.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw_hal/linux/uio/UioMapper.h>
#include <linux/acs/AcsBoardPolling.h>
#include <linux/acs/GpsHyperionLinuxController.h>
#include <linux/acs/ImtqPollingTask.h>
@ -31,6 +33,9 @@
#include <mission/system/objects/CamSwitcher.h>
#include <mission/system/tcs/TmpDevFdir.h>
#include <cstdint>
#include <cstring>
#include "OBSWConfig.h"
#include "bsp_q7s/boardtest/Q7STestTask.h"
#include "bsp_q7s/callbacks/gnssCallback.h"
@ -99,6 +104,7 @@
#include <sstream>
#include "bsp_q7s/core/defs.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
@ -129,6 +135,11 @@ ResetArgs RESET_ARGS_GNSS;
std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN;
std::atomic_bool PTME_LOCKED = false;
std::atomic_uint16_t I2C_FATAL_ERRORS = 0;
uint8_t core::FW_VERSION_MAJOR = 0;
uint8_t core::FW_VERSION_MINOR = 0;
uint8_t core::FW_VERSION_REVISION = 0;
bool core::FW_VERSION_HAS_SHA = false;
char core::FW_VERSION_GIT_SHA[4] = {};
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
@ -150,28 +161,23 @@ void Factory::setStaticFrameworkObjectIds() {
void ObjectFactory::setStatics() { Factory::setStaticFrameworkObjectIds(); }
void ObjectFactory::createTmpComponents() {
std::vector<std::pair<object_id_t, address_t>> tmpDevIds = {{
{objects::TMP1075_HANDLER_TCS_0, addresses::TMP1075_TCS_0},
{objects::TMP1075_HANDLER_TCS_1, addresses::TMP1075_TCS_1},
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
// damaged
// {objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
}};
void ObjectFactory::createTmpComponents(
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd) {
const char* tmpI2cDev = q7s::I2C_PS_EIVE;
if (core::FW_VERSION_MAJOR == 4) {
tmpI2cDev = q7s::I2C_PL_EIVE;
} else if (core::FW_VERSION_MAJOR >= 5) {
tmpI2cDev = q7s::I2C_Q7_EIVE;
}
std::vector<I2cCookie*> tmpDevCookies;
for (size_t idx = 0; idx < tmpDevIds.size(); idx++) {
for (size_t idx = 0; idx < tmpDevsToAdd.size(); idx++) {
tmpDevCookies.push_back(
new I2cCookie(tmpDevIds[idx].second, TMP1075::MAX_REPLY_LENGTH, q7s::I2C_PS_EIVE));
new I2cCookie(tmpDevsToAdd[idx].second, TMP1075::MAX_REPLY_LENGTH, tmpI2cDev));
auto* tmpDevHandler =
new Tmp1075Handler(tmpDevIds[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevIds[idx].first));
new Tmp1075Handler(tmpDevsToAdd[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevsToAdd[idx].first));
tmpDevHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
// TODO: Remove this after TCS subsystem was added
// These devices are connected to the 3V3 stack and should be powered permanently. Therefore,
// we set them to normal mode immediately here.
tmpDevHandler->setModeNormal();
}
}
@ -243,7 +249,7 @@ ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF,
createRadSensorChipSelect(gpioComIF);
SpiCookie* spiCookieRadSensor =
new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR, RAD_SENSOR::READ_SIZE,
new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR, radSens::READ_SIZE,
spi::DEFAULT_MAX_1227_MODE, spi::DEFAULT_MAX_1227_SPEED);
spiCookieRadSensor->setMutexParams(MutexIF::TimeoutType::WAITING, spi::RAD_SENSOR_CS_TIMEOUT);
auto radSensor = new RadiationSensorHandler(objects::RAD_SENSOR, objects::SPI_MAIN_COM_IF,
@ -505,7 +511,7 @@ void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF*
debugGps = true;
#endif
RESET_ARGS_GNSS.gpioComIF = gpioComIF;
RESET_ARGS_GNSS.waitPeriodMs = 100;
RESET_ARGS_GNSS.waitPeriodMs = 5;
auto gpsCtrl = new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT,
enableHkSets, debugGps);
gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS);
@ -730,20 +736,12 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
// GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core
GpioCookie* gpioCookiePtmeIp = new GpioCookie;
GpiodRegularByLineName* gpio = nullptr;
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, "PAPB VC0");
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, "PAPB VC0");
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, "PAPB VC1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, "PAPB VC1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, "PAPB VC2");
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, "PAPB VC2");
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, "PAPB VC3");
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, "PAPB VC3");
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PTME_RESETN, "PTME RESETN",
@ -752,18 +750,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs");
// Creating virtual channel interfaces
VirtualChannelIF* vc0 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
VirtualChannelIF* vc1 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
VirtualChannelIF* vc2 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
VirtualChannelIF* vc3 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
VirtualChannelIF* vc0 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
VirtualChannelIF* vc1 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
VirtualChannelIF* vc2 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
VirtualChannelIF* vc3 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
// Creating ptme object and adding virtual channel interfaces
Ptme* ptme = new Ptme(objects::PTME);
ptme->addVcInterface(ccsds::VC0, vc0);
@ -908,8 +902,6 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF*
new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
gpioComIF, SdCardManager::instance(), stackHandler, false);
spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler);
// plPcduHandler->enablePeriodicPrintout(true, 5);
// static_cast<void>(plPcduHandler);
#if OBSW_TEST_PL_PCDU == 1
plPcduHandler->setStartUpImmediately();
#endif
@ -943,16 +935,7 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
starTrackerCookie->setNoFixedSizeReply();
StrComHandler* strComIF = new StrComHandler(objects::STR_COM_IF);
const char* paramJsonFile = nullptr;
#ifdef EGSE
paramJsonFile = "/home/pi/arcsec/json/flight-config.json";
#else
#if OBSW_STAR_TRACKER_GROUND_CONFIG == 1
paramJsonFile = "/mnt/sd0/startracker/ground-config.json";
#else
paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
#endif
#endif
const char* paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
if (paramJsonFile == nullptr) {
sif::error << "No valid Star Tracker parameter JSON file" << std::endl;
}
@ -965,12 +948,13 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
starTracker->setCustomFdir(strFdir);
}
void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets) {
void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets,
const char* i2cDev) {
auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY);
imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
new ImtqPollingTask(objects::IMTQ_POLLING, I2C_FATAL_ERRORS);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, i2cDev);
auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie,
power::Switches::PDU1_CH3_MGT_5V, enableHkSets);
imtqHandler->enableThermalModule(ThermalStateCfg());
@ -986,8 +970,8 @@ void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enable
#endif
}
void ObjectFactory::createBpxBatteryComponent(bool enableHkSets) {
I2cCookie* bpxI2cCookie = new I2cCookie(addresses::BPX_BATTERY, 100, q7s::I2C_PL_EIVE);
void ObjectFactory::createBpxBatteryComponent(bool enableHkSets, const char* i2cDev) {
I2cCookie* bpxI2cCookie = new I2cCookie(addresses::BPX_BATTERY, 100, i2cDev);
BpxBatteryHandler* bpxHandler = new BpxBatteryHandler(
objects::BPX_BATT_HANDLER, objects::I2C_COM_IF, bpxI2cCookie, enableHkSets);
bpxHandler->setStartUpImmediately();
@ -1025,3 +1009,50 @@ void ObjectFactory::createRadSensorChipSelect(LinuxLibgpioIF* gpioIF) {
gpioCookieRadSensor->addGpio(gpioIds::ENABLE_RADFET, gpio);
gpioChecker(gpioIF->addGpios(gpioCookieRadSensor), "RAD sensor");
}
void ObjectFactory::createPlI2cResetGpio(LinuxLibgpioIF* gpioIF) {
using namespace gpio;
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
if (gpioIF == nullptr) {
return;
}
GpioCookie* gpioI2cResetnCookie = new GpioCookie;
GpiodRegularByLineName* gpioI2cResetn = new GpiodRegularByLineName(
q7s::gpioNames::PL_I2C_ARESETN, "PL_I2C_ARESETN", Direction::OUT, Levels::HIGH);
gpioI2cResetnCookie->addGpio(gpioIds::PL_I2C_ARESETN, gpioI2cResetn);
gpioChecker(gpioIF->addGpios(gpioI2cResetnCookie), "PL I2C ARESETN");
// Reset I2C explicitely again.
gpioIF->pullLow(gpioIds::PL_I2C_ARESETN);
TaskFactory::delayTask(1);
gpioIF->pullHigh(gpioIds::PL_I2C_ARESETN);
}
}
ReturnValue_t ObjectFactory::readFirmwareVersion() {
uint32_t* mappedSysRomAddr = nullptr;
// The SYS ROM FPGA block is only available in those versions.
if (not(common::OBSW_VERSION_MAJOR >= 6) or (common::OBSW_VERSION_MAJOR == 4)) {
return returnvalue::OK;
}
// This has to come before the version announce because it might be required for retrieving
// the firmware version.
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
ReturnValue_t result =
sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
if (result != returnvalue::OK) {
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
return returnvalue::FAILED;
}
if (mappedSysRomAddr != nullptr) {
uint32_t firstEntry = *(reinterpret_cast<uint32_t*>(mappedSysRomAddr));
uint32_t secondEntry = *(reinterpret_cast<uint32_t*>(mappedSysRomAddr) + 1);
core::FW_VERSION_MAJOR = (firstEntry >> 24) & 0xff;
core::FW_VERSION_MINOR = (firstEntry >> 16) & 0xff;
core::FW_VERSION_REVISION = (firstEntry >> 8) & 0xff;
bool hasGitSha = (firstEntry & 0x0b1);
if (hasGitSha) {
std::memcpy(core::FW_VERSION_GIT_SHA, &secondEntry, 4);
}
}
return returnvalue::OK;
}

View File

@ -58,7 +58,7 @@ void createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher
bool enableHkSets);
void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF,
PowerSwitchIF* pwrSwitcher, Stack5VHandler& stackHandler);
void createTmpComponents();
void createTmpComponents(std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd);
void createRadSensorChipSelect(LinuxLibgpioIF* gpioIF);
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
void createAcsBoardGpios(GpioCookie& cookie);
@ -67,17 +67,19 @@ void createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF, Ser
adis1650x::Type adisType);
void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable,
HeaterHandler*& heaterHandler);
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets);
void createBpxBatteryComponent(bool enableHkSets);
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets, const char* i2cDev);
void createBpxBatteryComponent(bool enableHkSets, const char* i2cDev);
void createStrComponents(PowerSwitchIF* pwrSwitcher);
void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gpioIF);
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher);
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher);
ReturnValue_t createCcsdsComponents(CcsdsComponentArgs& args);
ReturnValue_t readFirmwareVersion();
void createMiscComponents();
void createTestComponents(LinuxLibgpioIF* gpioComIF);
void createPlI2cResetGpio(LinuxLibgpioIF* gpioComIF);
void testAcsBrdAss(AcsBoardAssembly* assAss);

View File

@ -11,13 +11,13 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/WatchdogHandler.h"
#include "commonConfig.h"
#include "core/scheduling.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/version.h"
#include "mission/acs/defs.h"
#include "mission/com/defs.h"
#include "mission/system/systemTree.h"
#include "q7sConfig.h"
#include "scheduling.h"
#include "watchdog/definitions.h"
static constexpr int OBSW_ALREADY_RUNNING = -2;

View File

@ -9,7 +9,6 @@
#include <vector>
#include "OBSWConfig.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/platform.h"
@ -21,6 +20,8 @@
#include "mission/pollingSeqTables.h"
#include "mission/scheduling.h"
#include "mission/utility/InitMission.h"
#include "objectFactory.h"
#include "q7sConfig.h"
/* This is configured for linux without CR */
#ifdef PLATFORM_UNIX
@ -324,6 +325,10 @@ void scheduling::initTasks() {
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
}
result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
}
#if OBSW_ADD_SYRLINKS == 1
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
@ -527,7 +532,15 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
FixedTimeslotTaskIF* i2cPst =
factory.createFixedTimeslotTask("I2C_PS_PST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.6,
missedDeadlineFunc, &RR_SCHEDULING);
result = pst::pstI2cProcessingSystem(i2cPst);
pst::TmpSchedConfig tmpSchedConf;
#if OBSW_Q7S_EM == 1
tmpSchedConf.scheduleTmpDev0 = true;
tmpSchedConf.scheduleTmpDev1 = true;
tmpSchedConf.schedulePlPcduDev0 = true;
tmpSchedConf.schedulePlPcduDev1 = true;
tmpSchedConf.scheduleIfBoardDev = true;
#endif
result = pst::pstI2c(tmpSchedConf, i2cPst);
if (result != returnvalue::OK) {
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
sif::warning << "scheduling::initTasks: I2C PST is empty" << std::endl;

View File

@ -129,7 +129,7 @@ ReturnValue_t Xadc::readValFromFile(const char* filename, T& val) {
sif::warning << "Xadc::readValFromFile: Failed to open file " << filename << std::endl;
return returnvalue::FAILED;
}
char valstring[MAX_STR_LENGTH] = "";
char valstring[MAX_STR_LENGTH]{};
char* returnVal = fgets(valstring, MAX_STR_LENGTH, fp);
if (returnVal == nullptr) {
sif::warning << "Xadc::readValFromFile: Failed to read string from file " << filename
@ -139,6 +139,11 @@ ReturnValue_t Xadc::readValFromFile(const char* filename, T& val) {
}
std::istringstream valSstream(valstring);
valSstream >> val;
if (valSstream.bad()) {
sif::warning << "Xadc: Conversion of value to target type failed" << std::endl;
fclose(fp);
return returnvalue::FAILED;
}
fclose(fp);
return returnvalue::OK;
}

View File

@ -77,6 +77,8 @@ enum gpioId_t {
CS_RAD_SENSOR,
ENABLE_RADFET,
PL_I2C_ARESETN,
PAPB_BUSY_N,
PAPB_EMPTY,
@ -93,15 +95,10 @@ enum gpioId_t {
EN_RW_CS,
SPI_MUX,
VC0_PAPB_EMPTY,
VC0_PAPB_BUSY,
VC1_PAPB_EMPTY,
VC1_PAPB_BUSY,
VC2_PAPB_EMPTY,
VC2_PAPB_BUSY,
VC3_PAPB_EMPTY,
VC3_PAPB_BUSY,
PTME_RESETN,
PDEC_RESET,

View File

@ -11,6 +11,8 @@ static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1";
static constexpr char OBSW_UPDATE_ARCHIVE_FILE_NAME[] = "eive-sw-update.tar.xz";
static constexpr char STRIPPED_OBSW_BINARY_FILE_NAME[] = "eive-obsw-stripped";
static constexpr char OBSW_VERSION_FILE_NAME[] = "obsw_version.txt";
static constexpr char PUS_SEQUENCE_COUNT_FILE[] = "pus-sequence-count.txt";
static constexpr char CFDP_SEQUENCE_COUNT_FILE[] = "cfdp-sequence-count.txt";
static constexpr char OBSW_PATH[] = "/usr/bin/eive-obsw";
static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt";

View File

@ -19,6 +19,7 @@ target_sources(
GpsCtrlDummy.cpp
GyroAdisDummy.cpp
GyroL3GD20Dummy.cpp
RadSensorDummy.cpp
MgmLIS3MDLDummy.cpp
PlPcduDummy.cpp
ExecutableComIfDummy.cpp

View File

@ -1,6 +1,6 @@
#include "CoreControllerDummy.h"
#include <bsp_q7s/core/CoreDefinitions.h>
#include <bsp_q7s/core/defs.h>
#include <objects/systemObjectList.h>
#include <cmath>

View File

@ -5,14 +5,19 @@
ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
power::Switch_t pwrSwitcher, bool enableHkSets)
: DeviceHandlerBase(objectId, comif, comCookie),
setNoTorque(this),
setWithTorque(this),
enableHkSets(enableHkSets),
statusSet(this),
dipoleSet(*this),
rawMtmNoTorque(this),
hkDatasetNoTorque(this),
rawMtmWithTorque(this),
hkDatasetWithTorque(this),
calMtmMeasurementSet(this),
switcher(pwrSwitcher) {}
ImtqDummy::~ImtqDummy() = default;
void ImtqDummy::doStartUp() { setMode(MODE_NORMAL); }
void ImtqDummy::doStartUp() { setMode(MODE_ON); }
void ImtqDummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
@ -79,17 +84,37 @@ ReturnValue_t ImtqDummy::initializeLocalDataPool(localpool::DataPool &localDataP
localDataPoolMap.emplace(imtq::MCU_TEMPERATURE_WT, new PoolEntry<int16_t>({0}));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(setNoTorque.getSid(), enableHkSets, 30.0));
subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 30.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(setWithTorque.getSid(), enableHkSets, 30.0));
subdp::DiagnosticsHkPeriodicParams(hkDatasetWithTorque.getSid(), enableHkSets, 30.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(rawMtmNoTorque.getSid(), false, 10.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(rawMtmWithTorque.getSid(), false, 10.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(calMtmMeasurementSet.getSid(), false, 10.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(statusSet.getSid(), false, 10.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(dipoleSet.getSid(), false, 10.0));
return DeviceHandlerBase::initializeLocalDataPool(localDataPoolMap, poolManager);
}
LocalPoolDataSetBase *ImtqDummy::getDataSetHandle(sid_t sid) {
if (sid == setNoTorque.getSid()) {
return &setNoTorque;
} else if (sid == setWithTorque.getSid()) {
return &setWithTorque;
if (sid == hkDatasetNoTorque.getSid()) {
return &hkDatasetNoTorque;
} else if (sid == dipoleSet.getSid()) {
return &dipoleSet;
} else if (sid == statusSet.getSid()) {
return &statusSet;
} else if (sid == hkDatasetWithTorque.getSid()) {
return &hkDatasetWithTorque;
} else if (sid == rawMtmWithTorque.getSid()) {
return &rawMtmWithTorque;
} else if (sid == calMtmMeasurementSet.getSid()) {
return &calMtmMeasurementSet;
} else if (sid == rawMtmNoTorque.getSid()) {
return &rawMtmNoTorque;
}
return nullptr;
}

View File

@ -18,11 +18,18 @@ class ImtqDummy : public DeviceHandlerBase {
~ImtqDummy() override;
protected:
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
imtq::HkDatasetNoTorque setNoTorque;
imtq::HkDatasetWithTorque setWithTorque;
bool enableHkSets;
imtq::StatusDataset statusSet;
imtq::DipoleActuationSet dipoleSet;
imtq::RawMtmMeasurementNoTorque rawMtmNoTorque;
imtq::HkDatasetNoTorque hkDatasetNoTorque;
imtq::RawMtmMeasurementWithTorque rawMtmWithTorque;
imtq::HkDatasetWithTorque hkDatasetWithTorque;
imtq::CalibratedMtmMeasurementSet calMtmMeasurementSet;
PoolEntry<uint8_t> statusMode = PoolEntry<uint8_t>({0});
PoolEntry<uint8_t> statusError = PoolEntry<uint8_t>({0});
PoolEntry<uint8_t> statusConfig = PoolEntry<uint8_t>({0});
@ -42,6 +49,8 @@ class ImtqDummy : public DeviceHandlerBase {
power::Switch_t switcher = power::NO_SWITCH;
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;

View File

@ -7,15 +7,21 @@ using namespace returnvalue;
Max31865Dummy::Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), set(this, EiveMax31855::EXCHANGE_SET_ID) {}
void Max31865Dummy::doStartUp() { setMode(MODE_ON); }
void Max31865Dummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
void Max31865Dummy::doShutDown() {
PoolReadGuard pg(&set);
set.setValidity(false, true);
setMode(MODE_OFF);
}
ReturnValue_t Max31865Dummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Max31865Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { return OK; }
ReturnValue_t Max31865Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Max31865Dummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return 0;
return NOTHING_TO_SEND;
}
ReturnValue_t Max31865Dummy::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {

View File

@ -7,7 +7,7 @@ PlPcduDummy::PlPcduDummy(object_id_t objectId, object_id_t comif, CookieIF *comC
PlPcduDummy::~PlPcduDummy() {}
void PlPcduDummy::doStartUp() { setMode(MODE_NORMAL); }
void PlPcduDummy::doStartUp() { setMode(MODE_ON); }
void PlPcduDummy::doShutDown() { setMode(MODE_OFF); }

View File

@ -0,0 +1,55 @@
#include "RadSensorDummy.h"
RadSensorDummy::RadSensorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), sensorSet(this) {}
RadSensorDummy::~RadSensorDummy() {}
void RadSensorDummy::doStartUp() { setMode(MODE_ON); }
void RadSensorDummy::doShutDown() { setMode(MODE_OFF); }
ReturnValue_t RadSensorDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t RadSensorDummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t RadSensorDummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return returnvalue::OK;
}
ReturnValue_t RadSensorDummy::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
return returnvalue::OK;
}
ReturnValue_t RadSensorDummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
return returnvalue::OK;
}
void RadSensorDummy::fillCommandAndReplyMap() {}
uint32_t RadSensorDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 500; }
ReturnValue_t RadSensorDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(radSens::TEMPERATURE_C, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(radSens::AIN0, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN1, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN4, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN5, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN6, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN7, new PoolEntry<uint16_t>({0}));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(sensorSet.getSid(), false, 20.0));
return returnvalue::OK;
return returnvalue::OK;
}
LocalPoolDataSetBase *RadSensorDummy::getDataSetHandle(sid_t sid) { return &sensorSet; }

35
dummies/RadSensorDummy.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "mission/payload/radSensorDefinitions.h"
class RadSensorDummy : public DeviceHandlerBase {
public:
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
static const DeviceCommandId_t PERIODIC_REPLY = 2;
static const uint8_t SIMPLE_COMMAND_DATA = 1;
static const uint8_t PERIODIC_REPLY_DATA = 2;
RadSensorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
virtual ~RadSensorDummy();
protected:
radSens::RadSensorDataset sensorSet;
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId,
size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
void fillCommandAndReplyMap() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
};

View File

@ -3,13 +3,24 @@
#include <mission/acs/rwHelpers.h>
RwDummy::RwDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie) {}
: DeviceHandlerBase(objectId, comif, comCookie),
statusSet(this),
lastResetStatusSet(this),
tmDataset(this),
rwSpeedActuationSet(*this) {}
RwDummy::~RwDummy() {}
void RwDummy::doStartUp() { setMode(MODE_ON); }
void RwDummy::doStartUp() {
statusSet.setReportingEnabled(true);
setMode(MODE_ON);
}
void RwDummy::doShutDown() { setMode(MODE_OFF); }
void RwDummy::doShutDown() {
statusSet.setReportingEnabled(false);
setMode(MODE_OFF);
}
ReturnValue_t RwDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; }
@ -74,5 +85,11 @@ ReturnValue_t RwDummy::initializeLocalDataPool(localpool::DataPool &localDataPoo
localDataPoolMap.emplace(rws::SPI_BYTES_READ, new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(rws::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
localDataPoolMap.emplace(rws::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({0}));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(statusSet.getSid(), false, 12.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(tmDataset.getSid(), false, 30.0));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(lastResetStatusSet.getSid(), false, 30.0));
return returnvalue::OK;
}

View File

@ -2,6 +2,7 @@
#define DUMMIES_RWDUMMY_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/acs/rwHelpers.h>
class RwDummy : public DeviceHandlerBase {
public:
@ -15,6 +16,11 @@ class RwDummy : public DeviceHandlerBase {
virtual ~RwDummy();
protected:
rws::StatusSet statusSet;
rws::LastResetSatus lastResetStatusSet;
rws::TmDataset tmDataset;
rws::RwSpeedActuationSet rwSpeedActuationSet;
PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0});
PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10});

View File

@ -5,7 +5,7 @@ SusDummy::SusDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
SusDummy::~SusDummy() {}
void SusDummy::doStartUp() { setMode(MODE_NORMAL); }
void SusDummy::doStartUp() { setMode(MODE_ON); }
void SusDummy::doShutDown() { setMode(MODE_OFF); }

View File

@ -7,9 +7,9 @@
#include <cstdlib>
#include <utility>
TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
Max31865DummyMap tempSensorDummies_,
Tmp1075DummyMap tempTmpSensorDummies_)
TemperatureSensorInserter::TemperatureSensorInserter(
object_id_t objectId, Max31865DummyMap tempSensorDummies_,
std::optional<Tmp1075DummyMap> tempTmpSensorDummies_)
: SystemObject(objectId),
max31865DummyMap(std::move(tempSensorDummies_)),
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
@ -25,8 +25,10 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
for (auto& rtdDummy : max31865DummyMap) {
rtdDummy.second->setTemperature(10, true);
}
for (auto& tmpDummy : tmp1075DummyMap) {
tmpDummy.second->setTemperature(10, true);
if (tmp1075DummyMap.has_value()) {
for (auto& tmpDummy : tmp1075DummyMap.value()) {
tmpDummy.second->setTemperature(10, true);
}
}
tempsWereInitialized = true;
}
@ -96,6 +98,25 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
}
break;
}
case (TestCase::COLD_PLOC_CONSECUTIVE): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
}
if (cycles == 30) {
sif::debug << "Setting warmer PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
}
if (cycles == 45) {
sif::debug << "Setting cold PLOC temperature again" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
}
if (cycles == 60) {
sif::debug << "Setting warmer PLOC temperature again" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
}
break;
}
case (TestCase::COLD_CAMERA): {
if (cycles == 15) {
sif::debug << "Setting cold CAM temperature" << std::endl;
@ -105,6 +126,21 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
sif::debug << "Setting CAM temperature back to normal" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true);
}
break;
}
case (TestCase::COLD_PLOC_STAYS_COLD): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-40, true);
}
break;
}
case (TestCase::COLD_CAMERA_STAYS_COLD): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-40, true);
}
break;
}
}
cycles++;

View File

@ -12,7 +12,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
using Max31865DummyMap = std::map<object_id_t, Max31865Dummy*>;
using Tmp1075DummyMap = std::map<object_id_t, Tmp1075Dummy*>;
explicit TemperatureSensorInserter(object_id_t objectId, Max31865DummyMap tempSensorDummies_,
Tmp1075DummyMap tempTmpSensorDummies_);
std::optional<Tmp1075DummyMap> tempTmpSensorDummies_);
ReturnValue_t initialize() override;
ReturnValue_t initializeAfterTaskCreation() override;
@ -22,7 +22,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
private:
Max31865DummyMap max31865DummyMap;
Tmp1075DummyMap tmp1075DummyMap;
std::optional<Tmp1075DummyMap> tmp1075DummyMap;
enum TestCase {
NONE = 0,
@ -32,6 +32,9 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
COLD_STR = 4,
COLD_STR_CONSECUTIVE = 5,
COLD_CAMERA = 6,
COLD_PLOC_CONSECUTIVE = 7,
COLD_PLOC_STAYS_COLD = 8,
COLD_CAMERA_STAYS_COLD = 9
};
int iteration = 0;
uint32_t cycles = 0;

View File

@ -8,35 +8,57 @@ using namespace returnvalue;
Tmp1075Dummy::Tmp1075Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), set(this) {}
void Tmp1075Dummy::doStartUp() { setMode(MODE_NORMAL); }
void Tmp1075Dummy::doShutDown() { setMode(MODE_OFF); }
void Tmp1075Dummy::doStartUp() { setMode(MODE_ON); }
void Tmp1075Dummy::doShutDown() {
PoolReadGuard pg(&set);
set.setValidity(false, true);
setMode(MODE_OFF);
}
ReturnValue_t Tmp1075Dummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Tmp1075Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { return OK; }
ReturnValue_t Tmp1075Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Tmp1075Dummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return 0;
return NOTHING_TO_SEND;
}
ReturnValue_t Tmp1075Dummy::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
return 0;
}
ReturnValue_t Tmp1075Dummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
return 0;
}
void Tmp1075Dummy::setTemperature(float temperature, bool valid) {
PoolReadGuard pg(&set);
set.temperatureCelcius.value = temperature;
set.setValidity(valid, true);
}
void Tmp1075Dummy::fillCommandAndReplyMap() {}
uint32_t Tmp1075Dummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 1000; }
ReturnValue_t Tmp1075Dummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry<float>({10.0}, true));
return OK;
}
ReturnValue_t Tmp1075Dummy::setHealth(HealthState health) {
if (health == FAULTY or health == PERMANENT_FAULTY) {
setMode(_MODE_SHUT_DOWN);
}
return DeviceHandlerBase::setHealth(health);
}
LocalPoolDataSetBase *Tmp1075Dummy::getDataSetHandle(sid_t sid) { return &set; }

View File

@ -26,6 +26,7 @@ class Tmp1075Dummy : public DeviceHandlerBase {
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
ReturnValue_t setHealth(HealthState health) override;
protected:
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;

View File

@ -18,6 +18,7 @@
#include <dummies/PlPcduDummy.h>
#include <dummies/PlocMpsocDummy.h>
#include <dummies/PlocSupervisorDummy.h>
#include <dummies/RadSensorDummy.h>
#include <dummies/RwDummy.h>
#include <dummies/SaDeploymentDummy.h>
#include <dummies/ScexDummy.h>
@ -34,6 +35,7 @@
#include "TemperatureSensorInserter.h"
#include "dummies/Max31865Dummy.h"
#include "dummies/SusDummy.h"
#include "dummies/Tmp1075Dummy.h"
#include "mission/genericFactory.h"
#include "mission/system/acs/acsModeTree.h"
@ -63,11 +65,14 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
rws[3] = new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy);
ObjectFactory::createRwAssy(pwrSwitcher, power::Switches::PDU2_CH2_RW_5V, rws, rwIds);
new SaDeplDummy(objects::SOLAR_ARRAY_DEPL_HANDLER);
auto* strAssy = new StrAssembly(objects::STR_ASSY);
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
auto* strDummy =
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
strDummy->connectModeTreeParent(*strAssy);
if (cfg.addStrDummy) {
auto* strAssy = new StrAssembly(objects::STR_ASSY);
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
auto* strDummy =
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
strDummy->connectModeTreeParent(*strAssy);
}
if (cfg.addSyrlinksDummies) {
auto* syrlinksDummy =
new SyrlinksDummy(objects::SYRLINKS_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
@ -191,25 +196,36 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
objects::RTD_15_IC18_IMTQ,
new Max31865Dummy(objects::RTD_15_IC18_IMTQ, objects::DUMMY_COM_IF, comCookieDummy));
std::map<object_id_t, Tmp1075Dummy*> tmpSensorDummies;
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_TCS_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_0, objects::DUMMY_COM_IF, comCookieDummy));
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_TCS_1,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_1, objects::DUMMY_COM_IF, comCookieDummy));
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_PLPCDU_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
// damaged.
// tmpSensorDummies.emplace(
// objects::TMP1075_HANDLER_PLPCDU_1,
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
// comCookieDummy));
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_IF_BOARD,
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
std::optional<TemperatureSensorInserter::Tmp1075DummyMap> tmpSensorDummies;
if (cfg.addTmpDummies) {
TemperatureSensorInserter::Tmp1075DummyMap tmpDummyMap;
if (cfg.tmp1075Cfg.addTcsBrd0) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_TCS_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_0, objects::DUMMY_COM_IF,
comCookieDummy));
}
if (cfg.tmp1075Cfg.addTcsBrd1) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_TCS_1,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_1, objects::DUMMY_COM_IF,
comCookieDummy));
}
if (cfg.tmp1075Cfg.addPlPcdu0) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_PLPCDU_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0,
objects::DUMMY_COM_IF, comCookieDummy));
}
if (cfg.tmp1075Cfg.addPlPcdu1) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_PLPCDU_1,
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1,
objects::DUMMY_COM_IF, comCookieDummy));
}
if (cfg.tmp1075Cfg.addIfBrd) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_IF_BOARD,
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD,
objects::DUMMY_COM_IF, comCookieDummy));
}
tmpSensorDummies = std::move(tmpDummyMap);
}
new TemperatureSensorInserter(objects::THERMAL_TEMP_INSERTER, rtdSensorDummies,
tmpSensorDummies);
TcsBoardAssembly* tcsBoardAssy =
@ -217,8 +233,10 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
for (auto& rtd : rtdSensorDummies) {
rtd.second->connectModeTreeParent(*tcsBoardAssy);
}
for (auto& tmp : tmpSensorDummies) {
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
if (tmpSensorDummies.has_value()) {
for (auto& tmp : tmpSensorDummies.value()) {
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
}
}
}
if (cfg.addCamSwitcherDummy) {
@ -226,11 +244,15 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
power::Switches::PDU2_CH8_PAYLOAD_CAMERA);
camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
auto* plPcduDummy =
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
if (cfg.addScexDummy) {
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
if (cfg.addPlPcduDummy) {
auto* plPcduDummy =
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
if (cfg.addPlocDummies) {
auto* plocMpsocDummy =
new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
@ -239,4 +261,9 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
objects::PLOC_SUPERVISOR_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, pwrSwitcher);
plocSupervisorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
if (cfg.addRadSensorDummy) {
auto* radSensorDummy =
new RadSensorDummy(objects::RAD_SENSOR, objects::DUMMY_COM_IF, comCookieDummy);
radSensorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
}

View File

@ -6,6 +6,14 @@ class GpioIF;
namespace dummy {
struct Tmp1075Cfg {
bool addTcsBrd0 = true;
bool addTcsBrd1 = true;
bool addPlPcdu0 = true;
bool addPlPcdu1 = true;
bool addIfBrd = true;
};
// Default values targeted towards EM.
struct DummyCfg {
bool addCoreCtrlCfg = true;
@ -19,7 +27,13 @@ struct DummyCfg {
bool addTempSensorDummies = true;
bool addRtdComIFDummy = true;
bool addPlocDummies = true;
bool addStrDummy = true;
bool addTmpDummies = true;
bool addRadSensorDummy = true;
bool addPlPcduDummy = false;
Tmp1075Cfg tmp1075Cfg;
bool addCamSwitcherDummy = false;
bool addScexDummy = false;
};
void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF, bool enableHkSets);

2
fsfw

@ -1 +1 @@
Subproject commit 0a977ea688cd78585aabb9ba511eaf8030452712
Subproject commit d575da85407e029dabecaffa5368f0c9f1034941

View File

@ -133,6 +133,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
11802;0x2e1a;RESET_OCCURED;LOW;No description;mission/acs/rwHelpers.h
11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h
11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h
11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h
12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h
12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h
12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h
@ -254,6 +255,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
@ -271,6 +273,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14010;0x36ba;TRYING_I2C_RECOVERY;HIGH;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
@ -279,6 +283,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;mission/controller/tcsDefs.h
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
133 11802 0x2e1a RESET_OCCURED LOW No description mission/acs/rwHelpers.h
134 11901 0x2e7d BOOTING_FIRMWARE_FAILED_EVENT LOW Failed to boot firmware mission/acs/str/StarTrackerHandler.h
135 11902 0x2e7e BOOTING_BOOTLOADER_FAILED_EVENT LOW Failed to boot star tracker into bootloader mode mission/acs/str/StarTrackerHandler.h
136 11903 0x2e7f COM_ERROR_REPLY_RECEIVED LOW Received COM error. P1: Communication Error ID (datasheet p32) mission/acs/str/StarTrackerHandler.h
137 12001 0x2ee1 SUPV_MEMORY_READ_RPT_CRC_FAILURE LOW PLOC supervisor crc failure in telemetry packet linux/payload/PlocSupervisorHandler.h
138 12002 0x2ee2 SUPV_UNKNOWN_TM LOW Unhandled event. P1: APID, P2: Service ID linux/payload/PlocSupervisorHandler.h
139 12003 0x2ee3 SUPV_UNINIMPLEMENTED_TM LOW No description linux/payload/PlocSupervisorHandler.h
255 13800 0x35e8 MISSING_PACKET LOW No description mission/payload/scexHelpers.h
256 13801 0x35e9 EXPERIMENT_TIMEDOUT LOW No description mission/payload/scexHelpers.h
257 13802 0x35ea MULTI_PACKET_COMMAND_DONE INFO No description mission/payload/scexHelpers.h
258 13803 0x35eb FS_UNUSABLE LOW No description mission/payload/scexHelpers.h
259 13901 0x364d SET_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
260 13902 0x364e GET_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
261 13903 0x364f INSERT_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
273 14010 0x36ba TRYING_I2C_RECOVERY HIGH I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices. mission/sysDefs.h
274 14011 0x36bb I2C_REBOOT HIGH I2C is unavailable. Recovery did not work, performing full reboot. mission/sysDefs.h
275 14012 0x36bc PDEC_REBOOT HIGH PDEC recovery through reset was not possible, performing full reboot. mission/sysDefs.h
276 14013 0x36bd FIRMWARE_INFO INFO Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set. mission/sysDefs.h
277 14014 0x36be ACTIVE_SD_INFO INFO Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1 mission/sysDefs.h
278 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/tcsDefs.h
279 14101 0x3715 NO_HEALTHY_HEATER_AVAILABLE MEDIUM No description mission/controller/tcsDefs.h
280 14102 0x3716 SYRLINKS_OVERHEATING HIGH No description mission/controller/tcsDefs.h
283 14106 0x371a PCDU_SYSTEM_OVERHEATING HIGH No description mission/controller/tcsDefs.h
284 14107 0x371b HEATER_NOT_OFF_FOR_OFF_MODE MEDIUM No description mission/controller/tcsDefs.h
285 14108 0x371c MGT_OVERHEATING HIGH No description mission/controller/tcsDefs.h
286 14109 0x371d TCS_SWITCHING_HEATER_ON INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
287 14110 0x371e TCS_SWITCHING_HEATER_OFF INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
288 14111 0x371f TCS_HEATER_MAX_BURN_TIME_REACHED MEDIUM P1: Heater index. P2: Maximum burn time for heater. mission/controller/tcsDefs.h
289 14201 0x3779 TX_TIMER_EXPIRED INFO The transmit timer to protect the Syrlinks expired P1: The current timer value mission/system/com/ComSubsystem.h
290 14202 0x377a BIT_LOCK_TX_ON INFO Transmitter will be turned on due to detection of bitlock mission/system/com/ComSubsystem.h
291 14300 0x37dc POSSIBLE_FILE_CORRUPTION LOW P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp. mission/persistentTmStoreDefs.h

View File

@ -133,6 +133,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
11802;0x2e1a;RESET_OCCURED;LOW;No description;mission/acs/rwHelpers.h
11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h
11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h
11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h
12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h
12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h
12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h
@ -254,6 +255,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
@ -271,6 +273,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14010;0x36ba;TRYING_I2C_RECOVERY;HIGH;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
@ -279,6 +283,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;mission/controller/tcsDefs.h
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
133 11802 0x2e1a RESET_OCCURED LOW No description mission/acs/rwHelpers.h
134 11901 0x2e7d BOOTING_FIRMWARE_FAILED_EVENT LOW Failed to boot firmware mission/acs/str/StarTrackerHandler.h
135 11902 0x2e7e BOOTING_BOOTLOADER_FAILED_EVENT LOW Failed to boot star tracker into bootloader mode mission/acs/str/StarTrackerHandler.h
136 11903 0x2e7f COM_ERROR_REPLY_RECEIVED LOW Received COM error. P1: Communication Error ID (datasheet p32) mission/acs/str/StarTrackerHandler.h
137 12001 0x2ee1 SUPV_MEMORY_READ_RPT_CRC_FAILURE LOW PLOC supervisor crc failure in telemetry packet linux/payload/PlocSupervisorHandler.h
138 12002 0x2ee2 SUPV_UNKNOWN_TM LOW Unhandled event. P1: APID, P2: Service ID linux/payload/PlocSupervisorHandler.h
139 12003 0x2ee3 SUPV_UNINIMPLEMENTED_TM LOW No description linux/payload/PlocSupervisorHandler.h
255 13800 0x35e8 MISSING_PACKET LOW No description mission/payload/scexHelpers.h
256 13801 0x35e9 EXPERIMENT_TIMEDOUT LOW No description mission/payload/scexHelpers.h
257 13802 0x35ea MULTI_PACKET_COMMAND_DONE INFO No description mission/payload/scexHelpers.h
258 13803 0x35eb FS_UNUSABLE LOW No description mission/payload/scexHelpers.h
259 13901 0x364d SET_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
260 13902 0x364e GET_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
261 13903 0x364f INSERT_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
273 14010 0x36ba TRYING_I2C_RECOVERY HIGH I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices. mission/sysDefs.h
274 14011 0x36bb I2C_REBOOT HIGH I2C is unavailable. Recovery did not work, performing full reboot. mission/sysDefs.h
275 14012 0x36bc PDEC_REBOOT HIGH PDEC recovery through reset was not possible, performing full reboot. mission/sysDefs.h
276 14013 0x36bd FIRMWARE_INFO INFO Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set. mission/sysDefs.h
277 14014 0x36be ACTIVE_SD_INFO INFO Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1 mission/sysDefs.h
278 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/tcsDefs.h
279 14101 0x3715 NO_HEALTHY_HEATER_AVAILABLE MEDIUM No description mission/controller/tcsDefs.h
280 14102 0x3716 SYRLINKS_OVERHEATING HIGH No description mission/controller/tcsDefs.h
283 14106 0x371a PCDU_SYSTEM_OVERHEATING HIGH No description mission/controller/tcsDefs.h
284 14107 0x371b HEATER_NOT_OFF_FOR_OFF_MODE MEDIUM No description mission/controller/tcsDefs.h
285 14108 0x371c MGT_OVERHEATING HIGH No description mission/controller/tcsDefs.h
286 14109 0x371d TCS_SWITCHING_HEATER_ON INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
287 14110 0x371e TCS_SWITCHING_HEATER_OFF INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
288 14111 0x371f TCS_HEATER_MAX_BURN_TIME_REACHED MEDIUM P1: Heater index. P2: Maximum burn time for heater. mission/controller/tcsDefs.h
289 14201 0x3779 TX_TIMER_EXPIRED INFO The transmit timer to protect the Syrlinks expired P1: The current timer value mission/system/com/ComSubsystem.h
290 14202 0x377a BIT_LOCK_TX_ON INFO Transmitter will be turned on due to detection of bitlock mission/system/com/ComSubsystem.h
291 14300 0x37dc POSSIBLE_FILE_CORRUPTION LOW P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp. mission/persistentTmStoreDefs.h

View File

@ -54,9 +54,13 @@ class BspConfig:
# Store this file in the root of the generators folder
self.csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_events.csv")
self.subsystems_csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv")
self.subsystems_csv_filename = Path(
f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv"
)
self.csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/events.csv")
self.subsystem_csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv")
self.subsystem_csv_copy_dest = Path(
f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv"
)
if (
self.bsp_select == BspType.BSP_Q7S

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 296 translations.
* @brief Auto-generated event translation file. Contains 303 translations.
* @details
* Generated on: 2023-06-13 07:54:32
* Generated on: 2023-08-03 13:36:37
*/
#include "translateEvents.h"
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
@ -260,6 +261,7 @@ const char *TX_OFF_STRING = "TX_OFF";
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
@ -277,6 +279,8 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -285,6 +289,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -572,6 +579,8 @@ const char *translateEvents(Event event) {
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
case (11902):
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
case (11903):
return COM_ERROR_REPLY_RECEIVED_STRING;
case (12001):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (12002):
@ -814,6 +823,8 @@ const char *translateEvents(Event event) {
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
case (13803):
return FS_UNUSABLE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
@ -848,6 +859,10 @@ const char *translateEvents(Event event) {
return I2C_REBOOT_STRING;
case (14012):
return PDEC_REBOOT_STRING;
case (14013):
return FIRMWARE_INFO_STRING;
case (14014):
return ACTIVE_SD_INFO_STRING;
case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):
@ -864,6 +879,12 @@ const char *translateEvents(Event event) {
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
case (14108):
return MGT_OVERHEATING_STRING;
case (14109):
return TCS_SWITCHING_HEATER_ON_STRING;
case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201):
return TX_TIMER_EXPIRED_STRING;
case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 175 translations.
* Generated on: 2023-06-13 07:54:32
* Generated on: 2023-08-03 13:36:37
*/
#include "translateObjects.h"

View File

@ -2,6 +2,7 @@
#include <fcntl.h>
#include <fsfw/filesystem/HasFileSystemIF.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <mission/acs/str/strHelpers.h>
@ -23,6 +24,8 @@ extern "C" {
using namespace returnvalue;
static constexpr bool PACKET_WIRETAPPING = false;
StrComHandler::StrComHandler(object_id_t objectId) : SystemObject(objectId) {
lock = MutexFactory::instance()->createMutex();
semaphore.acquire();
@ -52,7 +55,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
case InternalState::POLL_ONE_REPLY: {
// Stopwatch watch;
replyTimeout.setTimeout(200);
replyResult = readOneReply(static_cast<uint32_t>(state));
readOneReply(static_cast<uint32_t>(state));
{
MutexGuard mg(lock);
replyWasReceived = true;
@ -680,6 +683,10 @@ ReturnValue_t StrComHandler::sendMessage(CookieIF* cookie, const uint8_t* sendDa
const uint8_t* txFrame;
size_t frameLen;
datalinkLayer.encodeFrame(sendData, sendLen, &txFrame, frameLen);
if (PACKET_WIRETAPPING) {
sif::debug << "Sending STR frame" << std::endl;
arrayprinter::print(txFrame, frameLen);
}
ssize_t bytesWritten = write(serialPort, txFrame, frameLen);
if (bytesWritten != static_cast<ssize_t>(frameLen)) {
sif::warning << "StrComHandler: Sending packet failed" << std::endl;
@ -709,13 +716,11 @@ ReturnValue_t StrComHandler::requestReceiveMessage(CookieIF* cookie, size_t requ
}
ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
// Consider it a configuration error if the task is not done with a command -> reply cycle
// in time.
bool replyWasReceived = false;
{
MutexGuard mg(lock);
if (state != InternalState::SLEEPING) {
return BUSY;
return returnvalue::OK;
}
replyWasReceived = this->replyWasReceived;
}
@ -728,7 +733,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf
*size = replyLen;
}
replyLen = 0;
return replyResult;
return returnvalue::OK;
}
ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) {
@ -782,8 +787,10 @@ ReturnValue_t StrComHandler::handleSerialReception() {
<< std::endl;
return FAILED;
} else if (bytesRead > 0) {
// sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl;
// arrayprinter::print(recBuf.data(), bytesRead);
if (PACKET_WIRETAPPING) {
sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl;
arrayprinter::print(recBuf.data(), bytesRead);
}
datalinkLayer.feedData(recBuf.data(), bytesRead);
}
return OK;
@ -797,6 +804,10 @@ ReturnValue_t StrComHandler::readOneReply(uint32_t failParameter) {
handleSerialReception();
result = datalinkLayer.checkRingBufForFrame(&replyPtr, replyLen);
if (result == returnvalue::OK) {
if (PACKET_WIRETAPPING) {
sif::debug << "Received STR reply frame" << std::endl;
arrayprinter::print(replyPtr, replyLen);
}
return returnvalue::OK;
} else if (result != ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
triggerEvent(STR_HELPER_DEC_ERROR, result, failParameter);

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 296 translations.
* @brief Auto-generated event translation file. Contains 303 translations.
* @details
* Generated on: 2023-06-13 07:54:32
* Generated on: 2023-08-03 13:36:37
*/
#include "translateEvents.h"
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
@ -260,6 +261,7 @@ const char *TX_OFF_STRING = "TX_OFF";
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
@ -277,6 +279,8 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -285,6 +289,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -572,6 +579,8 @@ const char *translateEvents(Event event) {
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
case (11902):
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
case (11903):
return COM_ERROR_REPLY_RECEIVED_STRING;
case (12001):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (12002):
@ -814,6 +823,8 @@ const char *translateEvents(Event event) {
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
case (13803):
return FS_UNUSABLE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
@ -848,6 +859,10 @@ const char *translateEvents(Event event) {
return I2C_REBOOT_STRING;
case (14012):
return PDEC_REBOOT_STRING;
case (14013):
return FIRMWARE_INFO_STRING;
case (14014):
return ACTIVE_SD_INFO_STRING;
case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):
@ -864,6 +879,12 @@ const char *translateEvents(Event event) {
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
case (14108):
return MGT_OVERHEATING_STRING;
case (14109):
return TCS_SWITCHING_HEATER_ON_STRING;
case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201):
return TX_TIMER_EXPIRED_STRING;
case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 175 translations.
* Generated on: 2023-06-13 07:54:32
* Generated on: 2023-08-03 13:36:37
*/
#include "translateObjects.h"

View File

@ -16,9 +16,9 @@ AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNu
AxiPtmeConfig::~AxiPtmeConfig() {}
ReturnValue_t AxiPtmeConfig::initialize() {
ReturnValue_t result = returnvalue::OK;
UioMapper uioMapper(axiUio, mapNum);
result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
ReturnValue_t result =
uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@ -26,8 +26,7 @@ ReturnValue_t AxiPtmeConfig::initialize() {
}
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
ReturnValue_t result = returnvalue::OK;
result = mutex->lockMutex(timeoutType, mutexTimeout);
ReturnValue_t result = mutex->lockMutex(timeoutType, mutexTimeout);
if (result != returnvalue::OK) {
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
return returnvalue::FAILED;
@ -41,6 +40,11 @@ ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
return returnvalue::OK;
}
uint8_t AxiPtmeConfig::readCaduRateReg() {
MutexGuard mg(mutex);
return static_cast<uint8_t>(*(baseAddress + CADU_BITRATE_REG));
}
void AxiPtmeConfig::enableTxclockManipulator() {
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
}

View File

@ -38,6 +38,7 @@ class AxiPtmeConfig : public SystemObject {
* frequency of the clock connected to the bit clock input of PTME.
*/
ReturnValue_t writeCaduRateReg(uint8_t rateVal);
uint8_t readCaduRateReg();
/**
* @brief Next to functions control the tx clock manipulator component

View File

@ -7,20 +7,16 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
gpioId_t papbEmptyId, std::string uioFile, int mapNum)
: gpioComIF(gpioComIF),
papbBusyId(papbBusyId),
papbEmptyId(papbEmptyId),
uioFile(std::move(uioFile)),
mapNum(mapNum) {}
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId,
std::string uioFile, int mapNum)
: gpioComIF(gpioComIF), papbEmptyId(papbEmptyId), uioFile(std::move(uioFile)), mapNum(mapNum) {}
PapbVcInterface::~PapbVcInterface() {}
ReturnValue_t PapbVcInterface::initialize() {
UioMapper uioMapper(uioFile, mapNum);
ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg),
UioMapper::Permissions::WRITE_ONLY);
UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@ -32,63 +28,27 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
if (size < 4) {
return returnvalue::FAILED;
}
if (pollInterfaceReadiness(0, true) == returnvalue::OK) {
if (pollReadyForPacket()) {
startPacketTransfer(ByteWidthCfg::ONE);
} else {
return DirectTmSinkIF::IS_BUSY;
}
// TODO: This should work but does not.. :(
// size_t idx = 0;
// while (idx < size) {
//
// nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
// if ((size - idx) < 4) {
// *vcBaseReg = CONFIG_DATA_INPUT | (size - idx - 1);
// usleep(1);
// }
// if (pollPapbBusySignal(2) == returnvalue::OK) {
// // vcBaseReg + DATA_REG_OFFSET + 3 = static_cast<uint8_t>(data + idx);
// // vcBaseReg + DATA_REG_OFFSET + 2 = static_cast<uint8_t>(data + idx + 1);
// // vcBaseReg + DATA_REG_OFFSET + 1 = static_cast<uint8_t>(data + idx + 2);
// // vcBaseReg + DATA_REG_OFFSET = static_cast<uint8_t>(data + idx + 3);
//
// // std::memcpy((vcBaseReg + DATA_REG_OFFSET), data + idx , nextWriteSize);
// *(vcBaseReg + DATA_REG_OFFSET) = *reinterpret_cast<const uint32_t*>(data + idx);
// //uint8_t* byteReg = reinterpret_cast<uint8_t*>(vcBaseReg + DATA_REG_OFFSET);
//
// //byteReg[0] = data[idx];
// //byteReg[1] = data[idx];
// } else {
// abortPacketTransfer();
// return returnvalue::FAILED;
// }
// // TODO: Change this after the bugfix. Right now, the PAPB ignores the content of the byte
// // width configuration.5
// // It's okay to increment by a larger amount for the last segment here, loop will be over
// // in any case.
// idx += 4;
// }
for (size_t idx = 0; idx < size; idx++) {
// This delay is super-important, DO NOT REMOVE!
// Polling the GPIO or the config register too often messes up the scheduler.
// TODO: Maybe this should not be done like this. It would be better if there was a custom
// FPGA module which can accept packets and then takes care of dumping that packet into
// the PTME. DMA would be an ideal solution for this.
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
} else {
abortPacketTransfer();
return returnvalue::FAILED;
}
}
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
completePacketTransfer();
} else {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
for (size_t idx = 0; idx < size; idx++) {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
}
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
completePacketTransfer();
return returnvalue::OK;
}
@ -98,63 +58,49 @@ void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
bool checkReadyState) const {
uint32_t busyIdx = 0;
nextDelay.tv_nsec = FIRST_DELAY_PAPB_POLLING_NS;
while (true) {
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
uint32_t reg = *vcBaseReg;
bool busy = (reg >> 5) & 0b1;
bool ready = (reg >> 6) & 0b1;
if (not busy) {
return returnvalue::OK;
}
if (checkReadyState and not ready) {
return PAPB_BUSY;
}
busyIdx++;
if (busyIdx >= maxPollRetries) {
return PAPB_BUSY;
}
// Ignore signal handling here for now.
nanosleep(&nextDelay, &remDelay);
// Adaptive delay.
if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) {
nextDelay.tv_nsec *= 2;
}
}
return returnvalue::OK;
bool PapbVcInterface::pollReadyForPacket() const {
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
uint32_t reg = *vcBaseReg;
return (reg >> 6) & 0b1;
}
void PapbVcInterface::isVcInterfaceBufferEmpty() {
bool PapbVcInterface::isVcInterfaceBufferEmpty() {
ReturnValue_t result = returnvalue::OK;
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
result = gpioComIF->readGpio(papbEmptyId, papbEmptyState);
if (result != returnvalue::OK) {
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return;
sif::error << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return true;
}
if (papbEmptyState == gpio::Levels::HIGH) {
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
} else {
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
return true;
}
return;
return false;
}
bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; }
bool PapbVcInterface::isBusy() const { return not pollReadyForPacket(); }
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const {
uint32_t reg;
uint32_t idx = 0;
while (idx < maxCycles) {
reg = *vcBaseReg;
// Busy bit.
if (not((reg >> 5) & 0b1)) {
return true;
}
idx++;
}
return false;
}
ReturnValue_t PapbVcInterface::sendTestFrame() {
/** Size of one complete transfer frame data field amounts to 1105 bytes */
uint8_t testPacket[1105];

View File

@ -30,8 +30,7 @@ class PapbVcInterface : public VirtualChannelIF {
* @param uioFile UIO file providing access to the PAPB bus
* @param mapNum Map number of UIO map associated with this virtual channel
*/
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId,
std::string uioFile, int mapNum);
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId, std::string uioFile, int mapNum);
virtual ~PapbVcInterface();
bool isBusy() const override;
@ -81,11 +80,9 @@ class PapbVcInterface : public VirtualChannelIF {
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
static constexpr uint32_t MAX_BUSY_POLLS = 1000;
LinuxLibgpioIF* gpioComIF = nullptr;
/** Pulled to low when virtual channel not ready to receive data */
gpioId_t papbBusyId = gpio::NO_GPIO;
/** High when external buffer memory of virtual channel is empty */
gpioId_t papbEmptyId = gpio::NO_GPIO;
@ -120,13 +117,15 @@ class PapbVcInterface : public VirtualChannelIF {
*
* @return returnvalue::OK when ready to receive data else PAPB_BUSY.
*/
inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const;
inline bool pollReadyForPacket() const;
inline bool pollReadyForOctet(uint32_t maxCycles) const;
/**
* @brief This function can be used for debugging to check whether there are packets in
* the packet buffer of the virtual channel or not.
*/
void isVcInterfaceBufferEmpty();
bool isVcInterfaceBufferEmpty();
/**
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)

View File

@ -26,6 +26,11 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
return axiPtmeConfig->writeCaduRateReg(static_cast<uint8_t>(rateVal));
}
uint32_t PtmeConfig::getRate() {
uint8_t rateReg = axiPtmeConfig->readCaduRateReg();
return (BIT_CLK_FREQ / (rateReg + 1));
}
void PtmeConfig::invertTxClock(bool invert) {
if (invert) {
axiPtmeConfig->enableTxclockInversion();

View File

@ -32,6 +32,7 @@ class PtmeConfig : public SystemObject {
* of the CADU clock due to the convolutional code added by the s-Band transceiver.
*/
ReturnValue_t setRate(uint32_t bitRate);
uint32_t getRate();
/**
* @brief Will change the time the tx data signal is updated with respect to the tx clock

View File

@ -57,7 +57,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -119,7 +120,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -187,7 +189,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -255,7 +258,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -418,7 +422,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -580,7 +585,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -750,7 +756,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -917,7 +924,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug-q7s|cmake-build-release-q7s-em|cmake-build-release-q7s/_deps/etl-src/uml|cmake-build-release-q7s/_deps/etl-src/test|cmake-build-release-q7s/_deps/etl-src/temp|cmake-build-release-q7s/_deps/etl-src/support|cmake-build-release-q7s/_deps/etl-src/subprojects|cmake-build-release-q7s/_deps/etl-src/scripts|cmake-build-release-q7s/_deps/etl-src/images|cmake-build-release-q7s/_deps/etl-src/examples|cmake-build-release-q7s/_deps/etl-src/cmake|cmake-build-release-q7s/_deps/etl-src/arduino|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s|cmake-build-release-q7s-em|cmake-build-release-q7s/_deps/etl-src/uml|cmake-build-release-q7s/_deps/etl-src/test|cmake-build-release-q7s/_deps/etl-src/temp|cmake-build-release-q7s/_deps/etl-src/support|cmake-build-release-q7s/_deps/etl-src/subprojects|cmake-build-release-q7s/_deps/etl-src/scripts|cmake-build-release-q7s/_deps/etl-src/images|cmake-build-release-q7s/_deps/etl-src/examples|cmake-build-release-q7s/_deps/etl-src/cmake|cmake-build-release-q7s/_deps/etl-src/arduino|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -1084,7 +1092,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -1149,7 +1158,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -1172,7 +1182,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561" name="eive-q7s-debug-em" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.enablement=null,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.image=null,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=null" parent="org.eclipse.cdt.build.core.emptycfg">
<configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561" name="eive-q7s-debug-em" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.enablement=null,org.eclipse.cdt.docker.launcher.containerbuild.property.dockerdpath=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=unix:///var/run/docker.sock,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.image=null" parent="org.eclipse.cdt.build.core.emptycfg">
<folderInfo id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561." name="/" resourcePath="">
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.1640701365" name="Arm Cross GCC" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.base">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.564607779" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
@ -1317,7 +1327,9 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug-q7s|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug-q7s|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="cmake-build-debug-q7s-em/_deps/etl-src/include"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>
@ -1386,7 +1398,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry excluding="cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
</sourceEntries>
</configuration>
</storageModule>

View File

@ -30,6 +30,7 @@ void SusHandler::doStartUp() {
void SusHandler::doShutDown() {
if (internalState != InternalState::SHUTDOWN) {
PoolReadGuard pg(&dataset);
dataset.tempC = thermal::INVALID_TEMPERATURE;
dataset.setValidity(false, true);
internalState = InternalState::SHUTDOWN;
commandExecuted = false;

View File

@ -26,10 +26,18 @@ enum SafeModeStrategy : uint8_t {
SAFECTRL_OFF = 0,
SAFECTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
SAFECTRL_NO_SENSORS_FOR_CONTROL = 2,
SAFECTRL_ACTIVE_MEKF = 10,
SAFECTRL_WITHOUT_MEKF = 11,
SAFECTRL_ECLIPSE_DAMPING = 12,
SAFECTRL_ECLIPSE_IDELING = 13,
// OBSW version <= v6.1.0
LEGACY_SAFECTRL_ACTIVE_MEKF = 10,
LEGACY_SAFECTRL_WITHOUT_MEKF = 11,
LEGACY_SAFECTRL_ECLIPSE_DAMPING = 12,
LEGACY_SAFECTRL_ECLIPSE_IDELING = 13,
// Added in v6.2.0
SAFECTRL_MEKF = 14,
SAFECTRL_GYR = 15,
SAFECTRL_SUSMGM = 16,
SAFECTRL_ECLIPSE_DAMPING_GYR = 17,
SAFECTRL_ECLIPSE_DAMPING_SUSMGM = 18,
SAFECTRL_ECLIPSE_IDELING = 19,
SAFECTRL_DETUMBLE_FULL = 20,
SAFECTRL_DETUMBLE_DETERIORATED = 21,
};

View File

@ -1,3 +1,4 @@
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <mission/acs/str/StarTrackerHandler.h>
@ -18,6 +19,7 @@ extern "C" {
#include "OBSWConfig.h"
#include "eive/definitions.h"
#include "fsfw/thermal/tcsDefinitions.h"
std::atomic_bool JCFG_DONE(false);
@ -87,7 +89,6 @@ void StarTrackerHandler::doStartUp() {
default:
return;
}
solutionSet.setReportingEnabled(true);
startupState = StartupState::DONE;
internalState = InternalState::IDLE;
setMode(_MODE_TO_ON);
@ -106,11 +107,14 @@ void StarTrackerHandler::doShutDown() {
solutionSet.caliQx.value = 0.0;
solutionSet.caliQy.value = 0.0;
solutionSet.caliQz.value = 0.0;
solutionSet.isTrustWorthy = 0;
solutionSet.isTrustWorthy.value = 0;
solutionSet.setValidity(false, true);
}
{
PoolReadGuard pg(&temperatureSet);
temperatureSet.fpgaTemperature = thermal::INVALID_TEMPERATURE;
temperatureSet.cmosTemperature = thermal::INVALID_TEMPERATURE;
temperatureSet.mcuTemperature = thermal::INVALID_TEMPERATURE;
temperatureSet.setValidity(false, true);
}
reinitNextSetParam = false;
@ -321,7 +325,7 @@ ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id
ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
switch (internalState) {
case InternalState::BOOT_FIRMWARE: {
if (bootState == FwBootState::WAIT_FOR_EXECUTION or bootState == FwBootState::VERIFY_BOOT) {
if (bootState == FwBootState::VERIFY_BOOT or isAwaitingReply()) {
return NOTHING_TO_SEND;
}
if (bootState == FwBootState::NONE) {
@ -345,74 +349,69 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t
*id = startracker::REQ_VERSION;
return buildCommandFromCommand(*id, nullptr, 0);
}
case (FwBootState::SET_TIME): {
*id = startracker::SET_TIME_FROM_SYS_TIME;
return buildCommandFromCommand(*id, nullptr, 0);
}
case (FwBootState::LOGLEVEL): {
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LOGLEVEL;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
}
case (FwBootState::LIMITS): {
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LIMITS;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
}
case (FwBootState::TRACKING): {
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::TRACKING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
}
case FwBootState::MOUNTING:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::MOUNTING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::IMAGE_PROCESSOR:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::IMAGE_PROCESSOR;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::CAMERA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::CENTROIDING:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CENTROIDING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LISA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LISA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::MATCHING:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::MATCHING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::VALIDATION:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::VALIDATION;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::ALGO:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::ALGO;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LOG_SUBSCRIPTION:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LOGSUBSCRIPTION;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::DEBUG_CAMERA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::DEBUG_CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::AUTO_THRESHOLD:
*id = startracker::AUTO_THRESHOLD;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
default: {
sif::error << "STR: Unexpected boot state" << (int)bootState << std::endl;
return NOTHING_TO_SEND;
@ -455,6 +454,20 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
preparePingRequest();
return returnvalue::OK;
}
case (startracker::SET_TIME_FROM_SYS_TIME): {
SetTimeActionRequest setTimeRequest{};
timeval tv;
Clock::getClock(&tv);
setTimeRequest.unixTime =
(static_cast<uint64_t>(tv.tv_sec) * 1000 * 1000) + (static_cast<uint64_t>(tv.tv_usec));
arc_pack_settime_action_req(&setTimeRequest, commandBuffer, &rawPacketLen);
size_t serLen = 0;
// Time in milliseconds. Manual serialization because arcsec API ignores endianness.
SerializeAdapter::serialize(&setTimeRequest.unixTime, commandBuffer + 2, &serLen,
sizeof(commandBuffer) - 2, SerializeIF::Endianness::LITTLE);
rawPacket = commandBuffer;
return returnvalue::OK;
}
case (startracker::REQ_TIME): {
prepareTimeRequest();
return returnvalue::OK;
@ -547,6 +560,11 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel, reinitNextSetParam);
return result;
}
case (startracker::AUTO_THRESHOLD): {
result =
prepareParamCommand(commandData, commandDataLen, jcfgs.autoThreshold, reinitNextSetParam);
return result;
}
case (startracker::LOGSUBSCRIPTION): {
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription,
reinitNextSetParam);
@ -651,19 +669,23 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LOGLEVEL, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::SET_TIME_FROM_SYS_TIME, 2, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LOGSUBSCRIPTION, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::DEBUG_CAMERA, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LIMITS, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::AUTO_THRESHOLD, 2, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::MOUNTING, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::IMAGE_PROCESSOR, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::CAMERA, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::CENTROIDING, 3, nullptr,
this->insertInCommandAndReplyMap(startracker::CENTROIDING, 2, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LISA, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
@ -810,6 +832,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
setMode(toMode, startracker::SUBMODE_FIRMWARE);
}
sif::info << "STR: Firmware boot success" << std::endl;
solutionSet.setReportingEnabled(true);
internalState = InternalState::IDLE;
startupState = StartupState::IDLE;
break;
@ -833,6 +856,7 @@ void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonF
cfgs.mounting.init(paramJsonFile);
cfgs.limits.init(paramJsonFile);
cfgs.subscription.init(paramJsonFile);
cfgs.autoThreshold.init(paramJsonFile);
JCFG_DONE = true;
}
@ -856,13 +880,20 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
*foundLen = remainingSize;
return returnvalue::OK;
}
if (remainingSize < 3) {
sif::error << "StarTrackerHandler: Reply packet with length less than 3 is invalid"
if (remainingSize < 2) {
sif::error << "StarTrackerHandler: Reply packet with length " << remainingSize
<< " less than "
"2 is invalid"
<< std::endl;
return returnvalue::FAILED;
}
switch (startracker::getReplyFrameType(start)) {
case TMTC_COMM_ERROR: {
*foundLen = remainingSize;
triggerEvent(COM_ERROR_REPLY_RECEIVED, start[1]);
break;
}
case TMTC_ACTIONREPLY: {
*foundLen = remainingSize;
return scanForActionReply(startracker::getId(start), foundId);
@ -897,6 +928,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
ReturnValue_t result = returnvalue::OK;
switch (id) {
case (startracker::SET_TIME_FROM_SYS_TIME): {
result = handleActionReply(packet);
break;
}
case (startracker::REQ_TIME): {
result = handleTm(packet, timeSet, startracker::TimeSet::SIZE, "REQ_TIME");
break;
@ -956,7 +991,8 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
case (startracker::TRACKING):
case (startracker::VALIDATION):
case (startracker::IMAGE_PROCESSOR):
case (startracker::ALGO): {
case (startracker::ALGO):
case (startracker::AUTO_THRESHOLD): {
result = handleSetParamReply(packet);
break;
}
@ -1363,6 +1399,10 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(uint8_t replyId, DeviceComm
*foundId = startracker::UPLOAD_IMAGE;
break;
}
case (ARC_ACTION_REQ_SETTIME_ID): {
*foundId = startracker::SET_TIME_FROM_SYS_TIME;
break;
}
case (startracker::ID::CHECKSUM): {
*foundId = startracker::CHECKSUM;
break;
@ -1430,6 +1470,10 @@ ReturnValue_t StarTrackerHandler::scanForSetParameterReply(uint8_t replyId,
*foundId = startracker::DEBUG_CAMERA;
break;
}
case (startracker::ID::AUTO_THRESHOLD): {
*foundId = startracker::AUTO_THRESHOLD;
break;
}
case (startracker::ID::LOG_SUBSCRIPTION): {
*foundId = startracker::LOGSUBSCRIPTION;
break;
@ -1857,7 +1901,7 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) {
uint8_t status = startracker::getStatusField(rawFrame);
if (status != startracker::STATUS_OK) {
sif::warning << "StarTrackerHandler::handleSetParamReply: Failed to execute parameter set "
" command with parameter ID"
"command with parameter ID "
<< static_cast<unsigned int>(*(rawFrame + PARAMETER_ID_OFFSET)) << std::endl;
if (internalState != InternalState::IDLE) {
internalState = InternalState::IDLE;
@ -1865,21 +1909,25 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) {
return SET_PARAM_FAILED;
}
if (internalState != InternalState::IDLE) {
handleStartup(*(rawFrame + PARAMETER_ID_OFFSET));
handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET));
}
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleActionReply(const uint8_t* rawFrame) {
uint8_t status = startracker::getStatusField(rawFrame);
ReturnValue_t result = returnvalue::OK;
if (status != startracker::STATUS_OK) {
sif::warning << "StarTrackerHandler::handleActionReply: Failed to execute action "
<< "command with action ID "
<< static_cast<unsigned int>(*(rawFrame + ACTION_ID_OFFSET)) << " and status "
<< static_cast<unsigned int>(status) << std::endl;
return ACTION_FAILED;
result = ACTION_FAILED;
}
return returnvalue::OK;
if (internalState != InternalState::IDLE) {
handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET));
}
return result;
}
ReturnValue_t StarTrackerHandler::handleChecksumReply(const uint8_t* rawFrame) {
@ -1975,7 +2023,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
startupState = StartupState::BOOT_BOOTLOADER;
}
if (bootState == FwBootState::VERIFY_BOOT) {
bootState = FwBootState::LOGLEVEL;
bootState = FwBootState::SET_TIME;
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT);
internalState = InternalState::FAILED_BOOTLOADER_BOOT;
@ -2052,7 +2100,18 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(const uint8_t* rawFrame,
return result;
}
void StarTrackerHandler::handleStartup(uint8_t parameterId) {
void StarTrackerHandler::handleStartup(uint8_t tmType, uint8_t parameterId) {
switch (tmType) {
case (TMTC_ACTIONREPLY): {
case (ARC_ACTION_REQ_SETTIME_ID): {
bootState = FwBootState::LOGLEVEL;
return;
}
default: {
break;
}
}
}
switch (parameterId) {
case (startracker::ID::LOG_LEVEL): {
bootState = FwBootState::LIMITS;
@ -2062,7 +2121,7 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) {
bootState = FwBootState::TRACKING;
break;
}
case (startracker::ID::TRACKING): {
case (ARC_PARAM_TRACKING_ID): {
bootState = FwBootState::MOUNTING;
break;
}
@ -2103,6 +2162,10 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) {
break;
}
case (startracker::ID::DEBUG_CAMERA): {
bootState = FwBootState::AUTO_THRESHOLD;
break;
}
case (startracker::ID::AUTO_THRESHOLD): {
bootState = FwBootState::NONE;
internalState = InternalState::DONE;
break;

View File

@ -6,6 +6,7 @@
#include <mission/acs/str/ArcsecJsonParamBase.h>
#include <mission/acs/str/strHelpers.h>
#include <mission/acs/str/strJsonCommands.h>
#include <thirdparty/sagittactl/wire/common/genericstructs.h>
#include <thread>
@ -16,7 +17,7 @@
#include "fsfw/timemanager/Countdown.h"
extern "C" {
#include <wire/common/SLIP.h>
#include <wire/common/genericstructs.h>
}
/**
@ -143,6 +144,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
static const Event BOOTING_FIRMWARE_FAILED_EVENT = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode
static const Event BOOTING_BOOTLOADER_FAILED_EVENT = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Received COM error. P1: Communication Error ID (datasheet p32)
static constexpr Event COM_ERROR_REPLY_RECEIVED = MAKE_EVENT(3, severity::LOW);
static const uint8_t STATUS_OFFSET = 2;
static const uint8_t PARAMS_OFFSET = 2;
@ -226,6 +229,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
Mounting mounting;
Limits limits;
Subscription subscription;
AutoThreshold autoThreshold;
};
JsonConfigs jcfgs;
Countdown jcfgCountdown = Countdown(250);
@ -264,6 +268,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
BOOT_DELAY,
REQ_VERSION,
VERIFY_BOOT,
SET_TIME,
LOGLEVEL,
LIMITS,
TRACKING,
@ -278,7 +283,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
ALGO,
LOG_SUBSCRIPTION,
DEBUG_CAMERA,
AUTO_THRESHOLD,
WAIT_FOR_EXECUTION,
RETRY_CFG_CMD
};
FwBootState bootState = FwBootState::NONE;
@ -468,7 +475,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
/**
* @brief Handles the startup state machine
*/
void handleStartup(uint8_t parameterId);
void handleStartup(uint8_t tmType, uint8_t parameterId);
/**
* @brief Handles telemtry replies and fills the appropriate dataset

View File

@ -176,6 +176,13 @@ static const char DEBUG_CAMERA[] = "DebugCamera";
static const char TIMING[] = "timing";
static const char TEST[] = "test";
static constexpr char AUTO_THRESHOLD[] = "AutoThreshold";
static constexpr char AT_MODE[] = "mode";
static constexpr char AT_DESIRED_BLOB_COUNTS[] = "desiredBlobsCount";
static constexpr char AT_MIN_THRESHOLD[] = "minThreshold";
static constexpr char AT_MAX_THRESHOLD[] = "maxThreshold";
static constexpr char AT_THRESHOLD_KP[] = "thresholdKp";
} // namespace arcseckeys
#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ */

View File

@ -326,6 +326,8 @@ static const DeviceCommandId_t DEBUG_CAMERA = 83;
static const DeviceCommandId_t FIRMWARE_UPDATE = 84;
static const DeviceCommandId_t DISABLE_TIMESTAMP_GENERATION = 85;
static const DeviceCommandId_t ENABLE_TIMESTAMP_GENERATION = 86;
static constexpr DeviceCommandId_t SET_TIME_FROM_SYS_TIME = 87;
static constexpr DeviceCommandId_t AUTO_THRESHOLD = 88;
static const DeviceCommandId_t NONE = 0xFFFFFFFF;
static const uint32_t VERSION_SET_ID = REQ_VERSION;
@ -396,7 +398,6 @@ static const uint8_t ALGO = 16;
static const uint8_t REBOOT = 7;
static const uint8_t UPLOAD_IMAGE = 10;
static const uint8_t POWER = 11;
static const uint8_t SET_TIME = 14;
static const uint8_t SUBSCRIPTION = 18;
static const uint8_t SOLUTION = 24;
static const uint8_t TEMPERATURE = 27;
@ -410,6 +411,7 @@ static const uint8_t TAKE_IMAGE = 15;
static const uint8_t LOG_LEVEL = 3;
static const uint8_t LOG_SUBSCRIPTION = 19;
static const uint8_t DEBUG_CAMERA = 20;
static const uint8_t AUTO_THRESHOLD = 23;
} // namespace ID
namespace Program {
@ -441,6 +443,21 @@ static const uint32_t secret[16]{
REGION_12_SECRET, REGION_13_SECRET, REGION_14_SECRET, REGION_15_SECRET};
} // namespace region_secrets
namespace comError {
enum Id {
BAD_CRC = 1,
UNKNOWN_TM_ID = 2,
UNKNOWN_PARAM_ID = 3,
UNKNOWN_ACTION_REQ = 4,
INVALID_TM_SIZE = 5,
INVALID_PARAM_SIZE = 6,
INVALID_ACTION_REQ_SIZE = 7,
FRAME_TOO_SHORT = 8,
INVALID_FRAME_TYPE = 9,
UNKNOWN_ERROR = 10
};
}
enum class FlashSections : uint8_t {
BOOTLOADER_SECTION = 0,
MAIN_FIRMWARE_SECTION = 1,
@ -650,7 +667,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
// Ticks timestamp
lp_var_t<uint32_t> ticks = lp_var_t<uint32_t>(sid.objectId, PoolIds::TICKS_SOLUTION_SET, this);
/// Unix time stamp
lp_var_t<uint64_t> time = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
lp_var_t<uint64_t> timeUs = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
// Calibrated quaternion (takes into account the mounting quaternion), typically same as
// track q values
lp_var_t<float> caliQw = lp_var_t<float>(sid.objectId, PoolIds::CALI_QW, this);
@ -695,7 +712,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
void printSet() {
PoolReadGuard rg(this);
sif::info << "SolutionSet::printSet: Ticks: " << this->ticks << std::endl;
sif::info << "SolutionSet::printSet: Time: " << this->time << std::endl;
sif::info << "SolutionSet::printSet: Time: " << this->timeUs << std::endl;
sif::info << "SolutionSet::printSet: Calibrated quaternion Qw: " << this->caliQw << std::endl;
sif::info << "SolutionSet::printSet: Calibrated quaternion Qx: " << this->caliQx << std::endl;
sif::info << "SolutionSet::printSet: Calibrated quaternion Qy: " << this->caliQy << std::endl;

View File

@ -916,3 +916,45 @@ ReturnValue_t DebugCamera::createCommand(uint8_t* buffer) {
adduint32(param, buffer + offset);
return returnvalue::OK;
}
AutoThreshold::AutoThreshold() : ArcsecJsonParamBase(arcseckeys::AUTO_THRESHOLD) {}
size_t AutoThreshold::getSize() { return COMMAND_SIZE; }
ReturnValue_t AutoThreshold::createCommand(uint8_t* buffer) {
ReturnValue_t result = returnvalue::OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::AUTO_THRESHOLD);
offset = 2;
result = getParam(arcseckeys::AT_MODE, param);
if (result != returnvalue::OK) {
return result;
}
adduint8(param, buffer + offset);
offset += 1;
result = getParam(arcseckeys::AT_DESIRED_BLOB_COUNTS, param);
if (result != returnvalue::OK) {
return result;
}
adduint8(param, buffer + offset);
offset += 1;
result = getParam(arcseckeys::AT_MIN_THRESHOLD, param);
if (result != returnvalue::OK) {
return result;
}
adduint16(param, buffer + offset);
offset += 2;
result = getParam(arcseckeys::AT_MAX_THRESHOLD, param);
if (result != returnvalue::OK) {
return result;
}
adduint16(param, buffer + offset);
offset += 2;
result = getParam(arcseckeys::AT_THRESHOLD_KP, param);
if (result != returnvalue::OK) {
return result;
}
addfloat(param, buffer + offset);
return returnvalue::OK;
}

View File

@ -222,6 +222,22 @@ class LogSubscription : public ArcsecJsonParamBase {
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set log subscription parameters.
*
*/
class AutoThreshold : public ArcsecJsonParamBase {
public:
AutoThreshold();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 12;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set debug camera parameters
*

View File

@ -93,7 +93,8 @@ ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
sif::error << "CfdpHandler: Invalid PDU directive field " << pduDataField[0] << std::endl;
sif::error << "CfdpHandler: Invalid PDU directive field " << static_cast<int>(pduDataField[0])
<< std::endl;
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast<FileDirective>(pduDataField[0]);

View File

@ -246,7 +246,13 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
triggerEvent(CHANGING_MODE, mode, submode);
if (mode == HasModesIF::MODE_ON) {
if (this->submode != submode) {
uint32_t currentRate = ptmeConfig.getRate();
// Check whether the rate actually changes.
if ((this->submode != submode) and
(((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW) and
(currentRate != RATE_100KBPS))) or
((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH) and
(currentRate != RATE_500KBPS))))) {
initPtmeUpdateAfterXCycles();
updateContext.enableTransmitAfterPtmeUpdate = true;
updateContext.updateClockRate = true;

View File

@ -19,13 +19,8 @@ LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunne
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
readCommandQueue();
while (true) {
bool performWriteOp = true;
if (mode == MODE_OFF or ptmeLocked) {
performWriteOp = false;
}
// The funnel tasks are scheduled here directly as well.
ReturnValue_t result = channel.handleNextTm(performWriteOp);
ReturnValue_t result = channel.handleNextTm(!ptmeLocked);
if (result == DirectTmSinkIF::IS_BUSY) {
sif::error << "Lost live TM, PAPB busy" << std::endl;
}

View File

@ -42,13 +42,7 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
if (not someonesBusy) {
TaskFactory::delayTask(100);
} else if (vcBusyDuringDump) {
// TODO: Might not be necessary
sif::debug << "VC busy, delaying" << std::endl;
TaskFactory::delayTask(10);
} else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
TaskFactory::delayTask(2);
}
}
}

View File

@ -24,13 +24,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
if (not busy) {
TaskFactory::delayTask(100);
} else if (dumpContext.vcBusyDuringDump) {
sif::debug << "VC busy, delaying" << std::endl;
// TODO: Might not be necessary
TaskFactory::delayTask(10);
} else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
TaskFactory::delayTask(2);
}
}
}

View File

@ -773,11 +773,13 @@ void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
auto txStandbyHandler = [&]() {
txDataset.setReportingEnabled(false);
poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0);
poolManager.changeCollectionInterval(rxDataset.getSid(), 60.0);
transState = TransitionState::SET_TX_STANDBY;
internalState = InternalState::TX_TRANSITION;
};
auto txOnHandler = [&](TransitionState tgtTransitionState) {
txDataset.setReportingEnabled(true);
poolManager.changeCollectionInterval(rxDataset.getSid(), 5.0);
poolManager.changeCollectionInterval(txDataset.getSid(), 10.0);
poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0);
transState = tgtTransitionState;

View File

@ -45,13 +45,19 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
} else {
Command_t execCmd;
// Handle TC requests, for example deletion or retrieval requests.
// TODO: Not really clean here.. would be better if the executed command is returns as an
// enumeration.
result = store.handleCommandQueue(ipcStore, execCmd);
if (result == returnvalue::OK) {
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
if (result == PersistentTmStore::DUMP_DONE) {
dumpDoneHandler(store, dumpContext);
} else if (result == returnvalue::OK) {
cancelDumpCd.resetTimer();
tmSinkBusyCd.resetTimer();
dumpContext.reset();
}
}
if (execCmd != CommandMessageIF::CMD_NONE) {
tcRequestReceived = true;
}
}
@ -119,21 +125,13 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
DumpContext& dumpContext, bool& dumpPerformed) {
size_t dumpedLen = 0;
auto dumpDoneHandler = [&]() {
uint32_t startTime;
uint32_t endTime;
store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets,
dumpContext.dumpedBytes);
dumpContext.reset();
};
// Dump the next packet into the PTME.
dumpContext.ptmeBusyCounter = 0;
tmSinkBusyCd.resetTimer();
ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped);
if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) {
// This can happen if a file is corrupted and the next file swap completes the dump.
dumpDoneHandler();
dumpDoneHandler(store, dumpContext);
return returnvalue::OK;
} else if (result != returnvalue::OK) {
sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl;
@ -157,7 +155,7 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
}
}
if (result == PersistentTmStore::DUMP_DONE) {
dumpDoneHandler();
dumpDoneHandler(store, dumpContext);
}
return returnvalue::OK;
}
@ -198,6 +196,14 @@ ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& pare
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
}
void TmStoreTaskBase::dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext) {
uint32_t startTime;
uint32_t endTime;
store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, dumpContext.dumpedBytes);
dumpContext.reset();
}
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
void TmStoreTaskBase::readCommandQueue(void) {

View File

@ -96,6 +96,8 @@ class TmStoreTaskBase : public SystemObject,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
void dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext);
void announceMode(bool recursive) override;
object_id_t getObjectId() const override;
const HasHealthIF* getOptHealthIF() const override;

View File

@ -7,6 +7,7 @@
AcsController::AcsController(object_id_t objectId, bool enableHkSets)
: ExtendedControllerBase(objectId),
enableHkSets(enableHkSets),
fusedRotationEstimation(&acsParameters),
guidance(&acsParameters),
safeCtrl(&acsParameters),
ptgCtrl(&acsParameters),
@ -20,7 +21,8 @@ AcsController::AcsController(object_id_t objectId, bool enableHkSets)
gpsDataProcessed(this),
mekfData(this),
ctrlValData(this),
actuatorCmdData(this) {}
actuatorCmdData(this),
fusedRotRateData(this) {}
ReturnValue_t AcsController::initialize() {
ReturnValue_t result = parameterHelper.initialize();
@ -146,6 +148,8 @@ void AcsController::performSafe() {
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
&gyrDataProcessed, &fusedRotRateData);
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, &mekfData, &acsParameters);
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
@ -172,25 +176,42 @@ void AcsController::performSafe() {
acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy(
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
fusedRotRateData.rotRateOrthogonal.isValid(), fusedRotRateData.rotRateTotal.isValid(),
acsParameters.safeModeControllerParameters.useMekf,
acsParameters.safeModeControllerParameters.useGyr,
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
switch (safeCtrlStrat) {
case (acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF):
case (acs::SafeModeStrategy::SAFECTRL_MEKF):
safeCtrl.safeMekf(mgmDataProcessed.mgmVecTot.value, mekfData.satRotRateMekf.value,
susDataProcessed.sunIjkModel.value, mekfData.quatMekf.value, sunTargetDir,
magMomMtq, errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF):
safeCtrl.safeNonMekf(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
case (acs::SafeModeStrategy::SAFECTRL_GYR):
safeCtrl.safeGyr(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING):
safeCtrl.safeRateDamping(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
sunTargetDir, magMomMtq, errAng);
case (acs::SafeModeStrategy::SAFECTRL_SUSMGM):
safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateParallel.value,
fusedRotRateData.rotRateOrthogonal.value,
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR):
safeCtrl.safeRateDampingGyr(mgmDataProcessed.mgmVecTot.value,
gyrDataProcessed.gyrVecTot.value, sunTargetDir, magMomMtq,
errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM):
safeCtrl.safeRateDampingSusMgm(mgmDataProcessed.mgmVecTot.value,
fusedRotRateData.rotRateTotal.value, sunTargetDir, magMomMtq,
errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
@ -214,12 +235,20 @@ void AcsController::performSafe() {
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
// detumble check and switch
if (mekfData.satRotRateMekf.isValid() && acsParameters.safeModeControllerParameters.useMekf &&
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
if (acsParameters.safeModeControllerParameters.useMekf) {
if (mekfData.satRotRateMekf.isValid() and
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
}
} else if (acsParameters.safeModeControllerParameters.useGyr) {
if (gyrDataProcessed.gyrVecTot.isValid() and
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
}
} else if (fusedRotRateData.rotRateTotal.isValid() and
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
} else if (detumbleCounter > 0) {
@ -244,6 +273,8 @@ void AcsController::performDetumble() {
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
&gyrDataProcessed, &fusedRotRateData);
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, &mekfData, &acsParameters);
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
@ -289,17 +320,26 @@ void AcsController::performDetumble() {
actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment,
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
if (mekfData.satRotRateMekf.isValid() &&
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
detumbleCounter++;
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
if (acsParameters.safeModeControllerParameters.useMekf) {
if (mekfData.satRotRateMekf.isValid() and
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
detumbleCounter++;
}
} else if (acsParameters.safeModeControllerParameters.useGyr) {
if (gyrDataProcessed.gyrVecTot.isValid() and
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
detumbleCounter++;
}
} else if (fusedRotRateData.rotRateTotal.isValid() and
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
detumbleCounter++;
} else if (detumbleCounter > 0) {
detumbleCounter -= 1;
}
if (detumbleCounter > acsParameters.detumbleParameter.detumblecounter) {
detumbleCounter = 0;
// Triggers safe mode transition in subsystem
@ -307,7 +347,7 @@ void AcsController::performDetumble() {
startTransition(mode, acs::SafeSubmode::DEFAULT);
}
disableCtrlValData();
updateCtrlValData(safeCtrlStrat);
updateActuatorCmdData(cmdDipoleMtqs);
commandActuators(cmdDipoleMtqs[0], cmdDipoleMtqs[1], cmdDipoleMtqs[2],
acsParameters.magnetorquerParameter.torqueDuration);
@ -578,6 +618,23 @@ void AcsController::updateActuatorCmdData(const double *rwTargetTorque,
}
}
void AcsController::updateCtrlValData(uint8_t safeModeStrat) {
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
ctrlValData.tgtQuat.setValid(false);
std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
ctrlValData.errQuat.setValid(false);
ctrlValData.errAng.value = 0;
ctrlValData.errAng.setValid(false);
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
ctrlValData.tgtRotRate.setValid(false);
ctrlValData.safeStrat.value = safeModeStrat;
ctrlValData.safeStrat.setValid(true);
ctrlValData.setValidity(true, false);
}
}
void AcsController::updateCtrlValData(double errAng, uint8_t safeModeStrat) {
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
@ -608,17 +665,6 @@ void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQu
}
}
void AcsController::disableCtrlValData() {
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
ctrlValData.errAng.value = 0;
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
ctrlValData.setValidity(false, true);
}
}
ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
// MGM Raw
@ -707,6 +753,11 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_SPEED, &rwTargetSpeed);
localDataPoolMap.emplace(acsctrl::PoolIds::MTQ_TARGET_DIPOLE, &mtqTargetDipole);
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 10.0});
// Fused Rot Rate
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_ORTHOGONAL, &rotRateOrthogonal);
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_PARALLEL, &rotRateParallel);
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL, &rotRateTotal);
poolManager.subscribeForRegularPeriodicPacket({fusedRotRateData.getSid(), enableHkSets, 10.0});
return returnvalue::OK;
}
@ -732,6 +783,8 @@ LocalPoolDataSetBase *AcsController::getDataSetHandle(sid_t sid) {
return &ctrlValData;
case acsctrl::ACTUATOR_CMD_DATA:
return &actuatorCmdData;
case acsctrl::FUSED_ROTATION_RATE_DATA:
return &fusedRotRateData;
default:
return nullptr;
}

View File

@ -13,6 +13,7 @@
#include <mission/acs/rwHelpers.h>
#include <mission/acs/susMax1227Helpers.h>
#include <mission/controller/acs/ActuatorCmd.h>
#include <mission/controller/acs/FusedRotationEstimation.h>
#include <mission/controller/acs/Guidance.h>
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
#include <mission/controller/acs/Navigation.h>
@ -49,6 +50,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
AcsParameters acsParameters;
SensorProcessing sensorProcessing;
FusedRotationEstimation fusedRotationEstimation;
Navigation navigation;
ActuatorCmd actuatorCmd;
Guidance guidance;
@ -115,10 +117,10 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
void updateActuatorCmdData(const int16_t* mtqTargetDipole);
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
const int16_t* mtqTargetDipole);
void updateCtrlValData(uint8_t safeModeStrat);
void updateCtrlValData(double errAng, uint8_t safeModeStrat);
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
const double* tgtRotRate);
void disableCtrlValData();
/* ACS Sensor Values */
ACS::SensorValues sensorValues;
@ -226,6 +228,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
PoolEntry<int32_t> rwTargetSpeed = PoolEntry<int32_t>(4);
PoolEntry<int16_t> mtqTargetDipole = PoolEntry<int16_t>(3);
// Fused Rot Rate
acsctrl::FusedRotRateData fusedRotRateData;
PoolEntry<double> rotRateOrthogonal = PoolEntry<double>(3);
PoolEntry<double> rotRateParallel = PoolEntry<double>(3);
PoolEntry<double> rotRateTotal = PoolEntry<double>(3);
// Initial delay to make sure all pool variables have been initialized their owners
Countdown initialCountdown = Countdown(INIT_DELAY);
};

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#ifndef MISSION_CONTROLLER_THERMALCONTROLLER_H_
#define MISSION_CONTROLLER_THERMALCONTROLLER_H_
#include <bsp_q7s/core/CoreDefinitions.h>
#include <bsp_q7s/core/defs.h>
#include <fsfw/controller/ExtendedControllerBase.h>
#include <fsfw/devicehandlers/DeviceHandlerThermalSet.h>
#include <fsfw/timemanager/Countdown.h>
@ -24,74 +24,7 @@
#include <atomic>
#include <list>
/**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
* is exceeded.
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
* limit is exceeded to avoid reaching NOP limit
*/
struct TempLimits {
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
float nopUpperLimit)
: opLowerLimit(opLowerLimit),
opUpperLimit(opUpperLimit),
cutOffLimit(cutOffLimit),
nopLowerLimit(nopLowerLimit),
nopUpperLimit(nopUpperLimit) {}
float opLowerLimit;
float opUpperLimit;
float cutOffLimit;
float nopLowerLimit;
float nopUpperLimit;
};
struct ThermalState {
uint8_t errorCounter;
// Is heating on for that thermal module?
bool heating = false;
heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
// when a switch command is sent, with no guarantess that the heater actually went on.
uint32_t heaterStartTime = 0;
uint32_t heaterEndTime = 0;
};
struct HeaterState {
bool switchTransition;
HeaterHandler::SwitchState target;
uint8_t heaterSwitchControlCycles;
};
using HeaterSwitchStates = std::array<HeaterHandler::SwitchState, heater::NUMBER_OF_SWITCHES>;
enum ThermalComponents : uint8_t {
NONE = 0,
ACS_BOARD = 1,
MGT = 2,
RW = 3,
STR = 4,
IF_BOARD = 5,
TCS_BOARD = 6,
OBC = 7,
OBCIF_BOARD = 8,
SBAND_TRANSCEIVER = 9,
PCDUP60_BOARD = 10,
PCDUACU = 11,
PCDUPDU = 12,
PLPCDU_BOARD = 13,
PLOCMISSION_BOARD = 14,
PLOCPROCESSING_BOARD = 15,
DAC = 16,
CAMERA = 17,
DRO = 18,
X8 = 19,
HPA = 20,
TX = 21,
MPA = 22,
SCEX_BOARD = 23,
NUM_ENTRIES
};
#include <optional>
class ThermalController : public ExtendedControllerBase {
public:
@ -102,8 +35,28 @@ class ThermalController : public ExtendedControllerBase {
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160;
// 1 hour
static constexpr uint32_t DEFAULT_MAX_HEATER_ON_DURATION_MS = 60 * 60 * 1000;
static constexpr uint32_t MAX_HEATER_ON_DURATIONS_MS[8] = {// PLOC PROC board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// PCDU PDU
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// ACS Board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// OBC Board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// Camera
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// STR
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// DRO
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// S-Band
DEFAULT_MAX_HEATER_ON_DURATION_MS};
ThermalController(object_id_t objectId, HeaterHandler& heater,
const std::atomic_bool& tcsBoardShortUnavailable);
const std::atomic_bool& tcsBoardShortUnavailable, bool pollPcdu1Tmp);
virtual ~ThermalController();
ReturnValue_t initialize() override;
@ -111,16 +64,16 @@ class ThermalController : public ExtendedControllerBase {
struct HeaterContext {
public:
HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr,
const TempLimits& tempLimit)
const tcsCtrl::TempLimits& tempLimit)
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
bool doHeaterHandling = true;
heater::Switch switchNr;
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
heater::SwitchState switchState = heater::SwitchState::OFF;
heater::Switch redSwitchNr;
const TempLimits& tempLimit;
const tcsCtrl::TempLimits& tempLimit;
};
void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates);
void performThermalModuleCtrl(const tcsCtrl::HeaterSwitchStates& heaterSwitchStates);
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -142,12 +95,12 @@ class ThermalController : public ExtendedControllerBase {
HeaterHandler& heaterHandler;
bool pollPcdu1Tmp;
tcsCtrl::SensorTemperatures sensorTemperatures;
tcsCtrl::SusTemperatures susTemperatures;
tcsCtrl::DeviceTemperatures deviceTemperatures;
tcsCtrl::HeaterInfo heaterInfo;
lp_vec_t<int16_t, 9> currentVecPdu2 =
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
tcsCtrl::TcsCtrlInfo tcsCtrlInfo;
DeviceHandlerThermalSet imtqThermalSet;
@ -173,7 +126,7 @@ class ThermalController : public ExtendedControllerBase {
TMP1075::Tmp1075Dataset tmp1075SetTcs1;
TMP1075::Tmp1075Dataset tmp1075SetPlPcdu0;
// damaged
// TMP1075::Tmp1075Dataset tmp1075SetPlPcdu1;
TMP1075::Tmp1075Dataset* tmp1075SetPlPcdu1;
TMP1075::Tmp1075Dataset tmp1075SetIfBoard;
// SUS
@ -227,57 +180,67 @@ class ThermalController : public ExtendedControllerBase {
lp_var_t<float> tempMgm2 =
lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS);
lp_var_t<float> tempAdcPayloadPcdu = lp_var_t<float>(objects::PLPCDU_HANDLER, plpcdu::TEMP);
lp_vec_t<int16_t, 9> currentVecPdu2 =
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
// TempLimits
TempLimits acsBoardLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits mgtLimits = TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
TempLimits rwLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits strLimits = TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
TempLimits ifBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
TempLimits tcsBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
TempLimits obcLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits obcIfBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
TempLimits sBandTransceiverLimits = TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
TempLimits pcduP60BoardLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits pcduAcuLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits pcduPduLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits plPcduBoardLimits = TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
TempLimits plocMissionBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
TempLimits plocProcessingBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
TempLimits dacLimits = TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
TempLimits cameraLimits = TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
TempLimits droLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits x8Limits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits hpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits txLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits mpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
tcsCtrl::TempLimits acsBoardLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits mgtLimits = tcsCtrl::TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
tcsCtrl::TempLimits rwLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits strLimits = tcsCtrl::TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
tcsCtrl::TempLimits ifBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
tcsCtrl::TempLimits tcsBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
tcsCtrl::TempLimits obcLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits obcIfBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
tcsCtrl::TempLimits sBandTransceiverLimits = tcsCtrl::TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
tcsCtrl::TempLimits pcduP60BoardLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits pcduAcuLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits pcduPduLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits plPcduBoardLimits = tcsCtrl::TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
tcsCtrl::TempLimits plocMissionBoardLimits = tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
tcsCtrl::TempLimits plocProcessingBoardLimits =
tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
tcsCtrl::TempLimits dacLimits = tcsCtrl::TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
tcsCtrl::TempLimits cameraLimits = tcsCtrl::TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
tcsCtrl::TempLimits droLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits x8Limits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits hpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits txLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits mpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits scexBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
struct CtrlContext {
double sensorTemp = INVALID_TEMPERATURE;
uint8_t currentSensorIndex = 0;
tcsCtrl::ThermalComponents thermalComponent = tcsCtrl::NONE;
bool redSwitchNrInUse = false;
bool componentAboveCutOffLimit = false;
bool componentAboveUpperLimit = false;
Event overHeatEventToTrigger;
} ctrlCtx;
double sensorTemp = INVALID_TEMPERATURE;
ThermalComponents thermalComponent = NONE;
bool redSwitchNrInUse = false;
MessageQueueId_t camId = MessageQueueIF::NO_QUEUE;
bool componentAboveCutOffLimit = false;
bool componentAboveUpperLimit = false;
Event overHeatEventToTrigger;
bool eBandTooHotFlag = false;
bool camTooHotOneShotFlag = false;
bool scexTooHotFlag = false;
bool plocTooHotFlag = false;
bool pcduSystemTooHotFlag = false;
bool syrlinksTooHotFlag = false;
bool obcTooHotFlag = false;
bool mgtTooHotFlag = false;
bool strTooHotFlag = false;
bool rwTooHotFlag = false;
struct TooHotFlags {
bool eBandTooHotFlag = false;
bool camTooHotOneShotFlag = false;
bool scexTooHotFlag = false;
bool plocTooHotFlag = false;
bool pcduSystemTooHotFlag = false;
bool syrlinksTooHotFlag = false;
bool obcTooHotFlag = false;
bool mgtTooHotFlag = false;
bool strTooHotFlag = false;
bool rwTooHotFlag = false;
} tooHotFlags;
bool transitionWhenHeatersOff = false;
uint32_t transitionWhenHeatersOffCycles = 0;
Mode_t targetMode = MODE_OFF;
Submode_t targetSubmode = SUBMODE_NONE;
uint32_t cycles = 0;
std::array<ThermalState, ThermalComponents::NUM_ENTRIES> thermalStates{};
std::array<HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
std::array<tcsCtrl::ThermalState, tcsCtrl::NUM_THERMAL_COMPONENTS> thermalStates{};
std::array<tcsCtrl::HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
// Initial delay to make sure all pool variables have been initialized their owners.
// Also, wait for system initialization to complete.
@ -298,6 +261,12 @@ class ThermalController : public ExtendedControllerBase {
PoolEntry<uint8_t> heaterSwitchStates = PoolEntry<uint8_t>(heater::NUMBER_OF_SWITCHES);
PoolEntry<int16_t> heaterCurrent = PoolEntry<int16_t>();
PoolEntry<uint8_t> tcsCtrlHeaterOn = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint8_t> tcsCtrlSensorIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint8_t> tcsCtrlHeaterIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint32_t> tcsCtrlStartTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint32_t> tcsCtrlEndTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
static constexpr dur_millis_t MUTEX_TIMEOUT = 50;
void startTransition(Mode_t mode, Submode_t submode) override;
@ -319,8 +288,8 @@ class ThermalController : public ExtendedControllerBase {
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
void heaterSwitchHelperAllOff();
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state,
unsigned componentIdx);
void heaterSwitchHelper(heater::Switch switchNr, heater::SwitchState state,
std::optional<unsigned> componentIdx);
void ctrlAcsBoard();
void ctrlMgt();
@ -329,7 +298,6 @@ class ThermalController : public ExtendedControllerBase {
void ctrlIfBoard();
void ctrlTcsBoard();
void ctrlObc();
void ctrlObcIfBoard();
void ctrlSBandTransceiver();
void ctrlPcduP60Board();
void ctrlPcduAcu();
@ -345,7 +313,22 @@ class ThermalController : public ExtendedControllerBase {
void ctrlTx();
void ctrlMpa();
void ctrlScexBoard();
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
/**
* The transition of heaters might take some time. As long as a transition is
* going on, the TCS controller works in a reduced form. This function takes care
* of tracking transition and capturing their completion.
* @param currentHeaterStates
*/
void heaterTransitionControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
/**
* Control tasks to prevent heaters being on for prolonged periods. Ideally, this
* should never happen, but this task prevents bugs from causing heaters to stay on
* for a long time, which draws a lot of power.
* @param currentHeaterStates
*/
void heaterMaxDurationControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
void crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(heater::Switch switchIdx);
void setMode(Mode_t mode, Submode_t submode);
uint32_t tempFloatToU32() const;
bool tooHotHandler(object_id_t object, bool& oneShotFlag);

View File

@ -26,6 +26,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
case 0x1:
parameterWrapper->set(onBoardParams.mekfViolationTimer);
break;
case 0x2:
parameterWrapper->set(onBoardParams.fusedRateSafeDuringEclipse);
break;
default:
return INVALID_IDENTIFIER_ID;
}
@ -105,6 +108,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
parameterWrapper->setVector(mgmHandlingParameters.mgm4variance);
break;
case 0x12:
parameterWrapper->set(mgmHandlingParameters.mgmVectorFilterWeight);
break;
case 0x13:
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
break;
default:
@ -221,6 +227,15 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
case 0x23:
parameterWrapper->setMatrix(susHandlingParameters.sus11coeffBeta);
break;
case 0x24:
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
break;
case 0x25:
parameterWrapper->set(susHandlingParameters.susVectorFilterWeight);
break;
case 0x26:
parameterWrapper->set(susHandlingParameters.susRateFilterWeight);
break;
default:
return INVALID_IDENTIFIER_ID;
}
@ -336,26 +351,41 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
parameterWrapper->set(safeModeControllerParameters.k_parallelMekf);
break;
case 0x3:
parameterWrapper->set(safeModeControllerParameters.k_orthoNonMekf);
parameterWrapper->set(safeModeControllerParameters.k_orthoGyr);
break;
case 0x4:
parameterWrapper->set(safeModeControllerParameters.k_alignNonMekf);
parameterWrapper->set(safeModeControllerParameters.k_alignGyr);
break;
case 0x5:
parameterWrapper->set(safeModeControllerParameters.k_parallelNonMekf);
parameterWrapper->set(safeModeControllerParameters.k_parallelGyr);
break;
case 0x6:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
parameterWrapper->set(safeModeControllerParameters.k_orthoSusMgm);
break;
case 0x7:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
parameterWrapper->set(safeModeControllerParameters.k_alignSusMgm);
break;
case 0x8:
parameterWrapper->set(safeModeControllerParameters.useMekf);
parameterWrapper->set(safeModeControllerParameters.k_parallelSusMgm);
break;
case 0x9:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
break;
case 0xA:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
break;
case 0xB:
parameterWrapper->set(safeModeControllerParameters.useMekf);
break;
case 0xC:
parameterWrapper->set(safeModeControllerParameters.useGyr);
break;
case 0xD:
parameterWrapper->set(safeModeControllerParameters.dampingDuringEclipse);
break;
case 0xE:
parameterWrapper->set(safeModeControllerParameters.sineLimitSunRotRate);
break;
default:
return INVALID_IDENTIFIER_ID;
}

View File

@ -19,6 +19,7 @@ class AcsParameters : public HasParametersIF {
struct OnBoardParams {
double sampleTime = 0.4; // [s]
uint16_t mekfViolationTimer = 750;
uint8_t fusedRateSafeDuringEclipse = true;
} onBoardParams;
struct InertiaEIVE {
@ -77,7 +78,8 @@ class AcsParameters : public HasParametersIF {
float mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
float mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
float mgmDerivativeFilterWeight = 0.5;
float mgmVectorFilterWeight = 0.85;
float mgmDerivativeFilterWeight = 0.85;
} mgmHandlingParameters;
struct SusHandlingParameters {
@ -766,6 +768,9 @@ class AcsParameters : public HasParametersIF {
{116.975421945286, -5.53022680362263, -5.61081660666997, 0.109754904982136,
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
-0.000889232196185857, -0.00168429567131815}};
float susBrightnessThreshold = 0.7;
float susVectorFilterWeight = .85;
float susRateFilterWeight = .85;
} susHandlingParameters;
struct GyrHandlingParameters {
@ -824,15 +829,22 @@ class AcsParameters : public HasParametersIF {
double k_alignMekf = 4.0e-5;
double k_parallelMekf = 3.75e-4;
double k_orthoNonMekf = 4.4e-3;
double k_alignNonMekf = 4.0e-5;
double k_parallelNonMekf = 3.75e-4;
double k_orthoGyr = 4.4e-3;
double k_alignGyr = 4.0e-5;
double k_parallelGyr = 3.75e-4;
double k_orthoSusMgm = 1.1e-2;
double k_alignSusMgm = 2.0e-5;
double k_parallelSusMgm = 4.4e-4;
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
double sunTargetDir[3] = {0, 0, 1};
uint8_t useMekf = false;
uint8_t useGyr = true;
uint8_t dampingDuringEclipse = true;
float sineLimitSunRotRate = 0.24;
} safeModeControllerParameters;
struct PointingLawParameters {

View File

@ -2,6 +2,7 @@ target_sources(
${LIB_EIVE_MISSION}
PRIVATE AcsParameters.cpp
ActuatorCmd.cpp
FusedRotationEstimation.cpp
Guidance.cpp
Igrf13Model.cpp
MultiplicativeKalmanFilter.cpp

View File

@ -0,0 +1,116 @@
#include "FusedRotationEstimation.h"
FusedRotationEstimation::FusedRotationEstimation(AcsParameters *acsParameters_) {
acsParameters = acsParameters_;
}
void FusedRotationEstimation::estimateFusedRotationRateSafe(
acsctrl::SusDataProcessed *susDataProcessed, acsctrl::MgmDataProcessed *mgmDataProcessed,
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
if ((not mgmDataProcessed->mgmVecTot.isValid() and not susDataProcessed->susVecTot.isValid() and
not fusedRotRateData->rotRateTotal.isValid()) or
(not susDataProcessed->susVecTotDerivative.isValid() and
not mgmDataProcessed->mgmVecTotDerivative.isValid())) {
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->setValidity(false, true);
}
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
return;
}
if (not susDataProcessed->susVecTot.isValid()) {
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
return;
}
// calculate rotation around the sun
double magSunCross[3] = {0, 0, 0};
VectorOperations<double>::cross(mgmDataProcessed->mgmVecTot.value,
susDataProcessed->susVecTot.value, magSunCross);
double magSunCrossNorm = VectorOperations<double>::norm(magSunCross, 3);
double magNorm = VectorOperations<double>::norm(mgmDataProcessed->mgmVecTot.value, 3);
double fusedRotRateParallel[3] = {0, 0, 0};
if (magSunCrossNorm >
(acsParameters->safeModeControllerParameters.sineLimitSunRotRate * magNorm)) {
double omegaParallel =
VectorOperations<double>::dot(mgmDataProcessed->mgmVecTotDerivative.value, magSunCross) *
pow(magSunCrossNorm, -2);
VectorOperations<double>::mulScalar(susDataProcessed->susVecTot.value, omegaParallel,
fusedRotRateParallel, 3);
} else {
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
return;
}
// calculate rotation orthogonal to the sun
double fusedRotRateOrthogonal[3] = {0, 0, 0};
VectorOperations<double>::cross(susDataProcessed->susVecTotDerivative.value,
susDataProcessed->susVecTot.value, fusedRotRateOrthogonal);
VectorOperations<double>::mulScalar(
fusedRotRateOrthogonal,
pow(VectorOperations<double>::norm(susDataProcessed->susVecTot.value, 3), -2),
fusedRotRateOrthogonal, 3);
// calculate total rotation rate
double fusedRotRateTotal[3] = {0, 0, 0};
VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal);
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal,
3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateParallel.value, fusedRotRateParallel, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
fusedRotRateData->setValidity(true, true);
}
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
}
void FusedRotationEstimation::estimateFusedRotationRateEclipse(
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
if (not acsParameters->onBoardParams.fusedRateSafeDuringEclipse or
not gyrDataProcessed->gyrVecTot.isValid() or
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->setValidity(false, true);
}
return;
}
double angAccelB[3] = {0, 0, 0};
VectorOperations<double>::subtract(gyrDataProcessed->gyrVecTot.value, rotRateOldB, angAccelB, 3);
double fusedRotRateTotal[3] = {0, 0, 0};
VectorOperations<double>::add(fusedRotRateData->rotRateTotal.value, angAccelB, fusedRotRateTotal,
3);
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->rotRateOrthogonal.setValid(false);
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->rotRateParallel.setValid(false);
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
fusedRotRateData->rotRateTotal.setValid(true);
}
}

View File

@ -0,0 +1,29 @@
#ifndef MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
#define MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include <mission/controller/acs/AcsParameters.h>
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
class FusedRotationEstimation {
public:
FusedRotationEstimation(AcsParameters *acsParameters_);
void estimateFusedRotationRateSafe(acsctrl::SusDataProcessed *susDataProcessed,
acsctrl::MgmDataProcessed *mgmDataProcessed,
acsctrl::GyrDataProcessed *gyrDataProcessed,
acsctrl::FusedRotRateData *fusedRotRateData);
protected:
private:
static constexpr double ZERO_VEC[3] = {0, 0, 0};
AcsParameters *acsParameters;
double rotRateOldB[3] = {0, 0, 0};
void estimateFusedRotationRateEclipse(acsctrl::GyrDataProcessed *gyrDataProcessed,
acsctrl::FusedRotRateData *fusedRotRateData);
};
#endif /* MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_ */

View File

@ -30,10 +30,7 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
// ------------------------------------------------
double magIgrfModel[3] = {0.0, 0.0, 0.0};
if (gpsValid) {
// Should be existing class object which will be called and modified here.
Igrf13Model igrf13;
// So the line above should not be done here. Update: Can be done here as long updated coffs
// stored in acsParameters ?
igrf13.schmidtNormalization();
igrf13.updateCoeffGH(timeOfMgmMeasurement);
// maybe put a condition here, to only update after a full day, this
@ -45,14 +42,13 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
{
PoolReadGuard pg(mgmDataProcessed);
if (pg.getReadResult() == returnvalue::OK) {
float zeroVec[3] = {0.0, 0.0, 0.0};
std::memcpy(mgmDataProcessed->mgm0vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm1vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm2vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm3vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm4vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgmVecTot.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgmVecTotDerivative.value, zeroVec, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm0vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm1vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm2vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm3vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgm4vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(mgmDataProcessed->mgmVecTot.value, ZERO_VEC_D, 3 * sizeof(double));
std::memcpy(mgmDataProcessed->mgmVecTotDerivative.value, ZERO_VEC_D, 3 * sizeof(double));
mgmDataProcessed->setValidity(false, true);
std::memcpy(mgmDataProcessed->magIgrfModel.value, magIgrfModel, 3 * sizeof(double));
mgmDataProcessed->magIgrfModel.setValid(gpsValid);
@ -136,6 +132,10 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
for (uint8_t i = 0; i < 3; i++) {
mgmVecTot[i] = sensorFusionNumerator[i] / sensorFusionDenominator[i];
}
if (VectorOperations<double>::norm(mgmVecTot, 3) != 0 and mgmDataProcessed->mgmVecTot.isValid()) {
lowPassFilter(mgmVecTot, mgmDataProcessed->mgmVecTot.value,
mgmParameters->mgmVectorFilterWeight);
}
//-----------------------Mgm Rate Computation ---------------------------------------------------
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
@ -210,63 +210,68 @@ void SensorProcessing::processSus(
sunIjkModel[0] = cos(eclipticLongitude);
sunIjkModel[1] = sin(eclipticLongitude) * cos(epsilon);
sunIjkModel[2] = sin(eclipticLongitude) * sin(epsilon);
uint64_t susBrightness[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (sus0valid) {
sus0valid = susConverter.checkSunSensorData(sus0Value);
susBrightness[0] = susConverter.checkSunSensorData(sus0Value);
}
if (sus1valid) {
sus1valid = susConverter.checkSunSensorData(sus1Value);
susBrightness[1] = susConverter.checkSunSensorData(sus1Value);
}
if (sus2valid) {
sus2valid = susConverter.checkSunSensorData(sus2Value);
susBrightness[2] = susConverter.checkSunSensorData(sus2Value);
}
if (sus3valid) {
sus3valid = susConverter.checkSunSensorData(sus3Value);
susBrightness[3] = susConverter.checkSunSensorData(sus3Value);
}
if (sus4valid) {
sus4valid = susConverter.checkSunSensorData(sus4Value);
susBrightness[4] = susConverter.checkSunSensorData(sus4Value);
}
if (sus5valid) {
sus5valid = susConverter.checkSunSensorData(sus5Value);
susBrightness[5] = susConverter.checkSunSensorData(sus5Value);
}
if (sus6valid) {
sus6valid = susConverter.checkSunSensorData(sus6Value);
susBrightness[6] = susConverter.checkSunSensorData(sus6Value);
}
if (sus7valid) {
sus7valid = susConverter.checkSunSensorData(sus7Value);
susBrightness[7] = susConverter.checkSunSensorData(sus7Value);
}
if (sus8valid) {
sus8valid = susConverter.checkSunSensorData(sus8Value);
susBrightness[8] = susConverter.checkSunSensorData(sus8Value);
}
if (sus9valid) {
sus9valid = susConverter.checkSunSensorData(sus9Value);
susBrightness[9] = susConverter.checkSunSensorData(sus9Value);
}
if (sus10valid) {
sus10valid = susConverter.checkSunSensorData(sus10Value);
susBrightness[10] = susConverter.checkSunSensorData(sus10Value);
}
if (sus11valid) {
sus11valid = susConverter.checkSunSensorData(sus11Value);
susBrightness[11] = susConverter.checkSunSensorData(sus11Value);
}
if (!sus0valid && !sus1valid && !sus2valid && !sus3valid && !sus4valid && !sus5valid &&
!sus6valid && !sus7valid && !sus8valid && !sus9valid && !sus10valid && !sus11valid) {
bool susValid[12] = {sus0valid, sus1valid, sus2valid, sus3valid, sus4valid, sus5valid,
sus6valid, sus7valid, sus8valid, sus9valid, sus10valid, sus11valid};
bool allInvalid =
susConverter.checkValidity(susValid, susBrightness, susParameters->susBrightnessThreshold);
if (allInvalid) {
{
PoolReadGuard pg(susDataProcessed);
if (pg.getReadResult() == returnvalue::OK) {
float zeroVec[3] = {0.0, 0.0, 0.0};
std::memcpy(susDataProcessed->sus0vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus1vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus2vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus3vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus4vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus5vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus6vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus7vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus8vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus9vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus10vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus11vec.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->susVecTot.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->susVecTotDerivative.value, zeroVec, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus0vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus1vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus2vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus3vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus4vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus5vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus6vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus7vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus8vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus9vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus10vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus11vec.value, ZERO_VEC_F, 3 * sizeof(float));
std::memcpy(susDataProcessed->susVecTot.value, ZERO_VEC_D, 3 * sizeof(double));
std::memcpy(susDataProcessed->susVecTotDerivative.value, ZERO_VEC_D, 3 * sizeof(double));
susDataProcessed->setValidity(false, true);
std::memcpy(susDataProcessed->sunIjkModel.value, sunIjkModel, 3 * sizeof(double));
susDataProcessed->sunIjkModel.setValid(true);
@ -274,122 +279,87 @@ void SensorProcessing::processSus(
}
return;
}
// WARNING: NOT TRANSFORMED IN BODY FRAME YET
// Transformation into Geomtry Frame
float sus0VecBody[3] = {0, 0, 0}, sus1VecBody[3] = {0, 0, 0}, sus2VecBody[3] = {0, 0, 0},
sus3VecBody[3] = {0, 0, 0}, sus4VecBody[3] = {0, 0, 0}, sus5VecBody[3] = {0, 0, 0},
sus6VecBody[3] = {0, 0, 0}, sus7VecBody[3] = {0, 0, 0}, sus8VecBody[3] = {0, 0, 0},
sus9VecBody[3] = {0, 0, 0}, sus10VecBody[3] = {0, 0, 0}, sus11VecBody[3] = {0, 0, 0};
if (sus0valid) {
MatrixOperations<float>::multiply(
susParameters->sus0orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus0Value, susParameters->sus0coeffAlpha,
susParameters->sus0coeffBeta),
sus0VecBody, 3, 3, 1);
}
if (sus1valid) {
MatrixOperations<float>::multiply(
susParameters->sus1orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus1Value, susParameters->sus1coeffAlpha,
susParameters->sus1coeffBeta),
sus1VecBody, 3, 3, 1);
}
if (sus2valid) {
MatrixOperations<float>::multiply(
susParameters->sus2orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus2Value, susParameters->sus2coeffAlpha,
susParameters->sus2coeffBeta),
sus2VecBody, 3, 3, 1);
}
if (sus3valid) {
MatrixOperations<float>::multiply(
susParameters->sus3orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus3Value, susParameters->sus3coeffAlpha,
susParameters->sus3coeffBeta),
sus3VecBody, 3, 3, 1);
}
if (sus4valid) {
MatrixOperations<float>::multiply(
susParameters->sus4orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus4Value, susParameters->sus4coeffAlpha,
susParameters->sus4coeffBeta),
sus4VecBody, 3, 3, 1);
}
if (sus5valid) {
MatrixOperations<float>::multiply(
susParameters->sus5orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus5Value, susParameters->sus5coeffAlpha,
susParameters->sus5coeffBeta),
sus5VecBody, 3, 3, 1);
}
if (sus6valid) {
MatrixOperations<float>::multiply(
susParameters->sus6orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus6Value, susParameters->sus6coeffAlpha,
susParameters->sus6coeffBeta),
sus6VecBody, 3, 3, 1);
}
if (sus7valid) {
MatrixOperations<float>::multiply(
susParameters->sus7orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus7Value, susParameters->sus7coeffAlpha,
susParameters->sus7coeffBeta),
sus7VecBody, 3, 3, 1);
}
if (sus8valid) {
MatrixOperations<float>::multiply(
susParameters->sus8orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus8Value, susParameters->sus8coeffAlpha,
susParameters->sus8coeffBeta),
sus8VecBody, 3, 3, 1);
}
if (sus9valid) {
MatrixOperations<float>::multiply(
susParameters->sus9orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus9Value, susParameters->sus9coeffAlpha,
susParameters->sus9coeffBeta),
sus9VecBody, 3, 3, 1);
}
if (sus10valid) {
MatrixOperations<float>::multiply(
susParameters->sus10orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus10Value, susParameters->sus10coeffAlpha,
susParameters->sus10coeffBeta),
sus10VecBody, 3, 3, 1);
}
if (sus11valid) {
MatrixOperations<float>::multiply(
susParameters->sus11orientationMatrix[0],
susConverter.getSunVectorSensorFrame(sus11Value, susParameters->sus11coeffAlpha,
susParameters->sus11coeffBeta),
sus11VecBody, 3, 3, 1);
}
float susVecSensor[12][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
float susVecBody[12][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
/* ------ Mean Value: susDirEst ------ */
bool validIds[12] = {sus0valid, sus1valid, sus2valid, sus3valid, sus4valid, sus5valid,
sus6valid, sus7valid, sus8valid, sus9valid, sus10valid, sus11valid};
float susVecBody[3][12] = {{sus0VecBody[0], sus1VecBody[0], sus2VecBody[0], sus3VecBody[0],
sus4VecBody[0], sus5VecBody[0], sus6VecBody[0], sus7VecBody[0],
sus8VecBody[0], sus9VecBody[0], sus10VecBody[0], sus11VecBody[0]},
{sus0VecBody[1], sus1VecBody[1], sus2VecBody[1], sus3VecBody[1],
sus4VecBody[1], sus5VecBody[1], sus6VecBody[1], sus7VecBody[1],
sus8VecBody[1], sus9VecBody[1], sus10VecBody[1], sus11VecBody[1]},
{sus0VecBody[2], sus1VecBody[2], sus2VecBody[2], sus3VecBody[2],
sus4VecBody[2], sus5VecBody[2], sus6VecBody[2], sus7VecBody[2],
sus8VecBody[2], sus9VecBody[2], sus10VecBody[2], sus11VecBody[2]}};
if (susValid[0]) {
susConverter.calculateSunVector(susVecSensor[0], sus0Value);
MatrixOperations<float>::multiply(susParameters->sus0orientationMatrix[0], susVecSensor[0],
susVecBody[0], 3, 3, 1);
}
if (susValid[1]) {
susConverter.calculateSunVector(susVecSensor[1], sus1Value);
MatrixOperations<float>::multiply(susParameters->sus1orientationMatrix[0], susVecSensor[1],
susVecBody[1], 3, 3, 1);
}
if (susValid[2]) {
susConverter.calculateSunVector(susVecSensor[2], sus2Value);
MatrixOperations<float>::multiply(susParameters->sus2orientationMatrix[0], susVecSensor[2],
susVecBody[2], 3, 3, 1);
}
if (susValid[3]) {
susConverter.calculateSunVector(susVecSensor[3], sus3Value);
MatrixOperations<float>::multiply(susParameters->sus3orientationMatrix[0], susVecSensor[3],
susVecBody[3], 3, 3, 1);
}
if (susValid[4]) {
susConverter.calculateSunVector(susVecSensor[4], sus4Value);
MatrixOperations<float>::multiply(susParameters->sus4orientationMatrix[0], susVecSensor[4],
susVecBody[4], 3, 3, 1);
}
if (susValid[5]) {
susConverter.calculateSunVector(susVecSensor[5], sus5Value);
MatrixOperations<float>::multiply(susParameters->sus5orientationMatrix[0], susVecSensor[5],
susVecBody[5], 3, 3, 1);
}
if (susValid[6]) {
susConverter.calculateSunVector(susVecSensor[6], sus6Value);
MatrixOperations<float>::multiply(susParameters->sus6orientationMatrix[0], susVecSensor[6],
susVecBody[6], 3, 3, 1);
}
if (susValid[7]) {
susConverter.calculateSunVector(susVecSensor[7], sus7Value);
MatrixOperations<float>::multiply(susParameters->sus7orientationMatrix[0], susVecSensor[7],
susVecBody[7], 3, 3, 1);
}
if (susValid[8]) {
susConverter.calculateSunVector(susVecSensor[8], sus8Value);
MatrixOperations<float>::multiply(susParameters->sus8orientationMatrix[0], susVecSensor[8],
susVecBody[8], 3, 3, 1);
}
if (susValid[9]) {
susConverter.calculateSunVector(susVecSensor[9], sus9Value);
MatrixOperations<float>::multiply(susParameters->sus9orientationMatrix[0], susVecSensor[9],
susVecBody[9], 3, 3, 1);
}
if (susValid[10]) {
susConverter.calculateSunVector(susVecSensor[10], sus10Value);
MatrixOperations<float>::multiply(susParameters->sus10orientationMatrix[0], susVecSensor[10],
susVecBody[10], 3, 3, 1);
}
if (susValid[11]) {
susConverter.calculateSunVector(susVecSensor[11], sus11Value);
MatrixOperations<float>::multiply(susParameters->sus11orientationMatrix[0], susVecSensor[11],
susVecBody[11], 3, 3, 1);
}
double susMeanValue[3] = {0, 0, 0};
for (uint8_t i = 0; i < 12; i++) {
if (validIds[i]) {
susMeanValue[0] += susVecBody[0][i];
susMeanValue[1] += susVecBody[1][i];
susMeanValue[2] += susVecBody[2][i];
}
susMeanValue[0] += susVecBody[i][0];
susMeanValue[1] += susVecBody[i][1];
susMeanValue[2] += susVecBody[i][2];
}
double susVecTot[3] = {0.0, 0.0, 0.0};
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
if (VectorOperations<double>::norm(susVecTot, 3) != 0 and susDataProcessed->susVecTot.isValid()) {
lowPassFilter(susVecTot, susDataProcessed->susVecTot.value,
susParameters->susVectorFilterWeight);
}
/* -------- Sun Derivatiative --------------------- */
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
@ -402,33 +372,38 @@ void SensorProcessing::processSus(
susVecTotDerivativeValid = true;
}
}
if (VectorOperations<double>::norm(susVecTotDerivative, 3) != 0 and
susDataProcessed->susVecTotDerivative.isValid()) {
lowPassFilter(susVecTotDerivative, susDataProcessed->susVecTotDerivative.value,
susParameters->susRateFilterWeight);
}
timeOfSavedSusDirEst = timeOfSusMeasurement;
{
PoolReadGuard pg(susDataProcessed);
if (pg.getReadResult() == returnvalue::OK) {
std::memcpy(susDataProcessed->sus0vec.value, sus0VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus0vec.value, susVecBody[0], 3 * sizeof(float));
susDataProcessed->sus0vec.setValid(sus0valid);
std::memcpy(susDataProcessed->sus1vec.value, sus1VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus1vec.value, susVecBody[1], 3 * sizeof(float));
susDataProcessed->sus1vec.setValid(sus1valid);
std::memcpy(susDataProcessed->sus2vec.value, sus2VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus2vec.value, susVecBody[2], 3 * sizeof(float));
susDataProcessed->sus2vec.setValid(sus2valid);
std::memcpy(susDataProcessed->sus3vec.value, sus3VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus3vec.value, susVecBody[3], 3 * sizeof(float));
susDataProcessed->sus3vec.setValid(sus3valid);
std::memcpy(susDataProcessed->sus4vec.value, sus4VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus4vec.value, susVecBody[4], 3 * sizeof(float));
susDataProcessed->sus4vec.setValid(sus4valid);
std::memcpy(susDataProcessed->sus5vec.value, sus5VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus5vec.value, susVecBody[5], 3 * sizeof(float));
susDataProcessed->sus5vec.setValid(sus5valid);
std::memcpy(susDataProcessed->sus6vec.value, sus6VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus6vec.value, susVecBody[6], 3 * sizeof(float));
susDataProcessed->sus6vec.setValid(sus6valid);
std::memcpy(susDataProcessed->sus7vec.value, sus7VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus7vec.value, susVecBody[7], 3 * sizeof(float));
susDataProcessed->sus7vec.setValid(sus7valid);
std::memcpy(susDataProcessed->sus8vec.value, sus8VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus8vec.value, susVecBody[8], 3 * sizeof(float));
susDataProcessed->sus8vec.setValid(sus8valid);
std::memcpy(susDataProcessed->sus9vec.value, sus9VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus9vec.value, susVecBody[9], 3 * sizeof(float));
susDataProcessed->sus9vec.setValid(sus9valid);
std::memcpy(susDataProcessed->sus10vec.value, sus10VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus10vec.value, susVecBody[10], 3 * sizeof(float));
susDataProcessed->sus10vec.setValid(sus10valid);
std::memcpy(susDataProcessed->sus11vec.value, sus11VecBody, 3 * sizeof(float));
std::memcpy(susDataProcessed->sus11vec.value, susVecBody[11], 3 * sizeof(float));
susDataProcessed->sus11vec.setValid(sus11valid);
std::memcpy(susDataProcessed->susVecTot.value, susVecTot, 3 * sizeof(double));
susDataProcessed->susVecTot.setValid(true);
@ -459,12 +434,11 @@ void SensorProcessing::processGyr(
{
PoolReadGuard pg(gyrDataProcessed);
if (pg.getReadResult() == returnvalue::OK) {
double zeroVector[3] = {0.0, 0.0, 0.0};
std::memcpy(gyrDataProcessed->gyr0vec.value, zeroVector, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr1vec.value, zeroVector, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr2vec.value, zeroVector, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr3vec.value, zeroVector, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyrVecTot.value, zeroVector, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr0vec.value, ZERO_VEC_D, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr1vec.value, ZERO_VEC_D, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr2vec.value, ZERO_VEC_D, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyr3vec.value, ZERO_VEC_D, 3 * sizeof(double));
std::memcpy(gyrDataProcessed->gyrVecTot.value, ZERO_VEC_D, 3 * sizeof(double));
gyrDataProcessed->setValidity(false, true);
}
}

View File

@ -23,6 +23,9 @@ class SensorProcessing {
acsctrl::GpsDataProcessed *gpsDataProcessed,
const AcsParameters *acsParameters); // Will call protected functions
private:
static constexpr float ZERO_VEC_F[3] = {0, 0, 0};
static constexpr double ZERO_VEC_D[3] = {0, 0, 0};
protected:
// short description needed for every function
void processMgm(const float *mgm0Value, bool mgm0valid, const float *mgm1Value, bool mgm1valid,

View File

@ -1,121 +1,64 @@
#include "SusConverter.h"
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/LocalPoolVector.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include <math.h>
#include <iostream>
bool SusConverter::checkSunSensorData(const uint16_t susChannel[6]) {
if (susChannel[0] <= susChannelValueCheckLow || susChannel[0] > susChannelValueCheckHigh ||
uint64_t SusConverter::checkSunSensorData(const uint16_t susChannel[6]) {
if (susChannel[0] <= SUS_CHANNEL_VALUE_LOW || susChannel[0] > SUS_CHANNEL_VALUE_HIGH ||
susChannel[0] > susChannel[GNDREF]) {
return false;
return 0;
}
if (susChannel[1] <= susChannelValueCheckLow || susChannel[1] > susChannelValueCheckHigh ||
if (susChannel[1] <= SUS_CHANNEL_VALUE_LOW || susChannel[1] > SUS_CHANNEL_VALUE_HIGH ||
susChannel[1] > susChannel[GNDREF]) {
return false;
return 0;
};
if (susChannel[2] <= susChannelValueCheckLow || susChannel[2] > susChannelValueCheckHigh ||
if (susChannel[2] <= SUS_CHANNEL_VALUE_LOW || susChannel[2] > SUS_CHANNEL_VALUE_HIGH ||
susChannel[2] > susChannel[GNDREF]) {
return false;
return 0;
};
if (susChannel[3] <= susChannelValueCheckLow || susChannel[3] > susChannelValueCheckHigh ||
if (susChannel[3] <= SUS_CHANNEL_VALUE_LOW || susChannel[3] > SUS_CHANNEL_VALUE_HIGH ||
susChannel[3] > susChannel[GNDREF]) {
return false;
return 0;
};
susChannelValueSum =
uint64_t susChannelValueSum =
4 * susChannel[GNDREF] - (susChannel[0] + susChannel[1] + susChannel[2] + susChannel[3]);
if ((susChannelValueSum < susChannelValueSumHigh) &&
(susChannelValueSum > susChannelValueSumLow)) {
return false;
if (susChannelValueSum < SUS_ALBEDO_CHECK) {
return 0;
};
return true;
return susChannelValueSum;
}
void SusConverter::calcAngle(const uint16_t susChannel[6]) {
float xout, yout;
float s = 0.03; // s=[mm] gap between diodes
uint8_t d = 5; // d=[mm] edge length of the quadratic aperture
uint8_t h = 1; // h=[mm] distance between diodes and aperture
int ch0, ch1, ch2, ch3;
bool SusConverter::checkValidity(bool* susValid, const uint64_t brightness[12],
const float threshold) {
uint8_t maxBrightness = 0;
VectorOperations<uint64_t>::maxValue(brightness, 12, &maxBrightness);
if (brightness[maxBrightness] == 0) {
return true;
}
for (uint8_t idx = 0; idx < 12; idx++) {
if ((idx != maxBrightness) and (brightness[idx] < threshold * brightness[maxBrightness])) {
susValid[idx] = false;
continue;
}
susValid[idx] = true;
}
return false;
}
void SusConverter::calculateSunVector(float* sunVectorSensorFrame, const uint16_t susChannel[6]) {
// Substract measurement values from GNDREF zero current threshold
ch0 = susChannel[GNDREF] - susChannel[0];
ch1 = susChannel[GNDREF] - susChannel[1];
ch2 = susChannel[GNDREF] - susChannel[2];
ch3 = susChannel[GNDREF] - susChannel[3];
float ch0 = susChannel[GNDREF] - susChannel[0];
float ch1 = susChannel[GNDREF] - susChannel[1];
float ch2 = susChannel[GNDREF] - susChannel[2];
float ch3 = susChannel[GNDREF] - susChannel[3];
// Calculation of x and y
xout = ((d - s) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
yout = ((d - s) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
float xout = ((D - S) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
float yout = ((D - S) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
// Calculation of the angles
alphaBetaRaw[0] = atan2(xout, h) * (180 / M_PI); //[°]
alphaBetaRaw[1] = atan2(yout, h) * (180 / M_PI); //[°]
}
void SusConverter::calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]) {
uint8_t index, k, l;
// while loop iterates above all calibration cells to use the different calibration functions in
// each cell
k = 0;
while (k < 3) {
k++;
l = 0;
while (l < 3) {
l++;
// if-condition to check in which cell the data point has to be
if ((alphaBetaRaw[0] > ((completeCellWidth * ((k - 1) / 3.)) - halfCellWidth) &&
alphaBetaRaw[0] < ((completeCellWidth * (k / 3.)) - halfCellWidth)) &&
(alphaBetaRaw[1] > ((completeCellWidth * ((l - 1) / 3.)) - halfCellWidth) &&
alphaBetaRaw[1] < ((completeCellWidth * (l / 3.)) - halfCellWidth))) {
index = (3 * (k - 1) + l) - 1; // calculate the index of the datapoint for the right cell
alphaBetaCalibrated[0] =
coeffAlpha[index][0] + coeffAlpha[index][1] * alphaBetaRaw[0] +
coeffAlpha[index][2] * alphaBetaRaw[1] +
coeffAlpha[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] +
coeffAlpha[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] +
coeffAlpha[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] +
coeffAlpha[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] +
coeffAlpha[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] +
coeffAlpha[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] +
coeffAlpha[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°]
alphaBetaCalibrated[1] =
coeffBeta[index][0] + coeffBeta[index][1] * alphaBetaRaw[0] +
coeffBeta[index][2] * alphaBetaRaw[1] +
coeffBeta[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] +
coeffBeta[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] +
coeffBeta[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] +
coeffBeta[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] +
coeffBeta[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] +
coeffBeta[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] +
coeffBeta[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°]
}
}
}
}
float* SusConverter::calculateSunVector() {
// Calculate the normalized Sun Vector
sunVectorSensorFrame[0] = -(tan(alphaBetaCalibrated[0] * (M_PI / 180)) /
(sqrt((powf(tan(alphaBetaCalibrated[0] * (M_PI / 180)), 2)) +
powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
sunVectorSensorFrame[1] = -(tan(alphaBetaCalibrated[1] * (M_PI / 180)) /
(sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) +
powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
sunVectorSensorFrame[2] =
-(-1 / (sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) +
powf((tan(alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
return sunVectorSensorFrame;
}
float* SusConverter::getSunVectorSensorFrame(const uint16_t susChannel[6],
const float coeffAlpha[9][10],
const float coeffBeta[9][10]) {
calcAngle(susChannel);
calibration(coeffAlpha, coeffBeta);
return calculateSunVector();
sunVectorSensorFrame[0] = -xout;
sunVectorSensorFrame[1] = -yout;
sunVectorSensorFrame[2] = H;
VectorOperations<float>::normalize(sunVectorSensorFrame, sunVectorSensorFrame, 3);
}

View File

@ -1,8 +1,4 @@
#ifndef MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
#define MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
#include <fsfw/datapoollocal/LocalPoolVector.h>
#include <stdint.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include "AcsParameters.h"
@ -10,41 +6,26 @@ class SusConverter {
public:
SusConverter() {}
bool checkSunSensorData(const uint16_t susChannel[6]);
void calcAngle(const uint16_t susChannel[6]);
void calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]);
float* calculateSunVector();
float* getSunVectorSensorFrame(const uint16_t susChannel[6], const float coeffAlpha[9][10],
const float coeffBeta[9][10]);
uint64_t checkSunSensorData(const uint16_t susChannel[6]);
bool checkValidity(bool* susValid, const uint64_t brightness[12], const float threshold);
void calculateSunVector(float* sunVectorSensorFrame, const uint16_t susChannel[6]);
private:
float alphaBetaRaw[2]; //[°]
float alphaBetaCalibrated[2]; //[°]
float sunVectorSensorFrame[3]; //[-]
bool validFlag[12] = {returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK,
returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK,
returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK};
static const uint8_t GNDREF = 4;
uint16_t susChannelValueCheckHigh =
4096; //=2^12[Bit]high borderline for the channel values of one sun sensor for validity Check
uint8_t susChannelValueCheckLow =
0; //[Bit]low borderline for the channel values of one sun sensor for validity Check
uint16_t susChannelValueSumHigh =
100; // 4096[Bit]high borderline for check if the sun sensor is illuminated by the sun or by
// the reflection of sunlight from the moon/earth
uint8_t susChannelValueSumLow =
0; //[Bit]low borderline for check if the sun sensor is illuminated
// by the sun or by the reflection of sunlight from the moon/earth
uint8_t completeCellWidth = 140,
halfCellWidth = 70; //[°] Width of the calibration cells --> necessary for checking in
// which cell a data point should be
uint16_t susChannelValueSum = 0;
// =2^12[Bit]high borderline for the channel values of one sun sensor for validity Check
static constexpr uint16_t SUS_CHANNEL_VALUE_HIGH = 4096;
// [Bit]low borderline for the channel values of one sun sensor for validity Check
static constexpr uint8_t SUS_CHANNEL_VALUE_LOW = 0;
// 4096[Bit]high borderline for check if the sun sensor is illuminated by the sun or by the
// reflection of sunlight from the moon/earth
static constexpr uint16_t SUS_ALBEDO_CHECK = 1000;
// [Bit]low borderline for check if the sun sensor is illuminated by the sun or by the reflection
// of sunlight from the moon/earth
static constexpr uint8_t SUS_CHANNEL_SUM_LOW = 0;
static constexpr float S = 0.03; // S=[mm] gap between diodes
static constexpr float D = 5; // D=[mm] edge length of the quadratic aperture
static constexpr float H = 2.5; // H=[mm] distance between diodes and aperture
AcsParameters acsParameters;
};
#endif /* MISSION_CONTROLLER_ACS_SUSCONVERTER_H_ */

View File

@ -9,20 +9,36 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter
SafeCtrl::~SafeCtrl() {}
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
const bool satRotRateValid, const bool sunDirValid,
const uint8_t mekfEnabled,
const uint8_t dampingEnabled) {
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(
const bool magFieldValid, const bool mekfValid, const bool satRotRateValid,
const bool sunDirValid, const bool fusedRateSplitValid, const bool fusedRateTotalValid,
const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled) {
if (not magFieldValid) {
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
} else if (mekfEnabled and mekfValid) {
return acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF;
} else if (satRotRateValid and sunDirValid) {
return acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF;
} else if (dampingEnabled and satRotRateValid and not sunDirValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING;
} else if (not dampingEnabled and satRotRateValid and not sunDirValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
return acs::SafeModeStrategy::SAFECTRL_MEKF;
} else if (sunDirValid) {
if (gyrEnabled and satRotRateValid) {
return acs::SafeModeStrategy::SAFECTRL_GYR;
} else if (not gyrEnabled and fusedRateSplitValid) {
return acs::SafeModeStrategy::SAFECTRL_SUSMGM;
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
} else if (not sunDirValid) {
if (dampingEnabled) {
if (gyrEnabled and satRotRateValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR;
} else if (not gyrEnabled and satRotRateValid and fusedRateTotalValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM;
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
} else if (not dampingEnabled and satRotRateValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
@ -43,8 +59,7 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
errorAngle = acos(dotSun);
splitRotationalRate(satRotRateB, sunDirB);
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
acsParameters->safeModeControllerParameters.k_parallelMekf,
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelMekf,
acsParameters->safeModeControllerParameters.k_orthoMekf);
calculateAngleErrorTorque(sunDirB, sunDirRefB,
acsParameters->safeModeControllerParameters.k_alignMekf);
@ -57,9 +72,8 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
const double *sunDirB, const double *sunDirRefB, double *magMomB,
double &errorAngle) {
void SafeCtrl::safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
@ -68,11 +82,10 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
errorAngle = acos(dotSun);
splitRotationalRate(satRotRateB, sunDirB);
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
acsParameters->safeModeControllerParameters.k_orthoGyr);
calculateAngleErrorTorque(sunDirB, sunDirRefB,
acsParameters->safeModeControllerParameters.k_alignNonMekf);
acsParameters->safeModeControllerParameters.k_alignGyr);
// sum of all torques
for (uint8_t i = 0; i < 3; i++) {
@ -82,8 +95,33 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
const double *rotRateOrthogonalB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
// calculate error angle between sunDirRef and sunDir
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
errorAngle = acos(dotSun);
std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB));
std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB));
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
calculateAngleErrorTorque(sunDirB, sunDirRefB,
acsParameters->safeModeControllerParameters.k_alignSusMgm);
// sum of all torques
for (uint8_t i = 0; i < 3; i++) {
cmdTorque[i] = cmdAlign[i] + cmdOrtho[i] + cmdParallel[i];
}
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
@ -91,9 +129,28 @@ void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRate
errorAngle = NAN;
splitRotationalRate(satRotRateB, sunDirRefB);
calculateRotationalRateTorque(sunDirRefB, sunDirRefB, errorAngle,
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
acsParameters->safeModeControllerParameters.k_orthoGyr);
// sum of all torques
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
// calculate magnetic moment to command
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB,
double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
// no error angle available for eclipse
errorAngle = NAN;
splitRotationalRate(satRotRateB, sunDirRefB);
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
// sum of all torques
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
@ -110,9 +167,7 @@ void SafeCtrl::splitRotationalRate(const double *satRotRateB, const double *sunD
VectorOperations<double>::subtract(satRotRateB, satRotRateParallelB, satRotRateOrthogonalB, 3);
}
void SafeCtrl::calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
double &errorAngle, const double gainParallel,
const double gainOrtho) {
void SafeCtrl::calculateRotationalRateTorque(const double gainParallel, const double gainOrtho) {
// calculate torque for parallel rotational rate
VectorOperations<double>::mulScalar(satRotRateParallelB, -gainParallel, cmdParallel, 3);

View File

@ -14,23 +14,34 @@ class SafeCtrl {
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
const bool satRotRateValid, const bool sunDirValid,
const uint8_t mekfEnabled, const uint8_t dampingEnabled);
const bool fusedRateSplitValid,
const bool fusedRateTotalValid, const uint8_t mekfEnabled,
const uint8_t gyrEnabled, const uint8_t dampingEnabled);
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
const double *quatBI, const double *sunDirRefB, double *magMomB,
double &errorAngle);
void safeNonMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void safeRateDamping(const double *magFieldB, const double *satRotRateB, const double *sunDirRefB,
double *magMomB, double &errorAngle);
void safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
const double *rotRateOrthogonalB, const double *sunDirB, const double *sunDirRefB,
double *magMomB, double &errorAngle);
void safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void splitRotationalRate(const double *satRotRateB, const double *sunDirB);
void calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
double &errorAngle, const double gainParallel,
const double gainOrtho);
void calculateRotationalRates(const double *magFieldB, const double *magRateB,
const double *sunDirB, const double *sunRateB,
double *fusedRotRate);
void calculateRotationalRateTorque(const double gainParallel, const double gainOrtho);
void calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
const double gainAlign);

View File

@ -18,7 +18,8 @@ enum SetIds : uint32_t {
GPS_PROCESSED_DATA,
MEKF_DATA,
CTRL_VAL_DATA,
ACTUATOR_CMD_DATA
ACTUATOR_CMD_DATA,
FUSED_ROTATION_RATE_DATA,
};
enum PoolIds : lp_id_t {
@ -103,6 +104,10 @@ enum PoolIds : lp_id_t {
RW_TARGET_TORQUE,
RW_TARGET_SPEED,
MTQ_TARGET_DIPOLE,
// Fused Rotation Rate
ROT_RATE_ORTHOGONAL,
ROT_RATE_PARALLEL,
ROT_RATE_TOTAL,
};
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
@ -115,6 +120,7 @@ static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 5;
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 3;
/**
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
@ -273,6 +279,19 @@ class ActuatorCmdData : public StaticLocalDataSet<ACT_CMD_SET_ENTRIES> {
private:
};
class FusedRotRateData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENTRIES> {
public:
FusedRotRateData(HasLocalDataPoolIF* hkOwner)
: StaticLocalDataSet(hkOwner, FUSED_ROTATION_RATE_DATA) {}
lp_vec_t<double, 3> rotRateOrthogonal =
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_ORTHOGONAL, this);
lp_vec_t<double, 3> rotRateParallel = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_PARALLEL, this);
lp_vec_t<double, 3> rotRateTotal = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL, this);
private:
};
} // namespace acsctrl
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */

View File

@ -9,6 +9,85 @@
namespace tcsCtrl {
/**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
* is exceeded.
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
* limit is exceeded to avoid reaching NOP limit
*/
struct TempLimits {
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
float nopUpperLimit)
: opLowerLimit(opLowerLimit),
opUpperLimit(opUpperLimit),
cutOffLimit(cutOffLimit),
nopLowerLimit(nopLowerLimit),
nopUpperLimit(nopUpperLimit) {}
float opLowerLimit;
float opUpperLimit;
float cutOffLimit;
float nopLowerLimit;
float nopUpperLimit;
};
/**
* Abstraction for the state of a single thermal component
*/
struct ThermalState {
uint8_t noSensorAvailableCounter;
// Which sensor is used for this component?
uint8_t sensorIndex = 0;
// Is heating on for that thermal module?
bool heating = false;
// Which switch is being used for heating the component
heater::Switch heaterSwitch = heater::Switch::HEATER_NONE;
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
// when a switch command is sent, with no guarantess that the heater actually went on.
uint32_t heaterStartTime = 0;
uint32_t heaterEndTime = 0;
};
/**
* Abstraction for the state of a single heater.
*/
struct HeaterState {
bool switchTransition = false;
heater::SwitchState target = heater::SwitchState::OFF;
uint8_t heaterSwitchControlCycles = 0;
bool trackHeaterMaxBurnTime = false;
Countdown heaterOnMaxBurnTime;
};
using HeaterSwitchStates = std::array<heater::SwitchState, heater::NUMBER_OF_SWITCHES>;
enum ThermalComponents : uint8_t {
NONE = 0,
ACS_BOARD = 1,
MGT = 2,
RW = 3,
STR = 4,
IF_BOARD = 5,
TCS_BOARD = 6,
OBC = 7,
LEGACY_OBCIF_BOARD = 8,
SBAND_TRANSCEIVER = 9,
PCDUP60_BOARD = 10,
PCDUACU = 11,
PCDUPDU = 12,
PLPCDU_BOARD = 13,
PLOCMISSION_BOARD = 14,
PLOCPROCESSING_BOARD = 15,
DAC = 16,
CAMERA = 17,
DRO = 18,
X8 = 19,
HPA = 20,
TX = 21,
MPA = 22,
SCEX_BOARD = 23,
NUM_THERMAL_COMPONENTS
};
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_CONTROLLER;
static constexpr Event NO_VALID_SENSOR_TEMPERATURE = MAKE_EVENT(0, severity::MEDIUM);
static constexpr Event NO_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM);
@ -18,6 +97,12 @@ static constexpr Event CAMERA_OVERHEATING = MAKE_EVENT(5, severity::HIGH);
static constexpr Event PCDU_SYSTEM_OVERHEATING = MAKE_EVENT(6, severity::HIGH);
static constexpr Event HEATER_NOT_OFF_FOR_OFF_MODE = MAKE_EVENT(7, severity::MEDIUM);
static constexpr Event MGT_OVERHEATING = MAKE_EVENT(8, severity::HIGH);
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
static constexpr Event TCS_SWITCHING_HEATER_ON = MAKE_EVENT(9, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
static constexpr Event TCS_SWITCHING_HEATER_OFF = MAKE_EVENT(10, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Heater index. P2: Maximum burn time for heater.
static constexpr Event TCS_HEATER_MAX_BURN_TIME_REACHED = MAKE_EVENT(11, severity::MEDIUM);
enum SetId : uint32_t {
SENSOR_TEMPERATURES = 0,
@ -25,6 +110,7 @@ enum SetId : uint32_t {
SUS_TEMPERATURES = 2,
COMPONENT_TEMPERATURES = 3,
HEATER_SET = 4,
TCS_CTRL_INFO = 5
};
enum PoolIds : lp_id_t {
@ -92,7 +178,13 @@ enum PoolIds : lp_id_t {
TEMP_ADC_PAYLOAD_PCDU,
HEATER_SWITCH_LIST,
HEATER_CURRENT
HEATER_CURRENT,
HEATER_ON_FOR_COMPONENT_VEC,
SENSOR_USED_FOR_TCS_CTRL,
HEATER_IDX_USED_FOR_TCS_CTRL,
HEATER_START_TIME,
HEATER_END_TIME
};
static const uint8_t ENTRIES_SENSOR_TEMPERATURE_SET = 25;
@ -232,6 +324,29 @@ class HeaterInfo : public StaticLocalDataSet<3> {
lp_var_t<int16_t> heaterCurrent = lp_var_t<int16_t>(sid.objectId, PoolIds::HEATER_CURRENT, this);
};
class TcsCtrlInfo : public StaticLocalDataSet<6> {
public:
explicit TcsCtrlInfo(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, TCS_CTRL_INFO) {}
explicit TcsCtrlInfo(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TCS_CTRL_INFO)) {}
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heatingOnVec =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
sid.objectId, PoolIds::HEATER_ON_FOR_COMPONENT_VEC, this);
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> sensorIdxUsedForTcsCtrl =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId,
PoolIds::SENSOR_USED_FOR_TCS_CTRL, this);
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterSwitchIdx =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
sid.objectId, PoolIds::HEATER_IDX_USED_FOR_TCS_CTRL, this);
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterStartTimes =
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_START_TIME,
this);
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterEndTimes =
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_END_TIME,
this);
};
} // namespace tcsCtrl
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ */

View File

@ -91,19 +91,21 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
} // namespace cfdp
std::atomic_bool tcs::TCS_BOARD_SHORTLY_UNAVAILABLE = false;
std::atomic_bool core::SAVE_PUS_SEQUENCE_COUNT = false;
std::atomic_bool core::SAVE_CFDP_SEQUENCE_COUNT = false;
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
PersistentTmStores& stores,
uint32_t eventManagerQueueDepth) {
uint32_t eventManagerQueueDepth, bool enableHkSets) {
// Framework objects
new EventManager(objects::EVENT_MANAGER, eventManagerQueueDepth);
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
if (healthTable_ != nullptr) {
*healthTable_ = healthTable;
}
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 5, enableHkSets, 120);
new VerificationReporter();
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
StorageManagerIF* tcStore;
@ -155,9 +157,11 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", **tmStore, **ipcStore,
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
config::MAX_PUS_FUNNEL_QUEUE_DEPTH, sdcMan,
config::PUS_SEQUENCE_COUNT_FILE,
core::SAVE_PUS_SEQUENCE_COUNT);
// The PUS funnel routes all live TM to the live destinations and to the TM stores.
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper, sdcMan);
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper);
// MISC store and PUS funnel to MISC store routing
{
@ -216,7 +220,9 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
stores.cfdpStore->getReportReceptionQueue(0));
}
PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", **tmStore,
**ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH);
**ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH, sdcMan,
config::CFDP_SEQUENCE_COUNT_FILE,
core::SAVE_CFDP_SEQUENCE_COUNT);
*cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, stores.cfdpStore->getReportReceptionQueue(0),
*ramToFileStore, config::EIVE_CFDP_APID);
@ -305,9 +311,9 @@ void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF&
heaterHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
}
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler) {
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler, bool pollPlPcduTmp1) {
auto* tcsCtrl = new ThermalController(objects::THERMAL_CONTROLLER, heaterHandler,
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE);
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE, pollPlPcduTmp1);
tcsCtrl->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
}
void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,

View File

@ -45,11 +45,12 @@ namespace ObjectFactory {
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
PersistentTmStores& stores, uint32_t eventManagerQueueDepth);
PersistentTmStores& stores, uint32_t eventManagerQueueDepth,
bool enableHkSets);
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
HeaterHandler*& heaterHandler);
void createThermalController(HeaterHandler& heaterHandler);
void createThermalController(HeaterHandler& heaterHandler, bool pollPlPcduTmp1);
void createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,
std::array<DeviceHandlerBase*, 4> rws, std::array<object_id_t, 4> rwIds);
void createSusAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 12> suses);

View File

@ -1,7 +1,9 @@
#include <fsfw/src/fsfw/datapool/PoolReadGuard.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/payload/PayloadPcduHandler.h>
#include "OBSWConfig.h"
#include "fsfw/thermal/tcsDefinitions.h"
#ifdef XIPHOS_Q7S
#include <fsfw_hal/linux/UnixFileGuard.h>
@ -64,6 +66,16 @@ void PayloadPcduHandler::doShutDown() {
return;
}
state = States::PL_PCDU_OFF;
quickTransitionAlreadyCalled = false;
{
PoolReadGuard pg(&adcSet);
adcSet.setReportingEnabled(false);
adcSet.tempC = thermal::INVALID_TEMPERATURE;
std::memset(adcSet.channels.value, 0, sizeof(adcSet.channels.value));
std::memset(adcSet.processed.value, 0, sizeof(adcSet.processed.value));
adcSet.setValidity(false, true);
}
// No need to set mode _MODE_POWER_DOWN, power switching was already handled
setMode(MODE_OFF);
}
@ -73,14 +85,7 @@ void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
stateMachineToNormal(modeFrom, subModeFrom);
return;
} else if (getMode() == _MODE_TO_ON and modeFrom == MODE_NORMAL) {
gpioIF->pullLow(gpioIds::PLPCDU_ENB_HPA);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_MPA);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_X8);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_DRO);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1);
pullAllGpiosLow(200);
state = States::STACK_5V_CORRECT;
}
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
@ -89,6 +94,11 @@ void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_t subModeFrom) {
using namespace plpcdu;
bool doFinish = true;
if (toNormalOneShot) {
PoolReadGuard pg(&adcSet);
adcSet.setReportingEnabled(true);
toNormalOneShot = false;
}
if (((getSubmode() >> SOLID_STATE_RELAYS_ADC_ON) & 0b1) == 1) {
if (state == States::PL_PCDU_OFF) {
sif::error << "PayloadPcduHandler::stateMachineToNormal: Unexpected state PL_PCDU_OFF"
@ -114,23 +124,23 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
state = States::ON_TRANS_ADC_CLOSE_ZERO;
adcCountdown.setTimeout(50);
adcCountdown.resetTimer();
adcState = AdcStates::BOOT_DELAY;
adcState = AdcState::BOOT_DELAY;
doFinish = false;
// If the values are not close to zero, we should not allow transition
monMode = MonitoringMode::CLOSE_TO_ZERO;
}
}
if (state == States::ON_TRANS_ADC_CLOSE_ZERO) {
if (adcState == AdcStates::BOOT_DELAY) {
if (adcState == AdcState::BOOT_DELAY) {
doFinish = false;
if (adcCountdown.hasTimedOut()) {
adcState = AdcStates::SEND_SETUP;
adcState = AdcState::SEND_SETUP;
adcCmdExecuted = false;
}
}
if (adcState == AdcStates::SEND_SETUP) {
if (adcState == AdcState::SEND_SETUP) {
if (adcCmdExecuted) {
adcState = AdcStates::NORMAL;
adcState = AdcState::NORMAL;
doFinish = true;
adcCountdown.setTimeout(100);
adcCountdown.resetTimer();
@ -167,6 +177,7 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
switchHandler(MPA_ON, gpioIds::PLPCDU_ENB_MPA, "MPA");
switchHandler(HPA_ON, gpioIds::PLPCDU_ENB_HPA, "HPA");
if (doFinish) {
toNormalOneShot = true;
setMode(MODE_NORMAL);
}
return returnvalue::OK;
@ -174,11 +185,11 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_
ReturnValue_t PayloadPcduHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
switch (adcState) {
case (AdcStates::SEND_SETUP): {
case (AdcState::SEND_SETUP): {
*id = plpcdu::SETUP_CMD;
return buildCommandFromCommand(*id, nullptr, 0);
}
case (AdcStates::NORMAL): {
case (AdcState::NORMAL): {
*id = plpcdu::READ_WITH_TEMP_EXT;
return buildCommandFromCommand(*id, nullptr, 0);
}
@ -190,7 +201,7 @@ ReturnValue_t PayloadPcduHandler::buildNormalDeviceCommand(DeviceCommandId_t* id
}
ReturnValue_t PayloadPcduHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
if (adcState == AdcStates::SEND_SETUP) {
if (adcState == AdcState::SEND_SETUP) {
*id = plpcdu::SETUP_CMD;
return buildCommandFromCommand(*id, nullptr, 0);
}
@ -211,9 +222,9 @@ void PayloadPcduHandler::updateSwitchGpio(gpioId_t id, gpio::Levels level) {
}
void PayloadPcduHandler::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(plpcdu::READ_CMD, 2, &adcSet);
insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1, &adcSet);
insertInCommandAndReplyMap(plpcdu::READ_WITH_TEMP_EXT, 1, &adcSet);
insertInCommandAndReplyMap(plpcdu::READ_CMD, 2);
insertInCommandAndReplyMap(plpcdu::READ_TEMP_EXT, 1);
insertInCommandAndReplyMap(plpcdu::READ_WITH_TEMP_EXT, 1);
insertInCommandAndReplyMap(plpcdu::SETUP_CMD, 1);
}
@ -277,27 +288,31 @@ ReturnValue_t PayloadPcduHandler::interpretDeviceReply(DeviceCommandId_t id,
break;
}
case (READ_CMD): {
PoolReadGuard pg(&adcSet);
if (pg.getReadResult() != returnvalue::OK) {
return pg.getReadResult();
{
PoolReadGuard pg(&adcSet);
if (pg.getReadResult() != returnvalue::OK) {
return pg.getReadResult();
}
handleExtConvRead(packet);
checkAdcValues();
adcSet.setValidity(true, true);
}
handleExtConvRead(packet);
checkAdcValues();
adcSet.setValidity(true, true);
handlePrintout();
break;
}
case (READ_WITH_TEMP_EXT): {
PoolReadGuard pg(&adcSet);
if (pg.getReadResult() != returnvalue::OK) {
return pg.getReadResult();
{
PoolReadGuard pg(&adcSet);
if (pg.getReadResult() != returnvalue::OK) {
return pg.getReadResult();
}
handleExtConvRead(packet);
uint8_t tempStartIdx = ADC_REPLY_SIZE + TEMP_REPLY_SIZE - 2;
adcSet.tempC.value =
max1227::getTemperature(packet[tempStartIdx] << 8 | packet[tempStartIdx + 1]);
checkAdcValues();
adcSet.setValidity(true, true);
}
handleExtConvRead(packet);
uint8_t tempStartIdx = ADC_REPLY_SIZE + TEMP_REPLY_SIZE - 2;
adcSet.tempC.value =
max1227::getTemperature(packet[tempStartIdx] << 8 | packet[tempStartIdx + 1]);
checkAdcValues();
adcSet.setValidity(true, true);
handlePrintout();
break;
}
@ -367,16 +382,9 @@ void PayloadPcduHandler::enablePeriodicPrintout(bool enable, uint8_t divider) {
void PayloadPcduHandler::quickTransitionBackToOff(bool startTransitionToOff, bool notifyFdir) {
States currentState = state;
gpioIF->pullLow(gpioIds::PLPCDU_ENB_HPA);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_MPA);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_X8);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_DRO);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1);
pullAllGpiosLow(200);
state = States::STACK_5V_SWITCHING;
adcState = AdcStates::OFF;
adcState = AdcState::OFF;
if (startTransitionToOff) {
startTransition(MODE_OFF, 0);
}
@ -405,10 +413,13 @@ void PayloadPcduHandler::checkAdcValues() {
adcSet.processed[U_DRO_DIV_6] = static_cast<float>(adcSet.channels[11]) * SCALE_VOLTAGE;
float lowerBound = 0.0;
float upperBound = 0.0;
bool adcTransition = false;
adcTransition = state == States::ON_TRANS_DRO and adcCountdown.isBusy();
// Now check against voltage and current limits, depending on state
if (state >= States::ON_TRANS_DRO and not adcTransition) {
bool adcTransition = adcState == AdcState::NORMAL and adcCountdown.isBusy();
if (NO_ADC_CHECKS or adcTransition) {
return;
}
// Now check against voltage and current limits.
uint8_t submode = getSubmode();
if (((submode >> NormalSubmodeBits::DRO_ON) & 0b1) == 0b1) {
if (ssrToDroInjectionRequested) {
handleFailureInjection("SSR to DRO", NEG_V_OUT_OF_BOUNDS);
ssrToDroInjectionRequested = false;
@ -435,8 +446,7 @@ void PayloadPcduHandler::checkAdcValues() {
return;
}
}
adcTransition = state == States::ON_TRANS_X8 and adcCountdown.isBusy();
if (state >= States::ON_TRANS_X8 and not adcTransition) {
if (((submode >> NormalSubmodeBits::X8_ON) & 0b1) == 0b1) {
if (droToX8InjectionRequested) {
handleFailureInjection("X8 to TX", U_X8_OUT_OF_BOUNDS);
droToX8InjectionRequested = false;
@ -453,8 +463,7 @@ void PayloadPcduHandler::checkAdcValues() {
return;
}
}
adcTransition = state == States::ON_TRANS_TX and adcCountdown.isBusy();
if (state >= States::ON_TRANS_TX and not adcTransition) {
if (((submode >> NormalSubmodeBits::TX_ON) & 0b1) == 0b1) {
if (txToMpaInjectionRequested) {
handleFailureInjection("TX to MPA", U_TX_OUT_OF_BOUNDS);
txToMpaInjectionRequested = false;
@ -471,8 +480,7 @@ void PayloadPcduHandler::checkAdcValues() {
return;
}
}
adcTransition = state == States::ON_TRANS_MPA and adcCountdown.isBusy();
if (state >= States::ON_TRANS_MPA and not adcTransition) {
if (((submode >> NormalSubmodeBits::MPA_ON) & 0b1) == 0b1) {
if (mpaToHpaInjectionRequested) {
handleFailureInjection("MPA to HPA", U_HPA_OUT_OF_BOUNDS);
mpaToHpaInjectionRequested = false;
@ -489,8 +497,7 @@ void PayloadPcduHandler::checkAdcValues() {
return;
}
}
adcTransition = state == States::ON_TRANS_HPA and adcCountdown.isBusy();
if (state >= States::ON_TRANS_HPA and not adcTransition) {
if (((submode >> NormalSubmodeBits::HPA_ON) & 0b1) == 0b1) {
if (allOnInjectRequested) {
handleFailureInjection("All On", U_HPA_OUT_OF_BOUNDS);
allOnInjectRequested = false;
@ -677,6 +684,18 @@ void PayloadPcduHandler::handleFailureInjection(std::string output, Event event)
droToX8InjectionRequested = false;
}
void PayloadPcduHandler::pullAllGpiosLow(uint32_t delayBeforeSwitchingOffDro) {
sif::info << "Pulling all PL PCDU GPIOs to low" << std::endl;
gpioIF->pullLow(gpioIds::PLPCDU_ENB_HPA);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_MPA);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_X8);
TaskFactory::delayTask(delayBeforeSwitchingOffDro);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_DRO);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0);
gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1);
}
ReturnValue_t PayloadPcduHandler::handleDoubleParamUpdate(std::string key,
ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues) {
@ -692,6 +711,8 @@ ReturnValue_t PayloadPcduHandler::handleDoubleParamUpdate(std::string key,
return params.writeJsonFile();
}
LocalPoolDataSetBase* PayloadPcduHandler::getDataSetHandle(sid_t sid) { return &adcSet; }
#ifdef XIPHOS_Q7S
ReturnValue_t PayloadPcduHandler::extConvAsTwoCallback(SpiComIF* comIf, SpiCookie* cookie,
const uint8_t* sendData, size_t sendLen,

View File

@ -76,6 +76,8 @@ class PayloadPcduHandler : public DeviceHandlerBase {
#endif
private:
static constexpr bool NO_ADC_CHECKS = false;
enum class States : uint8_t {
PL_PCDU_OFF,
STACK_5V_SWITCHING,
@ -84,20 +86,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
// Solid State Relay, enable battery voltages VBAT0 and VBAT1. This will also switch on
// the ADC
ON_TRANS_SSR,
ON_TRANS_ADC_CLOSE_ZERO,
// Enable Dielectric Resonant Oscillator and start monitoring voltages as
// soon as DRO voltage reaches 6V
ON_TRANS_DRO,
// Switch on X8 compoennt and monitor voltages for 5 seconds
ON_TRANS_X8,
// Switch on TX component and monitor voltages for 5 seconds
ON_TRANS_TX,
// Switch on MPA component and monitor voltages for 5 seconds
ON_TRANS_MPA,
// Switch on HPA component and monitor voltages for 5 seconds
ON_TRANS_HPA,
// All components of the experiment are on
PL_PCDU_ON,
ON_TRANS_ADC_CLOSE_ZERO
} state = States::PL_PCDU_OFF;
duallane::Submodes pwrSubmode = duallane::Submodes::A_SIDE;
@ -106,7 +95,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
enum class MonitoringMode { NONE, CLOSE_TO_ZERO, NEGATIVE } monMode = MonitoringMode::NONE;
enum class AdcStates { OFF, BOOT_DELAY, SEND_SETUP, NORMAL } adcState = AdcStates::OFF;
enum class AdcState { OFF, BOOT_DELAY, SEND_SETUP, NORMAL } adcState = AdcState::OFF;
bool goToNormalMode = false;
plpcdu::PlPcduAdcSet adcSet;
@ -128,6 +117,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
bool mpaToHpaInjectionRequested = false;
bool allOnInjectRequested = false;
bool clearSetOnOffFlag = true;
bool toNormalOneShot = true;
PeriodicOperationDivider opDivider = PeriodicOperationDivider(5);
uint8_t tempReadDivisor = 1;
@ -168,6 +158,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
void handleExtConvRead(const uint8_t* bufStart);
void handlePrintout();
void pullAllGpiosLow(uint32_t delayBeforeSwitchingOffDro);
void checkAdcValues();
void handleOutOfBoundsPrintout();
void checkJsonFileInit();
@ -178,6 +169,7 @@ class PayloadPcduHandler : public DeviceHandlerBase {
ReturnValue_t serializeFloat(uint32_t& param, float val);
ReturnValue_t handleDoubleParamUpdate(std::string key, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues);
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
};
#endif /* LINUX_DEVICES_PLPCDUHANDLER_H_ */

View File

@ -1,6 +1,7 @@
#include <OBSWConfig.h>
#include <devices/gpioIds.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/payload/RadiationSensorHandler.h>
#include <mission/power/gsDefs.h>
#include <mission/tcs/max1227.h>
@ -15,6 +16,8 @@ RadiationSensorHandler::RadiationSensorHandler(object_id_t objectId, object_id_t
if (comCookie == nullptr) {
sif::error << "RadiationSensorHandler: Invalid com cookie" << std::endl;
}
// Time out immediately so we get an immediate measurement at device startup.
measurementCd.timeOut();
}
RadiationSensorHandler::~RadiationSensorHandler() {}
@ -51,14 +54,17 @@ void RadiationSensorHandler::doShutDown() {
}
ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
if (measurementCd.isBusy()) {
return NOTHING_TO_SEND;
}
switch (communicationStep) {
case CommunicationStep::START_CONVERSION: {
*id = RAD_SENSOR::START_CONVERSION;
*id = radSens::START_CONVERSION;
communicationStep = CommunicationStep::READ_CONVERSIONS;
break;
}
case CommunicationStep::READ_CONVERSIONS: {
*id = RAD_SENSOR::READ_CONVERSIONS;
*id = radSens::READ_CONVERSIONS;
communicationStep = CommunicationStep::START_CONVERSION;
break;
}
@ -73,7 +79,7 @@ ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t
ReturnValue_t RadiationSensorHandler::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
if (internalState == InternalState::SETUP) {
*id = RAD_SENSOR::WRITE_SETUP;
*id = radSens::WRITE_SETUP;
} else {
return NOTHING_TO_SEND;
}
@ -84,15 +90,19 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
const uint8_t *commandData,
size_t commandDataLen) {
switch (deviceCommand) {
case (RAD_SENSOR::WRITE_SETUP): {
cmdBuffer[0] = RAD_SENSOR::SETUP_DEFINITION;
case (radSens::WRITE_SETUP): {
cmdBuffer[0] = radSens::SETUP_DEFINITION;
rawPacket = cmdBuffer;
rawPacketLen = 1;
internalState = InternalState::CONFIGURED;
return returnvalue::OK;
}
case (RAD_SENSOR::START_CONVERSION): {
case (radSens::START_CONVERSION): {
ReturnValue_t result = gpioIF->pullHigh(gpioIds::ENABLE_RADFET);
// Test a small delay between pulling the RADFET high and reading the sensor. As long as this
// delay remains small enough, this should not cause scheduling issues. Do not make this
// delay large, this device might be scheduled inside the ACS PST!
TaskFactory::delayTask(5);
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::warning
@ -102,25 +112,25 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
#endif
}
/* First the fifo will be reset here */
cmdBuffer[0] = RAD_SENSOR::RESET_DEFINITION;
cmdBuffer[1] = RAD_SENSOR::CONVERSION_DEFINITION;
cmdBuffer[0] = radSens::RESET_DEFINITION;
cmdBuffer[1] = radSens::CONVERSION_DEFINITION;
rawPacket = cmdBuffer;
rawPacketLen = 2;
return returnvalue::OK;
}
case (RAD_SENSOR::READ_CONVERSIONS): {
cmdBuffer[0] = RAD_SENSOR::DUMMY_BYTE;
std::memset(cmdBuffer, RAD_SENSOR::DUMMY_BYTE, RAD_SENSOR::READ_SIZE);
case (radSens::READ_CONVERSIONS): {
cmdBuffer[0] = radSens::DUMMY_BYTE;
std::memset(cmdBuffer, radSens::DUMMY_BYTE, radSens::READ_SIZE);
rawPacket = cmdBuffer;
rawPacketLen = RAD_SENSOR::READ_SIZE;
rawPacketLen = radSens::READ_SIZE;
return returnvalue::OK;
}
case RAD_SENSOR::ENABLE_DEBUG_OUTPUT: {
case radSens::ENABLE_DEBUG_OUTPUT: {
printPeriodicData = true;
rawPacketLen = 0;
return returnvalue::OK;
}
case RAD_SENSOR::DISABLE_DEBUG_OUTPUT: {
case radSens::DISABLE_DEBUG_OUTPUT: {
rawPacketLen = 0;
printPeriodicData = false;
return returnvalue::OK;
@ -132,12 +142,11 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
}
void RadiationSensorHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(RAD_SENSOR::WRITE_SETUP);
this->insertInCommandMap(RAD_SENSOR::START_CONVERSION);
this->insertInCommandMap(RAD_SENSOR::ENABLE_DEBUG_OUTPUT);
this->insertInCommandMap(RAD_SENSOR::DISABLE_DEBUG_OUTPUT);
this->insertInCommandAndReplyMap(RAD_SENSOR::READ_CONVERSIONS, 1, &dataset,
RAD_SENSOR::READ_SIZE);
this->insertInCommandMap(radSens::WRITE_SETUP);
this->insertInCommandMap(radSens::START_CONVERSION);
this->insertInCommandMap(radSens::ENABLE_DEBUG_OUTPUT);
this->insertInCommandMap(radSens::DISABLE_DEBUG_OUTPUT);
this->insertInCommandAndReplyMap(radSens::READ_CONVERSIONS, 1, &dataset, radSens::READ_SIZE);
}
ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t remainingSize,
@ -145,11 +154,11 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
*foundId = this->getPendingCommand();
switch (*foundId) {
case RAD_SENSOR::START_CONVERSION:
case RAD_SENSOR::WRITE_SETUP:
case radSens::START_CONVERSION:
case radSens::WRITE_SETUP:
*foundLen = remainingSize;
return IGNORE_REPLY_DATA;
case RAD_SENSOR::READ_CONVERSIONS: {
case radSens::READ_CONVERSIONS: {
ReturnValue_t result = gpioIF->pullLow(gpioIds::ENABLE_RADFET);
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
@ -160,8 +169,8 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
}
break;
}
case RAD_SENSOR::ENABLE_DEBUG_OUTPUT:
case RAD_SENSOR::DISABLE_DEBUG_OUTPUT:
case radSens::ENABLE_DEBUG_OUTPUT:
case radSens::DISABLE_DEBUG_OUTPUT:
sif::info << "RadiationSensorHandler::scanForReply: " << remainingSize << std::endl;
break;
default:
@ -176,24 +185,27 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
switch (id) {
case RAD_SENSOR::READ_CONVERSIONS: {
case radSens::READ_CONVERSIONS: {
uint8_t offset = 0;
PoolReadGuard readSet(&dataset);
uint16_t tempRaw = ((packet[offset] & 0x0f) << 8) | packet[offset + 1];
dataset.temperatureCelcius = max1227::getTemperature(tempRaw);
offset += 2;
dataset.ain0 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain1 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 6;
dataset.ain4 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain5 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain6 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain7 = (*(packet + offset) << 8) | *(packet + offset + 1);
dataset.setValidity(true, true);
measurementCd.resetTimer();
{
PoolReadGuard readSet(&dataset);
uint16_t tempRaw = ((packet[offset] & 0x0f) << 8) | packet[offset + 1];
dataset.temperatureCelcius = max1227::getTemperature(tempRaw);
offset += 2;
dataset.ain0 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain1 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 6;
dataset.ain4 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain5 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain6 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain7 = (*(packet + offset) << 8) | *(packet + offset + 1);
dataset.setValidity(true, true);
}
if (printPeriodicData) {
sif::info << "Radiation sensor temperature: " << dataset.temperatureCelcius << " °C"
<< std::dec << std::endl;
@ -204,6 +216,12 @@ ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
sif::info << "Radiation sensor ADC value channel 6: " << dataset.ain6 << std::endl;
sif::info << "Radiation sensor ADC value channel 7: " << dataset.ain7 << std::endl;
}
ReturnValue_t result =
getHkManagerHandle()->generateHousekeepingPacket(dataset.getSid(), &dataset, true);
if (result != returnvalue::OK) {
// TODO: Maybe add event?
sif::error << "Generating HK set for radiation sensor failed" << std::endl;
}
break;
}
default: {
@ -220,15 +238,18 @@ uint32_t RadiationSensorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mo
ReturnValue_t RadiationSensorHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(RAD_SENSOR::TEMPERATURE_C, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN0, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN1, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN4, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN5, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN6, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN7, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::TEMPERATURE_C, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(radSens::AIN0, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN1, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN4, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN5, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN6, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN7, new PoolEntry<uint16_t>({0}));
// It should normally not be necessary to enable this set, as a sample TM will be generated
// after a measurement. If this is still enabled, sample with double the measurement frequency
// to ensure we get all measurements.
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 20.0));
subdp::RegularHkPeriodicParams(dataset.getSid(), false, DEFAULT_MEASUREMENT_CD_MS / 2));
return returnvalue::OK;
}

View File

@ -38,13 +38,16 @@ class RadiationSensorHandler : public DeviceHandlerBase {
LocalDataPoolManager &poolManager) override;
private:
static constexpr uint32_t DEFAULT_MEASUREMENT_CD_MS = 30 * 60 * 1000;
enum class CommunicationStep { START_CONVERSION, READ_CONVERSIONS };
enum class InternalState { OFF, POWER_SWITCHING, SETUP, CONFIGURED };
bool printPeriodicData = false;
RAD_SENSOR::RadSensorDataset dataset;
static const uint8_t MAX_CMD_LEN = RAD_SENSOR::READ_SIZE;
radSens::RadSensorDataset dataset;
Countdown measurementCd = Countdown(DEFAULT_MEASUREMENT_CD_MS);
static const uint8_t MAX_CMD_LEN = radSens::READ_SIZE;
GpioIF *gpioIF = nullptr;
Stack5VHandler &stackHandler;

View File

@ -19,11 +19,16 @@ using namespace returnvalue;
ScexDeviceHandler::ScexDeviceHandler(object_id_t objectId, ScexUartReader& reader, CookieIF* cookie,
SdCardMountedIF& sdcMan)
: DeviceHandlerBase(objectId, reader.getObjectId(), cookie), sdcMan(sdcMan), reader(reader) {}
: DeviceHandlerBase(objectId, reader.getObjectId(), cookie), sdcMan(sdcMan), reader(reader) {
fsUnusableEventCd.timeOut();
}
ScexDeviceHandler::~ScexDeviceHandler() {}
void ScexDeviceHandler::doStartUp() { setMode(MODE_ON); }
void ScexDeviceHandler::doStartUp() {
filesystemChecks();
setMode(MODE_ON);
}
void ScexDeviceHandler::doShutDown() {
reader.reset();
@ -47,7 +52,7 @@ ReturnValue_t ScexDeviceHandler::buildCommandFromCommand(DeviceCommandId_t devic
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
bool tempCheck = false;
if (commandDataLen == 1) {
if (commandDataLen >= 1) {
tempCheck = commandData[0];
}
if (commandActive) {
@ -215,8 +220,12 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
}
fileNameSet = true;
} else {
ofstream out(fileName,
ofstream::binary | ofstream::app); // append
if (!sdcMan.isSdCardUsable(std::nullopt)) {
fsUnsableEvent();
return returnvalue::FAILED;
}
// Append to existing file.
ofstream out(fileName, ofstream::binary | ofstream::app);
if (out.bad()) {
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
<< std::endl;
@ -280,18 +289,8 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
}
void ScexDeviceHandler::performOperationHook() {
auto mntPrefix = sdcMan.getCurrentMountPrefix();
if (mntPrefix != nullptr) {
std::filesystem::path fullFilePath = mntPrefix;
std::error_code e;
fullFilePath /= "scex";
bool fileExists = std::filesystem::exists(fullFilePath, e);
if (not fileExists) {
bool created = std::filesystem::create_directory(fullFilePath, e);
if (not created) {
sif::error << "Could not create SCEX directory: " << e << std::endl;
}
}
if (getMode() != MODE_OFF) {
filesystemChecks();
}
uint32_t remainingMillis = finishCountdown.getRemainingMillis();
if (commandActive and finishCountdown.hasTimedOut()) {
@ -319,6 +318,33 @@ ReturnValue_t ScexDeviceHandler::initializeLocalDataPool(localpool::DataPool& lo
return OK;
}
void ScexDeviceHandler::filesystemChecks() {
auto mntPrefix = sdcMan.getCurrentMountPrefix();
if (mntPrefix == nullptr or !sdcMan.isSdCardUsable(std::nullopt)) {
sif::warning << "SCEX: Filesystem currently unavailable" << std::endl;
fsUnsableEvent();
} else {
std::filesystem::path fullFilePath = mntPrefix;
std::error_code e;
fullFilePath /= "scex";
bool fileExists = std::filesystem::exists(fullFilePath, e);
if (not fileExists) {
bool created = std::filesystem::create_directory(fullFilePath, e);
if (not created) {
sif::error << "Could not create SCEX directory: " << e << std::endl;
}
}
}
}
void ScexDeviceHandler::fsUnsableEvent() {
if (fsUnusableEventCd.isBusy()) {
return;
}
triggerEvent(scex::FS_UNUSABLE);
fsUnusableEventCd.resetTimer();
}
ReturnValue_t ScexDeviceHandler::generateNewScexFile(const char* cmdName) {
char timeString[64]{};
auto activeSd = sdcMan.getActiveSdCard();
@ -328,7 +354,8 @@ ReturnValue_t ScexDeviceHandler::generateNewScexFile(const char* cmdName) {
std::ostringstream oss;
auto prefix = sdcMan.getCurrentMountPrefix();
if (prefix == nullptr) {
if (prefix == nullptr or !sdcMan.isSdCardUsable(std::nullopt)) {
fsUnsableEvent();
return returnvalue::FAILED;
}
timeval tv;

View File

@ -42,6 +42,7 @@ class ScexDeviceHandler : public DeviceHandlerBase {
scex::Cmds currCmd = scex::Cmds::PING;
SdCardMountedIF &sdcMan;
Countdown finishCountdown = Countdown(LONG_CD);
Countdown fsUnusableEventCd = Countdown(10000);
// DeviceHandlerBase private function implementation
void doStartUp() override;
@ -49,12 +50,15 @@ class ScexDeviceHandler : public DeviceHandlerBase {
ScexHelper helper;
ScexUartReader &reader;
void fsUnsableEvent();
void performOperationHook() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
void fillCommandAndReplyMap() override;
void filesystemChecks();
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;

Some files were not shown because too many files have changed in this diff Show More