Compare commits
266 Commits
Author | SHA1 | Date | |
---|---|---|---|
d8ec121131 | |||
3e54bc9c3f | |||
4ca45f348c | |||
34a0288987 | |||
f031c46cb5 | |||
dbf627cc12 | |||
b06db0a0fc | |||
0a68b50ad7 | |||
b11ed219a2 | |||
67082a6559 | |||
36d5f8fd31 | |||
cdba7985ea | |||
38b7593900 | |||
78cc0fc52d | |||
4ed112d019 | |||
7549a24f6f | |||
d53fdf9078 | |||
67988dad64 | |||
56c5838d15 | |||
2950876ce4 | |||
a875bf55b8 | |||
a28ba4ec66 | |||
c65b402361 | |||
f5e47c6114 | |||
600921e3a0 | |||
3c38410643 | |||
2e0a685507 | |||
0ade2ae0ee | |||
b050047d9a | |||
65c231e92d | |||
5e93282662 | |||
0cabe3a9ea | |||
845548ed25 | |||
858c6c301e | |||
9825a8583f | |||
babc4f80a8 | |||
3299260653 | |||
a0e531445a | |||
5e854668b5 | |||
52c69f05e6 | |||
5dd2638241 | |||
c835b31e7f | |||
57b41701ce | |||
69bbe4ea39 | |||
f2a2c73984 | |||
85cf95d6bb | |||
08d83c158a | |||
b0e65867ee | |||
106cb1ab35 | |||
a06d90daad | |||
3cc48a4cea | |||
04178b8831 | |||
28882cc359 | |||
c9bd922711 | |||
94c736d143 | |||
c4516f53b8 | |||
f39981deca | |||
fd8317acd7 | |||
7df3308717 | |||
a76074acf5 | |||
697dcab345 | |||
104a8cab33 | |||
8d4b980c32 | |||
677457bbe7 | |||
908927ed9f | |||
4a287344f4 | |||
ae0413f7f6 | |||
01081cbb29 | |||
1d82977ca2 | |||
bc7bdfe1fe | |||
38a0c14940 | |||
3941770378 | |||
e10359077c | |||
8d1db69e0d | |||
8a2137d5d3 | |||
e47ba65550 | |||
143fb44037 | |||
18994f5e65 | |||
39a3b4aa6f | |||
2b18ab1504 | |||
83e0627548 | |||
152a3c20cf | |||
9e8880c2c5 | |||
ed8623259e | |||
69a3cb20be | |||
01b98ca091 | |||
0cd246182d | |||
9270165bf8 | |||
9aedc36e4d | |||
f5588e9c62 | |||
afbab6d3f2 | |||
6d0bd88cd9 | |||
23af9685d6 | |||
a26d71f745 | |||
8404ce237b | |||
1610bdecf9 | |||
53c88f85d5 | |||
ac514d9c19 | |||
e6f0695e1e | |||
6b37d292c6 | |||
e3677f89fe | |||
5267bfcd82 | |||
99eae0df51 | |||
73e2508025 | |||
1b2dd12e61 | |||
8585114041 | |||
c4f62842ab | |||
800ab7e87f | |||
11d9871c0a | |||
958abadd65 | |||
fba856a9a9 | |||
bc582abcb3 | |||
ba7a2c3ece | |||
a8a0299b46 | |||
f4b47a24c0 | |||
e9c5bfe324 | |||
5dcafa1de0 | |||
7522eac9eb | |||
847e3bb51d | |||
020dfa8278 | |||
389b77a092 | |||
a31f8c934a | |||
685a4caace | |||
9360dad028 | |||
8eac0b5ebd | |||
703eaaa9aa | |||
cab55c79dc | |||
62952b89b1 | |||
b205fb5269 | |||
959f37f25a | |||
789b0ff7ae | |||
601318d7eb | |||
87d622c82c | |||
fc43627abb | |||
0878f3882a | |||
6a8ddf96b8 | |||
6a2f569fc3 | |||
d2f11b1860 | |||
cf8dc9ed7d | |||
f65cf23391 | |||
b4c6965d9e | |||
78d39a3760 | |||
b58fc90879 | |||
2386944ed8 | |||
409631fb0a | |||
13b8f9b1ec | |||
d0f641abe0 | |||
9b5fc8995c | |||
23a4b08709 | |||
d1775a52aa | |||
ff6ad60eed | |||
95d220c304 | |||
65989261b0 | |||
e365e03c2a | |||
da36160f6e | |||
3f8603967c | |||
013692cc41 | |||
2f9de8c36e | |||
fcf3437410 | |||
f51656a813 | |||
bb7a616283 | |||
028f94a2f7 | |||
62ba7a1f80 | |||
9d42bb87d9 | |||
6c8eeeab31 | |||
f16d92c1b1 | |||
55a22c840c | |||
caa7c20adf | |||
6ee3fe2eef | |||
76ea3f7979 | |||
3871c8b8de | |||
e0f94039b4 | |||
a1380a6e3a | |||
795486ae6c | |||
4b1221ab99 | |||
f6f4db525c | |||
a6e24485e2 | |||
74a38dc76b | |||
5f6f85a778 | |||
6426142039 | |||
1541376701 | |||
27370fcd44 | |||
770fee0097 | |||
5903b3ef60 | |||
0bf4527e94 | |||
f695115102 | |||
a72805d137 | |||
b7c17fdf0f | |||
def7eca2f2 | |||
520b41c53b | |||
28d7dcf177 | |||
36d7852c1d | |||
5c97020087 | |||
861bee8083 | |||
3e7901f060 | |||
0301c18af2 | |||
f71972609c | |||
9c8fc84053 | |||
2153294e6f | |||
0fdc79df5e | |||
0e5a3a2f6c | |||
b81618344e | |||
d85ddcdbff | |||
092e9fa508 | |||
ba9cf5d79d | |||
4871479ed5 | |||
eb46841237 | |||
d44142ac26 | |||
f7be8ea63c | |||
3c6eb265c7 | |||
b1d2f73b01 | |||
eda1f7e212 | |||
56a4378a63 | |||
a16671762d | |||
350ed59033 | |||
096253a9a3 | |||
11e5866f31 | |||
9b8092fb09 | |||
f546df50a1 | |||
8201a4140a | |||
364342855d | |||
c688a51838 | |||
715a69db89 | |||
dc44af5b29 | |||
27f29eda40 | |||
50a62b9243 | |||
da7c450e06 | |||
a92fa31cb5 | |||
d273621419 | |||
64ec76bfb7 | |||
69525b6fd1 | |||
c1d8eda2c7 | |||
8b11302028 | |||
c1b4a1c164 | |||
58212d7081 | |||
a6e6ee053d | |||
e82777479b | |||
a51a680396 | |||
d3bf70243b | |||
4392598a67 | |||
26a9dce0a0 | |||
9d1d62aee0 | |||
bf2d97bd60 | |||
721a01409e | |||
a0d6552781 | |||
c709b2a526 | |||
5793d73ff6 | |||
c63b13fc40 | |||
224a3af6f8 | |||
131c508cae | |||
7a62624687 | |||
337717d271 | |||
9c77703ada | |||
718d067b40 | |||
37b540fd48 | |||
88db78fed9 | |||
5f3bd5c754 | |||
63275df3f0 | |||
d6f537da5f | |||
9a7779cffb | |||
0fa1bab94d | |||
29179bde0c | |||
b9a6425078 | |||
e13636167f | |||
9b849d10e9 | |||
77b7433caf |
1
.idea/cmake.xml
generated
1
.idea/cmake.xml
generated
@ -2,7 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="CMakeSharedSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" NO_GENERATOR="true" />
|
||||
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Q7S" GENERATION_OPTIONS="-DTGT_BSP="arm/q7s"" NO_GENERATOR="true">
|
||||
<ADDITIONAL_GENERATION_ENVIRONMENT>
|
||||
<envs>
|
||||
|
103
CHANGELOG.md
103
CHANGELOG.md
@ -16,10 +16,109 @@ will consitute of a breaking change warranting a new major release:
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v1.43.2] 2023-04-05
|
||||
|
||||
## Changed
|
||||
|
||||
- Adapted HK data rates to new table for LEOP SAFE mode.
|
||||
- GPS controller HK is now generated periodically as well.
|
||||
- Better mode combination checks for assembly components. This includes:
|
||||
- IMTQ assembly
|
||||
- Syrlinks assembly
|
||||
- Dual Lane Assembly
|
||||
- RWs are no longer commanded by the ACS Controller during safe mode. Instead the RW speed command
|
||||
is set to 0 as part or the `doShutDown` of the RW handler.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Dual lane assemblies: Fix handling when health states are overwritten. Also add better handling
|
||||
when some devices are permanent faulty and some are only faulty. In that case, only the faulty
|
||||
devices will be restored.
|
||||
- ACS dual lane assembly: Gyro 3 helper mode was assigned to the Gyro 2 mode.
|
||||
|
||||
# [v1.43.1] 2023-04-04
|
||||
|
||||
## Fixed
|
||||
|
||||
- Generic HK handling: Bug where HKs were generated a lot more often than required. This is the case
|
||||
if a device handler `PERFORM_OPERATION` step is performed more than once per PST cycle.
|
||||
- Syrlinks now goes to `_MODE_TO_ON` when finishing the `doStartUp` transition.
|
||||
|
||||
## Changed
|
||||
|
||||
- Doubled GS PST interval instead of scheduling everything twice.
|
||||
- Syrlinks now only has one `PERFORM_OPERATION` step, but still has two communication steps.
|
||||
- PCDU components only allow setting `NEEDS_RECOVERY`, `HEALTHY` and `EXTERNAL_CONTROL` health
|
||||
states now. TMP sensor components only allow `HEALTHY` , `EXTERNAL_CONTROL`, `FAULTY` and
|
||||
`PERMANENT_FAULTY`.
|
||||
- TCS controller now does a sanity check on the temperature values: Values below -80 C or above
|
||||
160 C are ignored.
|
||||
|
||||
# [v1.43.0] 2023-04-04
|
||||
|
||||
- q7s-package: v2.4.0
|
||||
- eive-tmtc: v2.21.0
|
||||
|
||||
## Added
|
||||
|
||||
- Version of thermal controller which performs basic control tasks.
|
||||
- PCDU handler can now command switch of the 3V3 stack (switch ID 19)
|
||||
- Set STR dev to OFF in assembly when it is faulty.
|
||||
- STR: Reset data link layer and flush RX for regular commands and before performing special
|
||||
commands to ensure consistent start state
|
||||
|
||||
## Fixed
|
||||
|
||||
- PTME was not reset after configuration changes.
|
||||
- GPS health devices: ACS board assembly not reacts to health changes.
|
||||
- STR COM helper: Reset reply size after returning a reply
|
||||
|
||||
## Changed
|
||||
|
||||
- Poll threshold configuration of the PTME IP core is now configurable via a parameter command
|
||||
and is set to 0b010 (4 polls) instead of 0b001 (1 poll) per default.
|
||||
- EIVE system fallback and COM system fallback: Perform general subsystem handling first, then
|
||||
event reception, and finally any new transition handling.
|
||||
- IMTQ MGM integration time lowered to 6 ms. This relaxes scheduling requirements a bit.
|
||||
- PCDU handler switcher HK set now has additional 3V3 switcher state HK.
|
||||
|
||||
# [v1.42.0] 2023-04-01
|
||||
|
||||
- eive-tmtc: v2.20.1
|
||||
- q7s-package: v2.3.0
|
||||
|
||||
## Changed
|
||||
|
||||
- SCEX filename updates. Also use T as the file ID / date separator between date and time.
|
||||
- COM TM store and dump handling: Introduce modes for all 4 TM VC/store tasks. The OFF mode can be
|
||||
used to disable ongoing dumps or to prevent writes to the PTME VC. This allows cleaner reset
|
||||
handling of the PTME. All 4 VC/store tasks were attached to the COM mode tree and are commanded
|
||||
as part of the COM sequence as well to ensure consistent state with the CCSDS IP core handler.
|
||||
- Added `PTME_LOCKED` boolean lock which is used to lock the PTME so it is not used by the VC tasks
|
||||
anymore. This lock will be controlled by the CCSDS IP core handler and is locked when the PTME
|
||||
needs to be reset. Examples for this are datarate changes.
|
||||
- Simulate real PCDU in PCDU dummy by remembering commandes switch change and triggering appropriate
|
||||
events. Switch feedback is still immediate.
|
||||
- GomSpace devices are polled with a doubled frequency. This speeds up power switch commanding.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Bugfix for side lane transitions of the dual lane assemblies, which only worked when the
|
||||
assembly was directly commanded.
|
||||
- Syrlinks Handler: Bugfix so transition command is only sent once.
|
||||
- SCEX file name bug: Create file name time stamp with `strftime` similarly to how it's done
|
||||
for the persistent TM store.
|
||||
|
||||
## Added
|
||||
|
||||
- Added GPS0 and GPS1 health device which are used by the ACS board assembly when deciding whether
|
||||
to change to the other side or to go to dual side directly. Setting the health devices to faulty
|
||||
should also trigger a side switch or a switch to dual mode.
|
||||
|
||||
# [v1.41.0] 2023-03-28
|
||||
|
||||
eive-tmtc: v2.20.0
|
||||
q7s-package: v2.2.0
|
||||
- eive-tmtc: v2.20.0
|
||||
- q7s-package: v2.2.0
|
||||
|
||||
## Fixed
|
||||
|
||||
|
@ -10,8 +10,8 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(OBSW_VERSION_MAJOR 1)
|
||||
set(OBSW_VERSION_MINOR 41)
|
||||
set(OBSW_VERSION_REVISION 0)
|
||||
set(OBSW_VERSION_MINOR 43)
|
||||
set(OBSW_VERSION_REVISION 2)
|
||||
|
||||
# set(CMAKE_VERBOSE TRUE)
|
||||
|
||||
@ -113,7 +113,7 @@ set(OBSW_ADD_TCS_CTRL
|
||||
1
|
||||
CACHE STRING "Add TCS controllers")
|
||||
set(OBSW_ADD_HEATERS
|
||||
${INIT_VAL}
|
||||
1
|
||||
CACHE STRING "Add TCS heaters")
|
||||
set(OBSW_ADD_PLOC_SUPERVISOR
|
||||
${INIT_VAL}
|
||||
@ -486,7 +486,8 @@ endif()
|
||||
target_link_libraries(${LIB_EIVE_MISSION} PUBLIC ${LIB_FSFW_NAME}
|
||||
${LIB_OS_NAME})
|
||||
|
||||
target_link_libraries(${LIB_DUMMIES} PUBLIC ${LIB_FSFW_NAME} ${LIB_JSON_NAME})
|
||||
target_link_libraries(${LIB_DUMMIES} PUBLIC ${LIB_EIVE_MISSION}
|
||||
${LIB_FSFW_NAME} ${LIB_JSON_NAME})
|
||||
|
||||
target_link_libraries(${OBSW_NAME} PRIVATE ${LIB_EIVE_MISSION} ${LIB_DUMMIES})
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "../mission/utility/DummySdCardManager.h"
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/platform.h"
|
||||
#include "fsfw/power/PowerSwitchIF.h"
|
||||
#include "fsfw_tests/integration/task/TestTask.h"
|
||||
|
||||
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
||||
@ -29,7 +30,7 @@
|
||||
#include <dummies/AcuDummy.h>
|
||||
#include <dummies/CoreControllerDummy.h>
|
||||
|
||||
#include "dummies/helpers.h"
|
||||
#include "dummies/helperFactory.h"
|
||||
|
||||
#ifdef PLATFORM_UNIX
|
||||
#include <fsfw_hal/linux/serial/SerialComIF.h>
|
||||
@ -67,6 +68,12 @@ void ObjectFactory::produce(void* args) {
|
||||
|
||||
auto* dummyGpioIF = new DummyGpioIF();
|
||||
auto* dummySwitcher = new DummyPowerSwitcher(objects::PCDU_HANDLER, 18, 0);
|
||||
std::vector<ReturnValue_t> switcherList;
|
||||
auto initVal = PowerSwitchIF::SWITCH_OFF;
|
||||
for (unsigned i = 0; i < 18; i++) {
|
||||
switcherList.emplace_back(initVal);
|
||||
}
|
||||
dummySwitcher->setInitialSwitcherList(switcherList);
|
||||
#ifdef PLATFORM_UNIX
|
||||
new SerialComIF(objects::UART_COM_IF);
|
||||
#if OBSW_ADD_PLOC_MPSOC == 1
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 283 translations.
|
||||
* @brief Auto-generated event translation file. Contains 284 translations.
|
||||
* @details
|
||||
* Generated on: 2023-03-28 22:20:01
|
||||
* Generated on: 2023-04-04 13:59:07
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -209,11 +209,11 @@ const char *TRANSITION_OTHER_SIDE_FAILED_STRING = "TRANSITION_OTHER_SIDE_FAILED"
|
||||
const char *NOT_ENOUGH_DEVICES_DUAL_MODE_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE";
|
||||
const char *POWER_STATE_MACHINE_TIMEOUT_STRING = "POWER_STATE_MACHINE_TIMEOUT";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING = "SIDE_SWITCH_TRANSITION_NOT_ALLOWED";
|
||||
const char *DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY_STRING = "DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY";
|
||||
const char *TRANSITION_OTHER_SIDE_FAILED_12900_STRING = "TRANSITION_OTHER_SIDE_FAILED_12900";
|
||||
const char *NOT_ENOUGH_DEVICES_DUAL_MODE_12901_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE_12901";
|
||||
const char *POWER_STATE_MACHINE_TIMEOUT_12902_STRING = "POWER_STATE_MACHINE_TIMEOUT_12902";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING =
|
||||
"SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING = "SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903";
|
||||
const char *CHILDREN_LOST_MODE_STRING = "CHILDREN_LOST_MODE";
|
||||
const char *GPS_FIX_CHANGE_STRING = "GPS_FIX_CHANGE";
|
||||
const char *CANT_GET_FIX_STRING = "CANT_GET_FIX";
|
||||
@ -270,10 +270,10 @@ const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT";
|
||||
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";
|
||||
const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING";
|
||||
const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING";
|
||||
const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING";
|
||||
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 *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";
|
||||
@ -700,6 +700,8 @@ const char *translateEvents(Event event) {
|
||||
return POWER_STATE_MACHINE_TIMEOUT_STRING;
|
||||
case (12803):
|
||||
return SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING;
|
||||
case (12804):
|
||||
return DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY_STRING;
|
||||
case (12900):
|
||||
return TRANSITION_OTHER_SIDE_FAILED_12900_STRING;
|
||||
case (12901):
|
||||
@ -820,14 +822,14 @@ const char *translateEvents(Event event) {
|
||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||
case (14102):
|
||||
return SYRLINKS_OVERHEATING_STRING;
|
||||
case (14103):
|
||||
return PLOC_OVERHEATING_STRING;
|
||||
case (14104):
|
||||
return OBC_OVERHEATING_STRING;
|
||||
case (14105):
|
||||
return HPA_OVERHEATING_STRING;
|
||||
return CAMERA_OVERHEATING_STRING;
|
||||
case (14106):
|
||||
return PLPCDU_OVERHEATING_STRING;
|
||||
return PCDU_SYSTEM_OVERHEATING_STRING;
|
||||
case (14107):
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 169 translations.
|
||||
* Generated on: 2023-03-28 22:20:01
|
||||
* Contains 171 translations.
|
||||
* Generated on: 2023-04-04 13:59:07
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
@ -38,6 +38,8 @@ const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
|
||||
const char *RW4_STRING = "RW4";
|
||||
const char *STAR_TRACKER_STRING = "STAR_TRACKER";
|
||||
const char *GPS_CONTROLLER_STRING = "GPS_CONTROLLER";
|
||||
const char *GPS_0_HEALTH_DEV_STRING = "GPS_0_HEALTH_DEV";
|
||||
const char *GPS_1_HEALTH_DEV_STRING = "GPS_1_HEALTH_DEV";
|
||||
const char *IMTQ_POLLING_STRING = "IMTQ_POLLING";
|
||||
const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER";
|
||||
const char *PCDU_HANDLER_STRING = "PCDU_HANDLER";
|
||||
@ -242,6 +244,10 @@ const char *translateObject(object_id_t object) {
|
||||
return STAR_TRACKER_STRING;
|
||||
case 0x44130045:
|
||||
return GPS_CONTROLLER_STRING;
|
||||
case 0x44130046:
|
||||
return GPS_0_HEALTH_DEV_STRING;
|
||||
case 0x44130047:
|
||||
return GPS_1_HEALTH_DEV_STRING;
|
||||
case 0x44140013:
|
||||
return IMTQ_POLLING_STRING;
|
||||
case 0x44140014:
|
||||
|
@ -156,6 +156,10 @@ void scheduling::initTasks() {
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
||||
}
|
||||
result = thermalTask->addComponent(objects::HEATER_HANDLER);
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
||||
}
|
||||
|
||||
FixedTimeslotTaskIF* pstTask = factory->createFixedTimeslotTask(
|
||||
"DUMMY_PST", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc);
|
||||
@ -193,7 +197,8 @@ void scheduling::initTasks() {
|
||||
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
||||
|
||||
PeriodicTaskIF* dummyTask = factory->createPeriodicTask(
|
||||
"DUMMY_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc);
|
||||
"DUMMY_TASK", 35, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc);
|
||||
dummyTask->addComponent(objects::THERMAL_TEMP_INSERTER);
|
||||
scheduling::scheduleTmpTempSensors(dummyTask);
|
||||
scheduling::scheduleRtdSensors(dummyTask);
|
||||
dummyTask->addComponent(objects::SUS_0_N_LOC_XFYFZM_PT_XF);
|
||||
|
@ -138,7 +138,7 @@ ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &local
|
||||
localDataPoolMap.emplace(core::TEMPERATURE, &tempPoolEntry);
|
||||
localDataPoolMap.emplace(core::PS_VOLTAGE, &psVoltageEntry);
|
||||
localDataPoolMap.emplace(core::PL_VOLTAGE, &plVoltageEntry);
|
||||
poolManager.subscribeForRegularPeriodicPacket({hkSet.getSid(), enableHkSet, 12.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({hkSet.getSid(), enableHkSet, 60.0});
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "ObjectFactory.h"
|
||||
|
||||
#include <fsfw/devicehandlers/HealthDevice.h>
|
||||
#include <fsfw/subsystem/Subsystem.h>
|
||||
#include <linux/acs/AcsBoardPolling.h>
|
||||
#include <linux/acs/GpsHyperionLinuxController.h>
|
||||
@ -19,15 +20,15 @@
|
||||
#include <mission/acs/MgmRm3100CustomHandler.h>
|
||||
#include <mission/acs/str/StarTrackerHandler.h>
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
#include <mission/com/LiveTmTask.h>
|
||||
#include <mission/com/PersistentLogTmStoreTask.h>
|
||||
#include <mission/com/PersistentSingleTmStoreTask.h>
|
||||
#include <mission/power/CspCookie.h>
|
||||
#include <mission/system/acs/ImtqAssembly.h>
|
||||
#include <mission/system/fdir/StrFdir.h>
|
||||
#include <mission/system/acs/StrAssembly.h>
|
||||
#include <mission/system/acs/StrFdir.h>
|
||||
#include <mission/system/objects/CamSwitcher.h>
|
||||
#include <mission/system/objects/StrAssembly.h>
|
||||
#include <mission/system/objects/SyrlinksAssembly.h>
|
||||
#include <mission/tmtc/LiveTmTask.h>
|
||||
#include <mission/tmtc/PersistentLogTmStoreTask.h>
|
||||
#include <mission/tmtc/PersistentSingleTmStoreTask.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/boardtest/Q7STestTask.h"
|
||||
@ -61,9 +62,9 @@
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/com/SyrlinksFdir.h"
|
||||
#include "mission/system/com/comModeTree.h"
|
||||
#include "mission/system/fdir/GomspacePowerFdir.h"
|
||||
#include "mission/system/fdir/RtdFdir.h"
|
||||
#include "mission/system/objects/TcsBoardAssembly.h"
|
||||
#include "mission/system/power/GomspacePowerFdir.h"
|
||||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
#include "mission/tmtc/tmFilters.h"
|
||||
@ -80,6 +81,7 @@ using gpio::Levels;
|
||||
#include <mission/acs/ImtqHandler.h>
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
#include <mission/com/SyrlinksHandler.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
#include <mission/payload/PayloadPcduHandler.h>
|
||||
#include <mission/payload/RadiationSensorHandler.h>
|
||||
#include <mission/payload/payloadPcduDefinitions.h>
|
||||
@ -95,7 +97,6 @@ using gpio::Levels;
|
||||
#include <mission/tcs/Max31865Definitions.h>
|
||||
#include <mission/tcs/Max31865PT1000Handler.h>
|
||||
#include <mission/tcs/Tmp1075Handler.h>
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@ -124,6 +125,7 @@ using gpio::Levels;
|
||||
|
||||
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;
|
||||
|
||||
void Factory::setStaticFrameworkObjectIds() {
|
||||
@ -358,7 +360,8 @@ void ObjectFactory::createAcsBoardGpios(GpioCookie& cookie) {
|
||||
}
|
||||
|
||||
void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF,
|
||||
SerialComIF* uartComIF, PowerSwitchIF& pwrSwitcher) {
|
||||
SerialComIF* uartComIF, PowerSwitchIF& pwrSwitcher,
|
||||
bool enableHkSets) {
|
||||
using namespace gpio;
|
||||
GpioCookie* gpioCookieAcsBoard = new GpioCookie();
|
||||
createAcsBoardGpios(*gpioCookieAcsBoard);
|
||||
@ -512,8 +515,8 @@ void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF*
|
||||
#endif
|
||||
RESET_ARGS_GNSS.gpioComIF = gpioComIF;
|
||||
RESET_ARGS_GNSS.waitPeriodMs = 100;
|
||||
auto gpsCtrl =
|
||||
new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT, debugGps);
|
||||
auto gpsCtrl = new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT,
|
||||
enableHkSets, debugGps);
|
||||
gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS);
|
||||
|
||||
ObjectFactory::createAcsBoardAssy(pwrSwitcher, assemblyChildren, gpsCtrl, gpioComIF);
|
||||
@ -588,7 +591,7 @@ void ObjectFactory::createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitc
|
||||
}
|
||||
|
||||
new SolarArrayDeploymentHandler(objects::SOLAR_ARRAY_DEPL_HANDLER, gpioIF, pwrSwitcher,
|
||||
pcdu::Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V,
|
||||
power::Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V,
|
||||
gpioIds::DEPLSA1, gpioIds::DEPLSA2, *SdCardManager::instance());
|
||||
}
|
||||
|
||||
@ -604,7 +607,7 @@ void ObjectFactory::createSyrlinksComponents(PowerSwitchIF* pwrSwitcher) {
|
||||
auto syrlinksFdir = new SyrlinksFdir(objects::SYRLINKS_HANDLER);
|
||||
auto syrlinksHandler =
|
||||
new SyrlinksHandler(objects::SYRLINKS_HANDLER, objects::SYRLINKS_COM_HANDLER,
|
||||
syrlinksUartCookie, pcdu::PDU1_CH1_SYRLINKS_12V, syrlinksFdir);
|
||||
syrlinksUartCookie, power::PDU1_CH1_SYRLINKS_12V, syrlinksFdir);
|
||||
syrlinksHandler->setPowerSwitcher(pwrSwitcher);
|
||||
syrlinksHandler->connectModeTreeParent(*syrlinksAssy);
|
||||
#if OBSW_DEBUG_SYRLINKS == 1
|
||||
@ -616,7 +619,7 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit
|
||||
using namespace gpio;
|
||||
std::stringstream consumer;
|
||||
auto* camSwitcher =
|
||||
new CamSwitcher(objects::CAM_SWITCHER, pwrSwitch, pcdu::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
new CamSwitcher(objects::CAM_SWITCHER, pwrSwitch, power::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
#if OBSW_ADD_PLOC_MPSOC == 1
|
||||
consumer << "0x" << std::hex << objects::PLOC_MPSOC_HANDLER;
|
||||
@ -649,7 +652,7 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit
|
||||
auto supvHelper = new PlocSupvUartManager(objects::PLOC_SUPERVISOR_HELPER);
|
||||
auto* supvHandler = new PlocSupervisorHandler(objects::PLOC_SUPERVISOR_HANDLER, supervisorCookie,
|
||||
Gpio(gpioIds::ENABLE_SUPV_UART, gpioComIF),
|
||||
pcdu::PDU1_CH6_PLOC_12V, *supvHelper);
|
||||
power::PDU1_CH6_PLOC_12V, *supvHelper);
|
||||
supvHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
#endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */
|
||||
static_cast<void>(consumer);
|
||||
@ -726,7 +729,7 @@ void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF,
|
||||
rws[idx] = rwHandler;
|
||||
}
|
||||
|
||||
createRwAssy(*pwrSwitcher, pcdu::Switches::PDU2_CH2_RW_5V, rws, rwIds);
|
||||
createRwAssy(*pwrSwitcher, power::Switches::PDU2_CH2_RW_5V, rws, rwIds);
|
||||
#endif /* OBSW_ADD_RW == 1 */
|
||||
}
|
||||
|
||||
@ -751,10 +754,8 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
|
||||
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);
|
||||
// Initialise to low and then pull high to do a PTME reset, which puts the PTME in reset
|
||||
// state. It will be put out of reset in the CCSDS handler initialize function.
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PTME_RESETN, "PTME RESETN",
|
||||
gpio::Direction::OUT, gpio::Levels::LOW);
|
||||
gpio::Direction::OUT, gpio::Levels::HIGH);
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::PTME_RESETN, gpio);
|
||||
gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs");
|
||||
|
||||
@ -788,34 +789,42 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
|
||||
|
||||
*args.ipCoreHandler =
|
||||
new CcsdsIpCoreHandler(objects::CCSDS_HANDLER, objects::CCSDS_PACKET_DISTRIBUTOR, *ptmeConfig,
|
||||
LINK_STATE, &args.gpioComIF, gpios);
|
||||
LINK_STATE, &args.gpioComIF, gpios, PTME_LOCKED);
|
||||
// This VC will receive all live TM
|
||||
auto* vcWithQueue =
|
||||
new VirtualChannelWithQueue(objects::PTME_VC0_LIVE_TM, ccsds::VC0, "PTME VC0 LIVE TM", *ptme,
|
||||
LINK_STATE, args.tmStore, 500);
|
||||
args.liveDestination = vcWithQueue;
|
||||
new LiveTmTask(objects::LIVE_TM_TASK, args.pusFunnel, args.cfdpFunnel, *vcWithQueue);
|
||||
auto* liveTask = new LiveTmTask(objects::LIVE_TM_TASK, args.pusFunnel, args.cfdpFunnel,
|
||||
*vcWithQueue, PTME_LOCKED);
|
||||
liveTask->connectModeTreeParent(satsystem::com::SUBSYSTEM);
|
||||
|
||||
// Set up log store.
|
||||
auto* vc = new VirtualChannel(objects::PTME_VC1_LOG_TM, ccsds::VC1, "PTME VC1 LOG TM", *ptme,
|
||||
LINK_STATE);
|
||||
LogStores logStores(args.stores);
|
||||
// Core task which handles the LOG store and takes care of dumping it as TM using a VC directly
|
||||
new PersistentLogTmStoreTask(objects::LOG_STORE_AND_TM_TASK, args.ipcStore, logStores, *vc,
|
||||
*SdCardManager::instance());
|
||||
auto* logStore =
|
||||
new PersistentLogTmStoreTask(objects::LOG_STORE_AND_TM_TASK, args.ipcStore, logStores, *vc,
|
||||
*SdCardManager::instance(), PTME_LOCKED);
|
||||
logStore->connectModeTreeParent(satsystem::com::SUBSYSTEM);
|
||||
|
||||
vc = new VirtualChannel(objects::PTME_VC2_HK_TM, ccsds::VC2, "PTME VC2 HK TM", *ptme, LINK_STATE);
|
||||
// Core task which handles the HK store and takes care of dumping it as TM using a VC directly
|
||||
new PersistentSingleTmStoreTask(objects::HK_STORE_AND_TM_TASK, args.ipcStore,
|
||||
*args.stores.hkStore, *vc, persTmStore::DUMP_HK_STORE_DONE,
|
||||
persTmStore::DUMP_HK_STORE_DONE, *SdCardManager::instance());
|
||||
auto* hkStore = new PersistentSingleTmStoreTask(
|
||||
objects::HK_STORE_AND_TM_TASK, args.ipcStore, *args.stores.hkStore, *vc,
|
||||
persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_STORE_DONE, *SdCardManager::instance(),
|
||||
PTME_LOCKED);
|
||||
hkStore->connectModeTreeParent(satsystem::com::SUBSYSTEM);
|
||||
|
||||
vc = new VirtualChannel(objects::PTME_VC3_CFDP_TM, ccsds::VC3, "PTME VC3 CFDP TM", *ptme,
|
||||
LINK_STATE);
|
||||
// Core task which handles the CFDP store and takes care of dumping it as TM using a VC directly
|
||||
new PersistentSingleTmStoreTask(objects::CFDP_STORE_AND_TM_TASK, args.ipcStore,
|
||||
*args.stores.cfdpStore, *vc, persTmStore::DUMP_CFDP_STORE_DONE,
|
||||
persTmStore::DUMP_CFDP_CANCELLED, *SdCardManager::instance());
|
||||
auto* cfdpTask = new PersistentSingleTmStoreTask(
|
||||
objects::CFDP_STORE_AND_TM_TASK, args.ipcStore, *args.stores.cfdpStore, *vc,
|
||||
persTmStore::DUMP_CFDP_STORE_DONE, persTmStore::DUMP_CFDP_CANCELLED,
|
||||
*SdCardManager::instance(), PTME_LOCKED);
|
||||
cfdpTask->connectModeTreeParent(satsystem::com::SUBSYSTEM);
|
||||
|
||||
ReturnValue_t result = (*args.ipCoreHandler)->connectModeTreeParent(satsystem::com::SUBSYSTEM);
|
||||
if (result != returnvalue::OK) {
|
||||
@ -958,7 +967,7 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
|
||||
auto strFdir = new StrFdir(objects::STAR_TRACKER);
|
||||
auto starTracker =
|
||||
new StarTrackerHandler(objects::STAR_TRACKER, objects::STR_COM_IF, starTrackerCookie,
|
||||
paramJsonFile, strComIF, pcdu::PDU1_CH2_STAR_TRACKER_5V);
|
||||
paramJsonFile, strComIF, power::PDU1_CH2_STAR_TRACKER_5V);
|
||||
starTracker->setPowerSwitcher(pwrSwitcher);
|
||||
starTracker->connectModeTreeParent(*strAssy);
|
||||
starTracker->setCustomFdir(strFdir);
|
||||
@ -971,7 +980,7 @@ void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enable
|
||||
new ImtqPollingTask(objects::IMTQ_POLLING, I2C_FATAL_ERRORS);
|
||||
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE);
|
||||
auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie,
|
||||
pcdu::Switches::PDU1_CH3_MGT_5V, enableHkSets);
|
||||
power::Switches::PDU1_CH3_MGT_5V, enableHkSets);
|
||||
imtqHandler->enableThermalModule(ThermalStateCfg());
|
||||
imtqHandler->setPowerSwitcher(pwrSwitcher);
|
||||
imtqHandler->connectModeTreeParent(*imtqAssy);
|
||||
|
@ -4,11 +4,11 @@
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <mission/com/CcsdsIpCoreHandler.h>
|
||||
#include <mission/com/PersistentLogTmStoreTask.h>
|
||||
#include <mission/genericFactory.h>
|
||||
#include <mission/system/objects/Stack5VHandler.h>
|
||||
#include <mission/tcs/HeaterHandler.h>
|
||||
#include <mission/tmtc/CfdpTmFunnel.h>
|
||||
#include <mission/tmtc/PersistentLogTmStoreTask.h>
|
||||
#include <mission/tmtc/PusTmFunnel.h>
|
||||
|
||||
#include <atomic>
|
||||
@ -24,6 +24,7 @@ class AcsBoardAssembly;
|
||||
class GpioIF;
|
||||
|
||||
extern std::atomic_uint16_t I2C_FATAL_ERRORS;
|
||||
extern std::atomic_bool PTME_LOCKED;
|
||||
|
||||
namespace ObjectFactory {
|
||||
|
||||
@ -61,7 +62,7 @@ void createTmpComponents();
|
||||
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
|
||||
void createAcsBoardGpios(GpioCookie& cookie);
|
||||
void createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF, SerialComIF* uartComIF,
|
||||
PowerSwitchIF& pwrSwitcher);
|
||||
PowerSwitchIF& pwrSwitcher, bool enableHkSets);
|
||||
void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable,
|
||||
HeaterHandler*& heaterHandler);
|
||||
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets);
|
||||
|
@ -291,6 +291,14 @@ void scheduling::initTasks() {
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("STR_ASSY", objects::STR_ASSY);
|
||||
}
|
||||
result = acsSysTask->addComponent(objects::GPS_0_HEALTH_DEV);
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("GPS_0_HEALTH_DEV", objects::GPS_0_HEALTH_DEV);
|
||||
}
|
||||
result = acsSysTask->addComponent(objects::GPS_1_HEALTH_DEV);
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("GPS_1_HEALTH_DEV", objects::GPS_1_HEALTH_DEV);
|
||||
}
|
||||
|
||||
PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask(
|
||||
"TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING);
|
||||
@ -530,7 +538,7 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
|
||||
|
||||
FixedTimeslotTaskIF* gomSpacePstTask =
|
||||
factory.createFixedTimeslotTask("GS_PST_TASK", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4,
|
||||
0.5, missedDeadlineFunc, &RR_SCHEDULING);
|
||||
0.25, missedDeadlineFunc, &RR_SCHEDULING);
|
||||
result = pst::pstGompaceCan(gomSpacePstTask);
|
||||
if (result != returnvalue::OK) {
|
||||
if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include "bsp_q7s/core/ObjectFactory.h"
|
||||
#include "busConf.h"
|
||||
#include "devConf.h"
|
||||
#include "dummies/helpers.h"
|
||||
#include "dummies/helperFactory.h"
|
||||
#include "eive/objects.h"
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
#include "linux/ObjectFactory.h"
|
||||
@ -137,8 +137,8 @@ void ObjectFactory::produce(void* args) {
|
||||
pcdu::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V);
|
||||
#endif
|
||||
createAcsController(true, enableHkSets);
|
||||
HeaterHandler* heaterHandler = nullptr;
|
||||
ObjectFactory::createGenericHeaterComponents(*gpioComIF, *pwrSwitcher, heaterHandler);
|
||||
HeaterHandler* heaterHandler;
|
||||
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
|
||||
createThermalController(*heaterHandler);
|
||||
satsystem::init();
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ void ObjectFactory::produce(void* args) {
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_ACS_BOARD == 1
|
||||
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher);
|
||||
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true);
|
||||
#endif
|
||||
HeaterHandler* heaterHandler;
|
||||
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
|
||||
@ -97,7 +97,7 @@ void ObjectFactory::produce(void* args) {
|
||||
|
||||
#if OBSW_ADD_SCEX_DEVICE == 1
|
||||
createScexComponents(q7s::UART_SCEX_DEV, pwrSwitcher, *SdCardManager::instance(), false,
|
||||
pcdu::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V);
|
||||
power::Switches::PDU1_CH5_SOLAR_CELL_EXP_5V);
|
||||
#endif
|
||||
/* Test Task */
|
||||
#if OBSW_ADD_TEST_CODE == 1
|
||||
|
@ -15,6 +15,9 @@ static constexpr char OBSW_VERSION_FILE_NAME[] = "obsw_version.txt";
|
||||
static constexpr char OBSW_PATH[] = "/usr/bin/eive-obsw";
|
||||
static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt";
|
||||
|
||||
// ISO8601 timestamp.
|
||||
static constexpr char FILE_DATE_FORMAT[] = "%FT%H%M%SZ";
|
||||
|
||||
static constexpr uint16_t EIVE_PUS_APID = 0x65;
|
||||
static constexpr uint16_t EIVE_CFDP_APID = 0x66;
|
||||
static constexpr uint16_t EIVE_LOCAL_CFDP_ENTITY_ID = EIVE_CFDP_APID;
|
||||
|
@ -43,6 +43,8 @@ enum commonObjects : uint32_t {
|
||||
RW4 = 0x44120350,
|
||||
STAR_TRACKER = 0x44130001,
|
||||
GPS_CONTROLLER = 0x44130045,
|
||||
GPS_0_HEALTH_DEV = 0x44130046,
|
||||
GPS_1_HEALTH_DEV = 0x44130047,
|
||||
|
||||
IMTQ_POLLING = 0x44140013,
|
||||
IMTQ_HANDLER = 0x44140014,
|
||||
|
@ -26,6 +26,6 @@ target_sources(
|
||||
CoreControllerDummy.cpp
|
||||
PlocMpsocDummy.cpp
|
||||
PlocSupervisorDummy.cpp
|
||||
helpers.cpp
|
||||
helperFactory.cpp
|
||||
MgmRm3100Dummy.cpp
|
||||
Tmp1075Dummy.cpp)
|
||||
|
@ -46,7 +46,7 @@ ReturnValue_t GyroAdisDummy::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(adis1650x::ACCELERATION_X, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(adis1650x::ACCELERATION_Y, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(adis1650x::ACCELERATION_Z, new PoolEntry<double>({0.0}));
|
||||
localDataPoolMap.emplace(adis1650x::TEMPERATURE, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(adis1650x::TEMPERATURE, new PoolEntry<float>({10.0}, true));
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "Max31865Dummy.h"
|
||||
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
Max31865Dummy::Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
@ -28,15 +30,20 @@ ReturnValue_t Max31865Dummy::initializeLocalDataPool(localpool::DataPool &localD
|
||||
LocalDataPoolManager &poolManager) {
|
||||
using namespace MAX31865;
|
||||
localDataPoolMap.emplace(static_cast<lp_id_t>(PoolIds::RTD_VALUE), new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(static_cast<lp_id_t>(PoolIds::TEMPERATURE_C), new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(static_cast<lp_id_t>(PoolIds::TEMPERATURE_C),
|
||||
new PoolEntry<float>({10.0}, true));
|
||||
localDataPoolMap.emplace(static_cast<lp_id_t>(PoolIds::LAST_FAULT_BYTE),
|
||||
new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(static_cast<lp_id_t>(PoolIds::FAULT_BYTE), new PoolEntry<uint8_t>({0}));
|
||||
return OK;
|
||||
}
|
||||
|
||||
void Max31865Dummy::setTemperature(float temperature) {
|
||||
set.temperatureCelcius.value = temperature;
|
||||
void Max31865Dummy::setTemperature(float temperature, bool valid) {
|
||||
PoolReadGuard pg(&set);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
set.temperatureCelcius.value = temperature;
|
||||
set.setValidity(valid, true);
|
||||
}
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *Max31865Dummy::getDataSetHandle(sid_t sid) { return &set; }
|
||||
|
@ -10,7 +10,7 @@ class Max31865Dummy : public DeviceHandlerBase {
|
||||
Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
Max31865Dummy(object_id_t objectId, CookieIF *comCookie);
|
||||
|
||||
void setTemperature(float temperature);
|
||||
void setTemperature(float temperature, bool setValid);
|
||||
|
||||
private:
|
||||
MAX31865::PrimarySet set;
|
||||
|
@ -40,7 +40,7 @@ uint32_t MgmLIS3MDLDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
|
||||
|
||||
ReturnValue_t MgmLIS3MDLDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, new PoolEntry<float>({10.0}, true));
|
||||
localDataPoolMap.emplace(mgmLis3::FIELD_STRENGTHS,
|
||||
new PoolEntry<float>({1.02, 0.56, -0.78}, true));
|
||||
return returnvalue::OK;
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <mission/power/gsDefs.h>
|
||||
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
|
||||
P60DockDummy::P60DockDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie) {}
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
|
||||
#include "mission/power/gsDefs.h"
|
||||
|
||||
class P60DockDummy : public DeviceHandlerBase {
|
||||
public:
|
||||
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
||||
@ -15,6 +17,8 @@ class P60DockDummy : public DeviceHandlerBase {
|
||||
virtual ~P60DockDummy();
|
||||
|
||||
protected:
|
||||
lp_var_t<float> temp1 = lp_var_t<float>(this, P60Dock::pool::P60DOCK_TEMPERATURE_1);
|
||||
lp_var_t<float> temp2 = lp_var_t<float>(this, P60Dock::pool::P60DOCK_TEMPERATURE_2);
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
|
@ -2,8 +2,12 @@
|
||||
|
||||
#include <mission/power/gsDefs.h>
|
||||
|
||||
#include "mission/power/defs.h"
|
||||
|
||||
PcduHandlerDummy::PcduHandlerDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie), dummySwitcher(objectId, 18, 18, false) {}
|
||||
: DeviceHandlerBase(objectId, comif, comCookie), dummySwitcher(objectId, 18, 18, false) {
|
||||
switcherLock = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
PcduHandlerDummy::~PcduHandlerDummy() {}
|
||||
|
||||
@ -44,6 +48,17 @@ ReturnValue_t PcduHandlerDummy::initializeLocalDataPool(localpool::DataPool &loc
|
||||
}
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
|
||||
if (onOff == SWITCH_ON) {
|
||||
triggerEvent(power::SWITCH_CMD_SENT, true, switchNr);
|
||||
} else {
|
||||
triggerEvent(power::SWITCH_CMD_SENT, false, switchNr);
|
||||
}
|
||||
{
|
||||
MutexGuard mg(switcherLock);
|
||||
// To simulate a real PCDU, remember the switch change to trigger a SWITCH_HAS_CHANGED event
|
||||
// at a later stage.
|
||||
switchChangeArray[switchNr] = true;
|
||||
}
|
||||
return dummySwitcher.sendSwitchCommand(switchNr, onOff);
|
||||
}
|
||||
|
||||
@ -60,3 +75,22 @@ ReturnValue_t PcduHandlerDummy::getFuseState(uint8_t fuseNr) const {
|
||||
}
|
||||
|
||||
uint32_t PcduHandlerDummy::getSwitchDelayMs(void) const { return dummySwitcher.getSwitchDelayMs(); }
|
||||
|
||||
void PcduHandlerDummy::performOperationHook() {
|
||||
SwitcherBoolArray switcherChangeCopy{};
|
||||
{
|
||||
MutexGuard mg(switcherLock);
|
||||
std::memcpy(switcherChangeCopy.data(), switchChangeArray.data(), switchChangeArray.size());
|
||||
}
|
||||
for (uint8_t idx = 0; idx < switcherChangeCopy.size(); idx++) {
|
||||
if (switcherChangeCopy[idx]) {
|
||||
if (dummySwitcher.getSwitchState(idx) == PowerSwitchIF::SWITCH_ON) {
|
||||
triggerEvent(power::SWITCH_HAS_CHANGED, true, idx);
|
||||
} else {
|
||||
triggerEvent(power::SWITCH_HAS_CHANGED, false, idx);
|
||||
}
|
||||
MutexGuard mg(switcherLock);
|
||||
switchChangeArray[idx] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,12 @@ class PcduHandlerDummy : public DeviceHandlerBase, public PowerSwitchIF {
|
||||
virtual ~PcduHandlerDummy();
|
||||
|
||||
protected:
|
||||
MutexIF *switcherLock;
|
||||
DummyPowerSwitcher dummySwitcher;
|
||||
using SwitcherBoolArray = std::array<bool, 18>;
|
||||
|
||||
SwitcherBoolArray switchChangeArray{};
|
||||
void performOperationHook() override;
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
|
||||
#include "mission/power/defs.h"
|
||||
|
||||
class PlocMpsocDummy : public DeviceHandlerBase {
|
||||
public:
|
||||
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "PlocSupervisorDummy.h"
|
||||
|
||||
PlocSupervisorDummy::PlocSupervisorDummy(object_id_t objectId, object_id_t comif,
|
||||
CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie) {}
|
||||
CookieIF *comCookie, PowerSwitchIF &pwrSwitcher)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie) {
|
||||
setPowerSwitcher(&pwrSwitcher);
|
||||
}
|
||||
|
||||
PlocSupervisorDummy::~PlocSupervisorDummy() {}
|
||||
|
||||
@ -42,3 +44,10 @@ ReturnValue_t PlocSupervisorDummy::initializeLocalDataPool(localpool::DataPool &
|
||||
LocalDataPoolManager &poolManager) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PlocSupervisorDummy::getSwitches(const uint8_t **switches,
|
||||
uint8_t *numberOfSwitches) {
|
||||
*numberOfSwitches = 1;
|
||||
*switches = reinterpret_cast<const uint8_t *>(&switchId);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <mission/power/defs.h>
|
||||
|
||||
class PlocSupervisorDummy : public DeviceHandlerBase {
|
||||
public:
|
||||
@ -10,10 +11,13 @@ class PlocSupervisorDummy : public DeviceHandlerBase {
|
||||
static const uint8_t SIMPLE_COMMAND_DATA = 1;
|
||||
static const uint8_t PERIODIC_REPLY_DATA = 2;
|
||||
|
||||
PlocSupervisorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
PlocSupervisorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
|
||||
PowerSwitchIF &pwrSwitcher);
|
||||
virtual ~PlocSupervisorDummy();
|
||||
|
||||
protected:
|
||||
const power::Switches switchId = power::Switches::PDU1_CH6_PLOC_12V;
|
||||
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
@ -27,4 +31,5 @@ class PlocSupervisorDummy : public DeviceHandlerBase {
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
|
||||
};
|
||||
|
@ -40,7 +40,7 @@ uint32_t StarTrackerDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo)
|
||||
|
||||
ReturnValue_t StarTrackerDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(startracker::MCU_TEMPERATURE, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(startracker::MCU_TEMPERATURE, new PoolEntry<float>({10.0}, true));
|
||||
|
||||
localDataPoolMap.emplace(startracker::TICKS_SOLUTION_SET, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::TIME_SOLUTION_SET, new PoolEntry<uint64_t>({0}));
|
||||
|
@ -40,7 +40,7 @@ uint32_t SyrlinksDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { r
|
||||
|
||||
ReturnValue_t SyrlinksDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(syrlinks::TEMP_BASEBAND_BOARD, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(syrlinks::TEMP_POWER_AMPLIFIER, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(syrlinks::TEMP_BASEBAND_BOARD, new PoolEntry<float>({10}, true));
|
||||
localDataPoolMap.emplace(syrlinks::TEMP_POWER_AMPLIFIER, new PoolEntry<float>({10}, true));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
|
||||
Max31865DummyMap tempSensorDummies_,
|
||||
Tmp1075DummyMap tempTmpSensorDummies_)
|
||||
: SystemObject(objects::THERMAL_TEMP_INSERTER),
|
||||
: SystemObject(objectId),
|
||||
max31865DummyMap(std::move(tempSensorDummies_)),
|
||||
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
|
||||
|
||||
@ -22,6 +22,32 @@ ReturnValue_t TemperatureSensorInserter::initialize() {
|
||||
}
|
||||
|
||||
ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
||||
// TODO: deviceSensors
|
||||
if (not tempsWereInitialized) {
|
||||
for (auto& rtdDummy : max31865DummyMap) {
|
||||
rtdDummy.second->setTemperature(10, true);
|
||||
}
|
||||
for (auto& tmpDummy : tmp1075DummyMap) {
|
||||
tmpDummy.second->setTemperature(10, true);
|
||||
}
|
||||
tempsWereInitialized = true;
|
||||
}
|
||||
|
||||
if (cycles == 10) {
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true);
|
||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(-100, true);
|
||||
}
|
||||
|
||||
if (cycles == 35) {
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(0, true);
|
||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true);
|
||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-100, true);
|
||||
}
|
||||
if (cycles == 60) {
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true);
|
||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true);
|
||||
}
|
||||
|
||||
/*
|
||||
ReturnValue_t result = max31865PlocHeatspreaderSet.read();
|
||||
if (result != returnvalue::OK) {
|
||||
@ -36,5 +62,7 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
||||
}
|
||||
max31865PlocHeatspreaderSet.commit();
|
||||
*/
|
||||
cycles++;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
ReturnValue_t TemperatureSensorInserter::initializeAfterTaskCreation() { return returnvalue::OK; }
|
||||
|
@ -14,6 +14,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
||||
Tmp1075DummyMap tempTmpSensorDummies_);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
protected:
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
@ -23,6 +24,8 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
||||
Tmp1075DummyMap tmp1075DummyMap;
|
||||
enum TestCase { NONE = 0, COOL_SYRLINKS = 1 };
|
||||
int iteration = 0;
|
||||
uint32_t cycles = 0;
|
||||
bool tempsWereInitialized = false;
|
||||
bool performTest = false;
|
||||
TestCase testCase = TestCase::NONE;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "Tmp1075Dummy.h"
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <mission/tcs/Tmp1075Definitions.h>
|
||||
|
||||
using namespace returnvalue;
|
||||
@ -26,11 +27,16 @@ ReturnValue_t Tmp1075Dummy::scanForReply(const uint8_t *start, size_t len,
|
||||
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>({0.0}));
|
||||
localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry<float>({10.0}, true));
|
||||
return OK;
|
||||
}
|
||||
LocalPoolDataSetBase *Tmp1075Dummy::getDataSetHandle(sid_t sid) { return &set; }
|
||||
|
@ -8,6 +8,7 @@
|
||||
class Tmp1075Dummy : public DeviceHandlerBase {
|
||||
public:
|
||||
Tmp1075Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
void setTemperature(float temperature, bool setValid);
|
||||
|
||||
private:
|
||||
TMP1075::Tmp1075Dataset set;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "helpers.h"
|
||||
#include "helperFactory.h"
|
||||
|
||||
#include <dummies/AcuDummy.h>
|
||||
#include <dummies/BpxDummy.h>
|
||||
@ -24,11 +24,12 @@
|
||||
#include <dummies/StarTrackerDummy.h>
|
||||
#include <dummies/SusDummy.h>
|
||||
#include <dummies/SyrlinksDummy.h>
|
||||
#include <fsfw/devicehandlers/HealthDevice.h>
|
||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||
#include <mission/power/gsDefs.h>
|
||||
#include <mission/system/acs/ImtqAssembly.h>
|
||||
#include <mission/system/acs/StrAssembly.h>
|
||||
#include <mission/system/objects/CamSwitcher.h>
|
||||
#include <mission/system/objects/StrAssembly.h>
|
||||
#include <mission/system/objects/TcsBoardAssembly.h>
|
||||
|
||||
#include "TemperatureSensorInserter.h"
|
||||
@ -56,7 +57,7 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
rws[1] = new RwDummy(objects::RW2, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
rws[2] = new RwDummy(objects::RW3, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
rws[3] = new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
ObjectFactory::createRwAssy(pwrSwitcher, pcdu::Switches::PDU2_CH2_RW_5V, rws, rwIds);
|
||||
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);
|
||||
@ -210,7 +211,7 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
}
|
||||
}
|
||||
auto* camSwitcher =
|
||||
new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher, pcdu::Switches::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
new CamSwitcher(objects::CAM_SWITCHER, pwrSwitcher, 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);
|
||||
@ -221,8 +222,8 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
auto* plocMpsocDummy =
|
||||
new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
plocMpsocDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
auto* plocSupervisorDummy = new PlocSupervisorDummy(objects::PLOC_SUPERVISOR_HANDLER,
|
||||
objects::DUMMY_COM_IF, comCookieDummy);
|
||||
auto* plocSupervisorDummy = new PlocSupervisorDummy(
|
||||
objects::PLOC_SUPERVISOR_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, pwrSwitcher);
|
||||
plocSupervisorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
}
|
2
fsfw
2
fsfw
Submodule fsfw updated: 4f632e2c68...6650c293da
@ -203,6 +203,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12801;0x3201;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;No description;mission/system/acs/AcsBoardAssembly.h
|
||||
12802;0x3202;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/AcsBoardAssembly.h
|
||||
12803;0x3203;SIDE_SWITCH_TRANSITION_NOT_ALLOWED;LOW;Not implemented, would increase already high complexity. Operator should instead command the assembly off first and then command the assembly on into the desired mode/submode combination;mission/system/acs/AcsBoardAssembly.h
|
||||
12804;0x3204;DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY;MEDIUM;This is triggered when the assembly would have normally switched the board side, but the GPS device of the other side was marked faulty. P1: Current submode.;mission/system/acs/AcsBoardAssembly.h
|
||||
12900;0x3264;TRANSITION_OTHER_SIDE_FAILED;HIGH;No description;mission/system/acs/SusAssembly.h
|
||||
12901;0x3265;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;No description;mission/system/acs/SusAssembly.h
|
||||
12902;0x3266;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/SusAssembly.h
|
||||
@ -260,13 +261,13 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;bsp_q7s/core/CoreController.h
|
||||
14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;bsp_q7s/core/CoreController.h
|
||||
14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.h
|
||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.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
|
||||
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
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
|
||||
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
|
||||
|
|
@ -30,6 +30,8 @@
|
||||
0x44120350;RW4
|
||||
0x44130001;STAR_TRACKER
|
||||
0x44130045;GPS_CONTROLLER
|
||||
0x44130046;GPS_0_HEALTH_DEV
|
||||
0x44130047;GPS_1_HEALTH_DEV
|
||||
0x44140013;IMTQ_POLLING
|
||||
0x44140014;IMTQ_HANDLER
|
||||
0x442000A1;PCDU_HANDLER
|
||||
|
|
@ -440,7 +440,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x5106;IMTQ_InternalProcessingError;No description;6;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5107;IMTQ_RejectedWithoutReason;No description;7;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5108;IMTQ_CmdErrUnknown;No description;8;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x51a7;IMTQ_UnexpectedSelfTestReply;The status reply to a self test command was received but no self test command has been sent. This should normally never happen.;167;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5109;IMTQ_StartupCfgError;No description;9;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x510a;IMTQ_UnexpectedSelfTestReply;The status reply to a self test command was received but no self test command has been sent. This should normally never happen.;10;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x52b0;RWHA_SpiWriteFailure;No description;176;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x52b1;RWHA_SpiReadFailure;Used by the spi send function to tell a failing read call;177;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x52b2;RWHA_MissingStartSign;Can be used by the HDLC decoding mechanism to inform about a missing start sign 0x7E;178;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
|
|
@ -203,6 +203,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12801;0x3201;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;No description;mission/system/acs/AcsBoardAssembly.h
|
||||
12802;0x3202;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/AcsBoardAssembly.h
|
||||
12803;0x3203;SIDE_SWITCH_TRANSITION_NOT_ALLOWED;LOW;Not implemented, would increase already high complexity. Operator should instead command the assembly off first and then command the assembly on into the desired mode/submode combination;mission/system/acs/AcsBoardAssembly.h
|
||||
12804;0x3204;DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY;MEDIUM;This is triggered when the assembly would have normally switched the board side, but the GPS device of the other side was marked faulty. P1: Current submode.;mission/system/acs/AcsBoardAssembly.h
|
||||
12900;0x3264;TRANSITION_OTHER_SIDE_FAILED;HIGH;No description;mission/system/acs/SusAssembly.h
|
||||
12901;0x3265;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;No description;mission/system/acs/SusAssembly.h
|
||||
12902;0x3266;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/SusAssembly.h
|
||||
@ -260,13 +261,13 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;bsp_q7s/core/CoreController.h
|
||||
14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;bsp_q7s/core/CoreController.h
|
||||
14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.h
|
||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/ThermalController.h
|
||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14103;0x3717;PLOC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14105;0x3719;HPA_OVERHEATING;HIGH;No description;mission/controller/ThermalController.h
|
||||
14106;0x371a;PLPCDU_OVERHEATING;HIGH;No description;mission/controller/ThermalController.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
|
||||
14104;0x3718;OBC_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
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
|
||||
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
|
||||
|
|
@ -29,6 +29,8 @@
|
||||
0x44120350;RW4
|
||||
0x44130001;STAR_TRACKER
|
||||
0x44130045;GPS_CONTROLLER
|
||||
0x44130046;GPS_0_HEALTH_DEV
|
||||
0x44130047;GPS_1_HEALTH_DEV
|
||||
0x44140013;IMTQ_POLLING
|
||||
0x44140014;IMTQ_HANDLER
|
||||
0x442000A1;PCDU_HANDLER
|
||||
|
|
@ -440,7 +440,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x5106;IMTQ_InternalProcessingError;No description;6;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5107;IMTQ_RejectedWithoutReason;No description;7;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5108;IMTQ_CmdErrUnknown;No description;8;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x51a7;IMTQ_UnexpectedSelfTestReply;The status reply to a self test command was received but no self test command has been sent. This should normally never happen.;167;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x5109;IMTQ_StartupCfgError;No description;9;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x510a;IMTQ_UnexpectedSelfTestReply;The status reply to a self test command was received but no self test command has been sent. This should normally never happen.;10;IMTQ_HANDLER;mission/acs/imtqHelpers.h
|
||||
0x52b0;RWHA_SpiWriteFailure;No description;176;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x52b1;RWHA_SpiReadFailure;Used by the spi send function to tell a failing read call;177;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
0x52b2;RWHA_MissingStartSign;Can be used by the HDLC decoding mechanism to inform about a missing start sign 0x7E;178;RW_HANDLER;mission/acs/rwHelpers.h
|
||||
|
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 283 translations.
|
||||
* @brief Auto-generated event translation file. Contains 284 translations.
|
||||
* @details
|
||||
* Generated on: 2023-03-28 22:20:01
|
||||
* Generated on: 2023-04-04 13:59:07
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -209,6 +209,7 @@ const char *TRANSITION_OTHER_SIDE_FAILED_STRING = "TRANSITION_OTHER_SIDE_FAILED"
|
||||
const char *NOT_ENOUGH_DEVICES_DUAL_MODE_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE";
|
||||
const char *POWER_STATE_MACHINE_TIMEOUT_STRING = "POWER_STATE_MACHINE_TIMEOUT";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING = "SIDE_SWITCH_TRANSITION_NOT_ALLOWED";
|
||||
const char *DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY_STRING = "DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY";
|
||||
const char *TRANSITION_OTHER_SIDE_FAILED_12900_STRING = "TRANSITION_OTHER_SIDE_FAILED_12900";
|
||||
const char *NOT_ENOUGH_DEVICES_DUAL_MODE_12901_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE_12901";
|
||||
const char *POWER_STATE_MACHINE_TIMEOUT_12902_STRING = "POWER_STATE_MACHINE_TIMEOUT_12902";
|
||||
@ -269,10 +270,10 @@ const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT";
|
||||
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";
|
||||
const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING";
|
||||
const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING";
|
||||
const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING";
|
||||
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 *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";
|
||||
@ -699,6 +700,8 @@ const char *translateEvents(Event event) {
|
||||
return POWER_STATE_MACHINE_TIMEOUT_STRING;
|
||||
case (12803):
|
||||
return SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING;
|
||||
case (12804):
|
||||
return DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY_STRING;
|
||||
case (12900):
|
||||
return TRANSITION_OTHER_SIDE_FAILED_12900_STRING;
|
||||
case (12901):
|
||||
@ -819,14 +822,14 @@ const char *translateEvents(Event event) {
|
||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||
case (14102):
|
||||
return SYRLINKS_OVERHEATING_STRING;
|
||||
case (14103):
|
||||
return PLOC_OVERHEATING_STRING;
|
||||
case (14104):
|
||||
return OBC_OVERHEATING_STRING;
|
||||
case (14105):
|
||||
return HPA_OVERHEATING_STRING;
|
||||
return CAMERA_OVERHEATING_STRING;
|
||||
case (14106):
|
||||
return PLPCDU_OVERHEATING_STRING;
|
||||
return PCDU_SYSTEM_OVERHEATING_STRING;
|
||||
case (14107):
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 173 translations.
|
||||
* Generated on: 2023-03-28 22:20:01
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-04-04 13:59:07
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
@ -37,6 +37,8 @@ const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
|
||||
const char *RW4_STRING = "RW4";
|
||||
const char *STAR_TRACKER_STRING = "STAR_TRACKER";
|
||||
const char *GPS_CONTROLLER_STRING = "GPS_CONTROLLER";
|
||||
const char *GPS_0_HEALTH_DEV_STRING = "GPS_0_HEALTH_DEV";
|
||||
const char *GPS_1_HEALTH_DEV_STRING = "GPS_1_HEALTH_DEV";
|
||||
const char *IMTQ_POLLING_STRING = "IMTQ_POLLING";
|
||||
const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER";
|
||||
const char *PCDU_HANDLER_STRING = "PCDU_HANDLER";
|
||||
@ -244,6 +246,10 @@ const char *translateObject(object_id_t object) {
|
||||
return STAR_TRACKER_STRING;
|
||||
case 0x44130045:
|
||||
return GPS_CONTROLLER_STRING;
|
||||
case 0x44130046:
|
||||
return GPS_0_HEALTH_DEV_STRING;
|
||||
case 0x44130047:
|
||||
return GPS_1_HEALTH_DEV_STRING;
|
||||
case 0x44140013:
|
||||
return IMTQ_POLLING_STRING;
|
||||
case 0x44140014:
|
||||
|
@ -18,8 +18,11 @@
|
||||
#include <ctime>
|
||||
|
||||
GpsHyperionLinuxController::GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId,
|
||||
bool debugHyperionGps)
|
||||
: ExtendedControllerBase(objectId), gpsSet(this), debugHyperionGps(debugHyperionGps) {}
|
||||
bool enableHkSets, bool debugHyperionGps)
|
||||
: ExtendedControllerBase(objectId),
|
||||
gpsSet(this),
|
||||
enableHkSets(enableHkSets),
|
||||
debugHyperionGps(debugHyperionGps) {}
|
||||
|
||||
GpsHyperionLinuxController::~GpsHyperionLinuxController() {
|
||||
gps_stream(&gps, WATCH_DISABLE, nullptr);
|
||||
@ -86,7 +89,7 @@ ReturnValue_t GpsHyperionLinuxController::initializeLocalDataPool(
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_USE, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::SATS_IN_VIEW, new PoolEntry<uint8_t>());
|
||||
localDataPoolMap.emplace(GpsHyperion::FIX_MODE, new PoolEntry<uint8_t>());
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), false, 30.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsSet.getSid(), enableHkSets, 30.0});
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -99,6 +102,7 @@ void GpsHyperionLinuxController::setResetPinTriggerFunction(gpioResetFunction_t
|
||||
ReturnValue_t GpsHyperionLinuxController::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
poolManager.performHkOperation();
|
||||
|
||||
while (true) {
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
trace::threadTrace(opCounter, "GPS CTRL");
|
||||
|
@ -29,7 +29,7 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
|
||||
enum ReadModes { SHM = 0, SOCKET = 1 };
|
||||
|
||||
GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId,
|
||||
GpsHyperionLinuxController(object_id_t objectId, object_id_t parentId, bool enableHkSets,
|
||||
bool debugHyperionGps = false);
|
||||
virtual ~GpsHyperionLinuxController();
|
||||
|
||||
@ -58,6 +58,7 @@ class GpsHyperionLinuxController : public ExtendedControllerBase {
|
||||
private:
|
||||
GpsPrimaryDataset gpsSet;
|
||||
gps_data_t gps = {};
|
||||
bool enableHkSets = false;
|
||||
const char* currentClientBuf = nullptr;
|
||||
ReadModes readMode = ReadModes::SOCKET;
|
||||
Countdown maxTimeToReachFix = Countdown(MAX_SECONDS_TO_REACH_FIX * 1000);
|
||||
|
@ -27,7 +27,7 @@ ReturnValue_t ImtqPollingTask::performOperation(uint8_t operationCode) {
|
||||
|
||||
comStatus = returnvalue::OK;
|
||||
// Stopwatch watch;
|
||||
switch (currentRequest) {
|
||||
switch (currentRequest.requestType) {
|
||||
case imtq::RequestType::MEASURE_NO_ACTUATION: {
|
||||
// Measured to take 24 ms for debug and release builds.
|
||||
// Stopwatch watch;
|
||||
@ -51,6 +51,30 @@ void ImtqPollingTask::handleMeasureStep() {
|
||||
uint8_t* replyPtr;
|
||||
ImtqRepliesDefault replies(replyBuf.data());
|
||||
// If some startup handling is added later, set configured after it was done once.
|
||||
if (performStartup) {
|
||||
// Set integration time for the MGM.
|
||||
cmdBuf[0] = imtq::CC::SET_PARAM;
|
||||
size_t dummy = 0;
|
||||
SerializeAdapter::serialize(&imtq::param::INTEGRATION_TIME_SELECT, cmdBuf.data() + 1, &dummy,
|
||||
cmdBuf.size(), SerializeIF::Endianness::LITTLE);
|
||||
cmdBuf[3] = currentRequest.integrationTimeSel;
|
||||
cmdLen = 4;
|
||||
ReturnValue_t result = performI2cFullRequest(replyBuf.data(), 5);
|
||||
if (result != returnvalue::OK) {
|
||||
comStatus = imtq::STARTUP_CFG_ERROR;
|
||||
}
|
||||
if (replyBuf[0] != imtq::CC::SET_PARAM) {
|
||||
sif::error << "ImtqPollingTask: First byte of reply not equal to sent CC" << std::endl;
|
||||
comStatus = imtq::STARTUP_CFG_ERROR;
|
||||
}
|
||||
if (replyBuf[4] != currentRequest.integrationTimeSel) {
|
||||
sif::error << "ImtqPollingTask: Integration time configuration failed" << std::endl;
|
||||
comStatus = imtq::STARTUP_CFG_ERROR;
|
||||
}
|
||||
currentIntegrationTimeMs =
|
||||
imtq::integrationTimeFromSelectValue(currentRequest.integrationTimeSel);
|
||||
performStartup = false;
|
||||
}
|
||||
replies.setConfigured();
|
||||
|
||||
// Can be used later to verify correct timing (e.g. all data has been read)
|
||||
@ -73,7 +97,7 @@ void ImtqPollingTask::handleMeasureStep() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (specialRequest != imtq::SpecialRequest::NONE) {
|
||||
if (currentRequest.specialRequest != imtq::SpecialRequest::NONE) {
|
||||
auto executeSelfTest = [&](imtq::selfTest::Axis axis) {
|
||||
cmdBuf[0] = imtq::CC::SELF_TEST_CMD;
|
||||
cmdBuf[1] = axis;
|
||||
@ -81,7 +105,7 @@ void ImtqPollingTask::handleMeasureStep() {
|
||||
};
|
||||
// If a self-test is already ongoing, ignore the request.
|
||||
if (replies.getSystemState()[2] != static_cast<uint8_t>(imtq::mode::SELF_TEST)) {
|
||||
switch (specialRequest) {
|
||||
switch (currentRequest.specialRequest) {
|
||||
case (imtq::SpecialRequest::DO_SELF_TEST_POS_X): {
|
||||
executeSelfTest(imtq::selfTest::Axis::X_POSITIVE);
|
||||
break;
|
||||
@ -234,18 +258,21 @@ ReturnValue_t ImtqPollingTask::initializeInterface(CookieIF* cookie) {
|
||||
ReturnValue_t ImtqPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
size_t sendLen) {
|
||||
const auto* imtqReq = reinterpret_cast<const imtq::Request*>(sendData);
|
||||
if (sendLen != sizeof(imtq::Request)) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
if (imtqReq->request == imtq::RequestType::ACTUATE) {
|
||||
std::memcpy(dipoles, imtqReq->dipoles, sizeof(dipoles));
|
||||
torqueDuration = imtqReq->torqueDuration;
|
||||
}
|
||||
currentRequest = imtqReq->request;
|
||||
specialRequest = imtqReq->specialRequest;
|
||||
if (state != InternalState::IDLE) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
state = InternalState::IS_BUSY;
|
||||
if (currentRequest.mode != imtqReq->mode) {
|
||||
if (imtqReq->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
performStartup = true;
|
||||
}
|
||||
}
|
||||
std::memcpy(¤tRequest, imtqReq, sendLen);
|
||||
}
|
||||
semaphore->release();
|
||||
|
||||
@ -345,10 +372,10 @@ void ImtqPollingTask::buildDipoleCommand() {
|
||||
uint8_t* serPtr = cmdBuf.data() + 1;
|
||||
size_t serLen = 0;
|
||||
for (uint8_t idx = 0; idx < 3; idx++) {
|
||||
SerializeAdapter::serialize(&dipoles[idx], &serPtr, &serLen, cmdBuf.size(),
|
||||
SerializeAdapter::serialize(¤tRequest.dipoles[idx], &serPtr, &serLen, cmdBuf.size(),
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
}
|
||||
SerializeAdapter::serialize(&torqueDuration, &serPtr, &serLen, cmdBuf.size(),
|
||||
SerializeAdapter::serialize(¤tRequest.torqueDuration, &serPtr, &serLen, cmdBuf.size(),
|
||||
SerializeIF::Endianness::LITTLE);
|
||||
// sif::debug << "Dipole X: " << dipoles[0] << std::endl;
|
||||
// sif::debug << "Torqeu Dur: " << torqueDuration << std::endl;
|
||||
@ -357,22 +384,28 @@ void ImtqPollingTask::buildDipoleCommand() {
|
||||
|
||||
ReturnValue_t ImtqPollingTask::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
||||
size_t* size) {
|
||||
imtq::RequestType currentRequest;
|
||||
imtq::Request currentRequest;
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
currentRequest = this->currentRequest;
|
||||
std::memcpy(¤tRequest, &this->currentRequest, sizeof(currentRequest));
|
||||
}
|
||||
|
||||
size_t replyLen = 0;
|
||||
MutexGuard mg(bufLock);
|
||||
if (currentRequest == imtq::RequestType::MEASURE_NO_ACTUATION) {
|
||||
replyLen = getExchangeBufLen(specialRequest);
|
||||
memcpy(exchangeBuf.data(), replyBuf.data(), replyLen);
|
||||
} else if (currentRequest == imtq::RequestType::ACTUATE) {
|
||||
replyLen = ImtqRepliesWithTorque::BASE_LEN;
|
||||
memcpy(exchangeBuf.data(), replyBufActuation.data(), replyLen);
|
||||
} else {
|
||||
*size = 0;
|
||||
{
|
||||
MutexGuard mg(bufLock);
|
||||
if (currentRequest.requestType == imtq::RequestType::MEASURE_NO_ACTUATION) {
|
||||
replyLen = getExchangeBufLen(currentRequest.specialRequest);
|
||||
memcpy(exchangeBuf.data(), replyBuf.data(), replyLen);
|
||||
} else if (currentRequest.requestType == imtq::RequestType::ACTUATE) {
|
||||
replyLen = ImtqRepliesWithTorque::BASE_LEN;
|
||||
memcpy(exchangeBuf.data(), replyBufActuation.data(), replyLen);
|
||||
} else {
|
||||
*size = 0;
|
||||
}
|
||||
}
|
||||
{
|
||||
MutexGuard mg(ipcLock);
|
||||
this->currentRequest.requestType = imtq::RequestType::DO_NOTHING;
|
||||
}
|
||||
*buffer = exchangeBuf.data();
|
||||
*size = replyLen;
|
||||
@ -417,6 +450,7 @@ void ImtqPollingTask::clearReadFlagsWithTorque(ImtqRepliesWithTorque& replies) {
|
||||
ReturnValue_t ImtqPollingTask::performI2cFullRequest(uint8_t* reply, size_t replyLen) {
|
||||
int fd = 0;
|
||||
if (cmdLen == 0 or reply == nullptr) {
|
||||
sif::error << "ImtqPollingTask: Command lenght is zero or reply PTR is invalid" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <fsfw/tasks/SemaphoreIF.h>
|
||||
#include <fsfw_hal/linux/i2c/I2cCookie.h>
|
||||
#include <mission/acs/acsBoardPolling.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
@ -24,7 +25,6 @@ class ImtqPollingTask : public SystemObject,
|
||||
static constexpr ReturnValue_t NO_REPLY_AVAILABLE = returnvalue::makeCode(2, 0);
|
||||
|
||||
enum class InternalState { IDLE, IS_BUSY } state = InternalState::IDLE;
|
||||
imtq::RequestType currentRequest = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
|
||||
SemaphoreIF* semaphore;
|
||||
ReturnValue_t comStatus = returnvalue::OK;
|
||||
@ -38,10 +38,9 @@ class ImtqPollingTask : public SystemObject,
|
||||
// Required in addition to integration time, otherwise old data might be read.
|
||||
static constexpr uint32_t MGM_READ_BUFFER_TIME_MS = 6;
|
||||
bool ignoreNextActuateRequest = false;
|
||||
bool performStartup = false;
|
||||
|
||||
imtq::SpecialRequest specialRequest = imtq::SpecialRequest::NONE;
|
||||
int16_t dipoles[3] = {};
|
||||
uint16_t torqueDuration = 0;
|
||||
imtq::Request currentRequest{};
|
||||
|
||||
std::array<uint8_t, 32> cmdBuf;
|
||||
std::array<uint8_t, 524> replyBuf;
|
||||
|
@ -42,7 +42,6 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
while (true) {
|
||||
lock->lockMutex();
|
||||
state = InternalState::SLEEPING;
|
||||
datalinkLayer.reset();
|
||||
lock->unlockMutex();
|
||||
semaphore.acquire();
|
||||
switch (state) {
|
||||
@ -58,6 +57,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::UPLOAD_IMAGE: {
|
||||
replyTimeout.setTimeout(200);
|
||||
resetReplyHandlingState();
|
||||
result = performImageUpload();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(IMAGE_UPLOAD_SUCCESSFUL);
|
||||
@ -68,6 +68,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::DOWNLOAD_IMAGE: {
|
||||
replyTimeout.setTimeout(200);
|
||||
resetReplyHandlingState();
|
||||
result = performImageDownload();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(IMAGE_DOWNLOAD_SUCCESSFUL);
|
||||
@ -78,6 +79,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::FLASH_READ: {
|
||||
replyTimeout.setTimeout(200);
|
||||
resetReplyHandlingState();
|
||||
result = performFlashRead();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(FLASH_READ_SUCCESSFUL);
|
||||
@ -88,6 +90,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
}
|
||||
case InternalState::FIRMWARE_UPDATE: {
|
||||
replyTimeout.setTimeout(200);
|
||||
resetReplyHandlingState();
|
||||
result = performFirmwareUpdate();
|
||||
if (result == returnvalue::OK) {
|
||||
triggerEvent(FIRMWARE_UPDATE_SUCCESSFUL);
|
||||
@ -645,7 +648,8 @@ ReturnValue_t StrComHandler::sendMessage(CookieIF* cookie, const uint8_t* sendDa
|
||||
return BUSY;
|
||||
}
|
||||
}
|
||||
serial::flushRxBuf(serialPort);
|
||||
// Ensure consistent state.
|
||||
resetReplyHandlingState();
|
||||
|
||||
const uint8_t* txFrame;
|
||||
size_t frameLen;
|
||||
@ -697,6 +701,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf
|
||||
*buffer = const_cast<uint8_t*>(replyPtr);
|
||||
*size = replyLen;
|
||||
}
|
||||
replyLen = 0;
|
||||
return replyResult;
|
||||
}
|
||||
|
||||
@ -781,3 +786,8 @@ ReturnValue_t StrComHandler::readOneReply(uint32_t failParameter) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StrComHandler::resetReplyHandlingState() {
|
||||
serial::flushRxBuf(serialPort);
|
||||
datalinkLayer.reset();
|
||||
}
|
||||
|
@ -374,6 +374,8 @@ class StrComHandler : public SystemObject, public DeviceCommunicationIF, public
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t readOneReply(uint32_t failParameter);
|
||||
|
||||
void resetReplyHandlingState();
|
||||
};
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_STRHELPER_H_ */
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 283 translations.
|
||||
* @brief Auto-generated event translation file. Contains 284 translations.
|
||||
* @details
|
||||
* Generated on: 2023-03-28 22:20:01
|
||||
* Generated on: 2023-04-04 13:59:07
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -209,11 +209,11 @@ const char *TRANSITION_OTHER_SIDE_FAILED_STRING = "TRANSITION_OTHER_SIDE_FAILED"
|
||||
const char *NOT_ENOUGH_DEVICES_DUAL_MODE_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE";
|
||||
const char *POWER_STATE_MACHINE_TIMEOUT_STRING = "POWER_STATE_MACHINE_TIMEOUT";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING = "SIDE_SWITCH_TRANSITION_NOT_ALLOWED";
|
||||
const char *DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY_STRING = "DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY";
|
||||
const char *TRANSITION_OTHER_SIDE_FAILED_12900_STRING = "TRANSITION_OTHER_SIDE_FAILED_12900";
|
||||
const char *NOT_ENOUGH_DEVICES_DUAL_MODE_12901_STRING = "NOT_ENOUGH_DEVICES_DUAL_MODE_12901";
|
||||
const char *POWER_STATE_MACHINE_TIMEOUT_12902_STRING = "POWER_STATE_MACHINE_TIMEOUT_12902";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING =
|
||||
"SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903";
|
||||
const char *SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903_STRING = "SIDE_SWITCH_TRANSITION_NOT_ALLOWED_12903";
|
||||
const char *CHILDREN_LOST_MODE_STRING = "CHILDREN_LOST_MODE";
|
||||
const char *GPS_FIX_CHANGE_STRING = "GPS_FIX_CHANGE";
|
||||
const char *CANT_GET_FIX_STRING = "CANT_GET_FIX";
|
||||
@ -270,10 +270,10 @@ const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT";
|
||||
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";
|
||||
const char *PLOC_OVERHEATING_STRING = "PLOC_OVERHEATING";
|
||||
const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *HPA_OVERHEATING_STRING = "HPA_OVERHEATING";
|
||||
const char *PLPCDU_OVERHEATING_STRING = "PLPCDU_OVERHEATING";
|
||||
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 *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";
|
||||
@ -700,6 +700,8 @@ const char *translateEvents(Event event) {
|
||||
return POWER_STATE_MACHINE_TIMEOUT_STRING;
|
||||
case (12803):
|
||||
return SIDE_SWITCH_TRANSITION_NOT_ALLOWED_STRING;
|
||||
case (12804):
|
||||
return DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY_STRING;
|
||||
case (12900):
|
||||
return TRANSITION_OTHER_SIDE_FAILED_12900_STRING;
|
||||
case (12901):
|
||||
@ -820,14 +822,14 @@ const char *translateEvents(Event event) {
|
||||
return NO_HEALTHY_HEATER_AVAILABLE_STRING;
|
||||
case (14102):
|
||||
return SYRLINKS_OVERHEATING_STRING;
|
||||
case (14103):
|
||||
return PLOC_OVERHEATING_STRING;
|
||||
case (14104):
|
||||
return OBC_OVERHEATING_STRING;
|
||||
case (14105):
|
||||
return HPA_OVERHEATING_STRING;
|
||||
return CAMERA_OVERHEATING_STRING;
|
||||
case (14106):
|
||||
return PLPCDU_OVERHEATING_STRING;
|
||||
return PCDU_SYSTEM_OVERHEATING_STRING;
|
||||
case (14107):
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 173 translations.
|
||||
* Generated on: 2023-03-28 22:20:01
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-04-04 13:59:07
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
@ -37,6 +37,8 @@ const char *GYRO_3_L3G_HANDLER_STRING = "GYRO_3_L3G_HANDLER";
|
||||
const char *RW4_STRING = "RW4";
|
||||
const char *STAR_TRACKER_STRING = "STAR_TRACKER";
|
||||
const char *GPS_CONTROLLER_STRING = "GPS_CONTROLLER";
|
||||
const char *GPS_0_HEALTH_DEV_STRING = "GPS_0_HEALTH_DEV";
|
||||
const char *GPS_1_HEALTH_DEV_STRING = "GPS_1_HEALTH_DEV";
|
||||
const char *IMTQ_POLLING_STRING = "IMTQ_POLLING";
|
||||
const char *IMTQ_HANDLER_STRING = "IMTQ_HANDLER";
|
||||
const char *PCDU_HANDLER_STRING = "PCDU_HANDLER";
|
||||
@ -244,6 +246,10 @@ const char *translateObject(object_id_t object) {
|
||||
return STAR_TRACKER_STRING;
|
||||
case 0x44130045:
|
||||
return GPS_CONTROLLER_STRING;
|
||||
case 0x44130046:
|
||||
return GPS_0_HEALTH_DEV_STRING;
|
||||
case 0x44130047:
|
||||
return GPS_1_HEALTH_DEV_STRING;
|
||||
case 0x44140013:
|
||||
return IMTQ_POLLING_STRING;
|
||||
case 0x44140014:
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "AxiPtmeConfig.h"
|
||||
|
||||
#include <fsfw/ipc/MutexGuard.h>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw_hal/linux/uio/UioMapper.h"
|
||||
|
||||
@ -39,97 +41,59 @@ ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::enableTxclockManipulator() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void AxiPtmeConfig::enableTxclockManipulator() {
|
||||
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::disableTxclockManipulator() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void AxiPtmeConfig::disableTxclockManipulator() {
|
||||
writeBit(COMMON_CONFIG_REG, false, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::enableTxclockInversion() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::INVERT_CLOCK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void AxiPtmeConfig::enableTxclockInversion() {
|
||||
writeBit(COMMON_CONFIG_REG, true, BitPos::INVERT_CLOCK);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::disableTxclockInversion() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::INVERT_CLOCK);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void AxiPtmeConfig::disableTxclockInversion() {
|
||||
writeBit(COMMON_CONFIG_REG, false, BitPos::INVERT_CLOCK);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::enableBatPriorityBit() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, true, BitPos::EN_BAT_PRIORITY);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void AxiPtmeConfig::enableBatPriorityBit() {
|
||||
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_BAT_PRIORITY);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::disableBatPriorityBit() {
|
||||
ReturnValue_t result = writeBit(COMMON_CONFIG_REG, false, BitPos::EN_BAT_PRIORITY);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
void AxiPtmeConfig::disableBatPriorityBit() {
|
||||
writeBit(COMMON_CONFIG_REG, false, BitPos::EN_BAT_PRIORITY);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::writeReg(uint32_t regOffset, uint32_t writeVal) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = mutex->lockMutex(timeoutType, mutexTimeout);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to lock mutex" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
void AxiPtmeConfig::writeReg(uint32_t regOffset, uint32_t writeVal) {
|
||||
MutexGuard mg(mutex, timeoutType, mutexTimeout);
|
||||
*(baseAddress + regOffset / ADRESS_DIVIDER) = writeVal;
|
||||
result = mutex->unlockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to unlock mutex" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::readReg(uint32_t regOffset, uint32_t* readVal) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = mutex->lockMutex(timeoutType, mutexTimeout);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to lock mutex" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*readVal = *(baseAddress + regOffset / ADRESS_DIVIDER);
|
||||
result = mutex->unlockMutex();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "AxiPtmeConfig::readReg: Failed to unlock mutex" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
uint32_t AxiPtmeConfig::readReg(uint32_t regOffset) {
|
||||
MutexGuard mg(mutex, timeoutType, mutexTimeout);
|
||||
return *(baseAddress + regOffset / ADRESS_DIVIDER);
|
||||
}
|
||||
|
||||
ReturnValue_t AxiPtmeConfig::writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos) {
|
||||
uint32_t readVal = 0;
|
||||
ReturnValue_t result = readReg(regOffset, &readVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
void AxiPtmeConfig::writePollThreshold(AxiPtmeConfig::IdlePollThreshold pollThreshold) {
|
||||
uint32_t regVal = readCommonCfgReg();
|
||||
// Clear bits first
|
||||
regVal &= ~(0b111 << 3);
|
||||
regVal |= (static_cast<uint8_t>(pollThreshold) << 3);
|
||||
writeCommonCfgReg(regVal);
|
||||
}
|
||||
|
||||
AxiPtmeConfig::IdlePollThreshold AxiPtmeConfig::readPollThreshold() {
|
||||
uint32_t regVal = readCommonCfgReg();
|
||||
return static_cast<AxiPtmeConfig::IdlePollThreshold>((regVal >> 3) & 0b111);
|
||||
}
|
||||
|
||||
void AxiPtmeConfig::writeCommonCfgReg(uint32_t value) { writeReg(COMMON_CONFIG_REG, value); }
|
||||
uint32_t AxiPtmeConfig::readCommonCfgReg() { return readReg(COMMON_CONFIG_REG); }
|
||||
|
||||
void AxiPtmeConfig::writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos) {
|
||||
uint32_t readVal = readReg(regOffset);
|
||||
uint32_t writeVal =
|
||||
(readVal & ~(1 << static_cast<uint32_t>(bitPos))) | bitVal << static_cast<uint32_t>(bitPos);
|
||||
result = writeReg(regOffset, writeVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
writeReg(regOffset, writeVal);
|
||||
}
|
||||
|
@ -14,6 +14,16 @@
|
||||
*/
|
||||
class AxiPtmeConfig : public SystemObject {
|
||||
public:
|
||||
enum IdlePollThreshold : uint8_t {
|
||||
ALWAYS = 0b000,
|
||||
POLL_1 = 0b001,
|
||||
POLL_4 = 0b010,
|
||||
POLL_16 = 0b011,
|
||||
POLL_64 = 0b100,
|
||||
POLL_256 = 0b101,
|
||||
POLL_1024 = 0b110,
|
||||
NEVER = 0b111
|
||||
};
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param axiUio Device file of UIO belonging to the AXI configuration interface.
|
||||
@ -40,8 +50,8 @@ class AxiPtmeConfig : public SystemObject {
|
||||
* Default: Enables TX clock manipulator
|
||||
*
|
||||
*/
|
||||
ReturnValue_t enableTxclockManipulator();
|
||||
ReturnValue_t disableTxclockManipulator();
|
||||
void enableTxclockManipulator();
|
||||
void disableTxclockManipulator();
|
||||
|
||||
/**
|
||||
* @brief The next to functions control whether data will be updated on the rising or falling edge
|
||||
@ -51,11 +61,14 @@ class AxiPtmeConfig : public SystemObject {
|
||||
* Disable clock inversion. Data updated on rising edge.
|
||||
* Default: Inversion is disabled
|
||||
*/
|
||||
ReturnValue_t enableTxclockInversion();
|
||||
ReturnValue_t disableTxclockInversion();
|
||||
void enableTxclockInversion();
|
||||
void disableTxclockInversion();
|
||||
|
||||
ReturnValue_t enableBatPriorityBit();
|
||||
ReturnValue_t disableBatPriorityBit();
|
||||
void enableBatPriorityBit();
|
||||
void disableBatPriorityBit();
|
||||
|
||||
void writePollThreshold(IdlePollThreshold pollThreshold);
|
||||
IdlePollThreshold readPollThreshold();
|
||||
|
||||
private:
|
||||
// Address of register storing the bitrate configuration parameter
|
||||
@ -80,7 +93,7 @@ class AxiPtmeConfig : public SystemObject {
|
||||
*
|
||||
* @param writeVal Value to write
|
||||
*/
|
||||
ReturnValue_t writeReg(uint32_t regOffset, uint32_t writeVal);
|
||||
void writeReg(uint32_t regOffset, uint32_t writeVal);
|
||||
|
||||
/**
|
||||
* @brief Reads value from configuration register
|
||||
@ -88,7 +101,10 @@ class AxiPtmeConfig : public SystemObject {
|
||||
* @param regOffset Offset of register from base address to read from
|
||||
* Qparam readVal Pointer to variable where read value will be written to
|
||||
*/
|
||||
ReturnValue_t readReg(uint32_t regOffset, uint32_t* readVal);
|
||||
uint32_t readReg(uint32_t regOffset);
|
||||
|
||||
uint32_t readCommonCfgReg();
|
||||
void writeCommonCfgReg(uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Sets one bit in a register
|
||||
@ -99,7 +115,7 @@ class AxiPtmeConfig : public SystemObject {
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED
|
||||
*/
|
||||
ReturnValue_t writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos);
|
||||
void writeBit(uint32_t regOffset, bool bitVal, BitPos bitPos);
|
||||
};
|
||||
|
||||
#endif /* LINUX_OBC_AXIPTMECONFIG_H_ */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <linux/ipcore/PapbVcInterface.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
@ -18,29 +19,63 @@ PapbVcInterface::~PapbVcInterface() {}
|
||||
|
||||
ReturnValue_t PapbVcInterface::initialize() {
|
||||
UioMapper uioMapper(uioFile, mapNum);
|
||||
uint32_t* baseReg;
|
||||
ReturnValue_t result = uioMapper.getMappedAdress(&baseReg, UioMapper::Permissions::WRITE_ONLY);
|
||||
ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg),
|
||||
UioMapper::Permissions::WRITE_ONLY);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
vcBaseReg = baseReg;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
if (pollPapbBusySignal(0) == returnvalue::OK) {
|
||||
startPacketTransfer();
|
||||
// There are no packets smaller than 4, this is considered a configuration error.
|
||||
if (size < 4) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (pollInterfaceReadiness(0, true) == returnvalue::OK) {
|
||||
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 too often can mess up the scheduler.
|
||||
// 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 (pollPapbBusySignal(2) == returnvalue::OK) {
|
||||
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
|
||||
} else {
|
||||
abortPacketTransfer();
|
||||
@ -48,7 +83,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
}
|
||||
}
|
||||
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
if (pollPapbBusySignal(2) == returnvalue::OK) {
|
||||
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
|
||||
completePacketTransfer();
|
||||
} else {
|
||||
abortPacketTransfer();
|
||||
@ -57,27 +92,29 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; }
|
||||
void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
|
||||
*vcBaseReg = CONFIG_DATA_INPUT | initWidth;
|
||||
}
|
||||
|
||||
void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
|
||||
|
||||
ReturnValue_t PapbVcInterface::pollPapbBusySignal(uint32_t maxPollRetries) const {
|
||||
gpio::Levels papbBusyState = gpio::Levels::LOW;
|
||||
ReturnValue_t result;
|
||||
ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
|
||||
bool checkReadyState) const {
|
||||
uint32_t busyIdx = 0;
|
||||
nextDelay.tv_nsec = 0;
|
||||
nextDelay.tv_nsec = FIRST_DELAY_PAPB_POLLING_NS;
|
||||
|
||||
while (true) {
|
||||
/** Check if PAPB interface is ready to receive data */
|
||||
result = gpioComIF->readGpio(papbBusyId, papbBusyState);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (papbBusyState == gpio::Levels::HIGH) {
|
||||
// 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) {
|
||||
@ -87,9 +124,7 @@ ReturnValue_t PapbVcInterface::pollPapbBusySignal(uint32_t maxPollRetries) const
|
||||
// Ignore signal handling here for now.
|
||||
nanosleep(&nextDelay, &remDelay);
|
||||
// Adaptive delay.
|
||||
if (nextDelay.tv_nsec == 0) {
|
||||
nextDelay.tv_nsec = FIRST_NON_NULL_DELAY_NS;
|
||||
} else if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) {
|
||||
if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) {
|
||||
nextDelay.tv_nsec *= 2;
|
||||
}
|
||||
}
|
||||
@ -116,7 +151,7 @@ void PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||
return;
|
||||
}
|
||||
|
||||
bool PapbVcInterface::isBusy() const { return pollPapbBusySignal(0) == PAPB_BUSY; }
|
||||
bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; }
|
||||
|
||||
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <linux/ipcore/VirtualChannelIF.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
@ -50,13 +52,14 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
|
||||
static const ReturnValue_t PAPB_BUSY = MAKE_RETURN_CODE(0xA0);
|
||||
|
||||
enum ByteWidthCfg : uint32_t { ONE = 0b00, TWO = 0b01, THREE = 0b10, FOUR = 0b11 };
|
||||
/**
|
||||
* Configuration bits:
|
||||
* bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00
|
||||
* bit[2]: Set this bit to 1 to abort a transferred packet
|
||||
* bit[3]: Signals to VcInterface the start of a new telemetry packet
|
||||
*/
|
||||
static constexpr uint32_t CONFIG_START = 0b00001000;
|
||||
static constexpr uint32_t CONFIG_DATA_INPUT = 0b00001000;
|
||||
|
||||
/**
|
||||
* Abort a transferred packet.
|
||||
@ -76,7 +79,7 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
*/
|
||||
static const int DATA_REG_OFFSET = 256;
|
||||
|
||||
static constexpr long int FIRST_NON_NULL_DELAY_NS = 10;
|
||||
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
|
||||
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
@ -89,7 +92,7 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
std::string uioFile;
|
||||
int mapNum = 0;
|
||||
mutable struct timespec nextDelay = {.tv_sec = 0, .tv_nsec = 0};
|
||||
const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 5};
|
||||
const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 10};
|
||||
mutable struct timespec remDelay;
|
||||
|
||||
volatile uint32_t* vcBaseReg = nullptr;
|
||||
@ -100,7 +103,7 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
* @brief This function sends the config byte to the virtual channel of the PTME IP Core
|
||||
* to initiate a packet transfer.
|
||||
*/
|
||||
void startPacketTransfer();
|
||||
void startPacketTransfer(ByteWidthCfg initWidth);
|
||||
|
||||
void abortPacketTransfer();
|
||||
|
||||
@ -117,7 +120,7 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
*
|
||||
* @return returnvalue::OK when ready to receive data else PAPB_BUSY.
|
||||
*/
|
||||
inline ReturnValue_t pollPapbBusySignal(uint32_t maxPollRetries) const;
|
||||
inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const;
|
||||
|
||||
/**
|
||||
* @brief This function can be used for debugging to check whether there are packets in
|
||||
|
@ -26,33 +26,30 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
|
||||
return axiPtmeConfig->writeCaduRateReg(static_cast<uint8_t>(rateVal));
|
||||
}
|
||||
|
||||
ReturnValue_t PtmeConfig::invertTxClock(bool invert) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
void PtmeConfig::invertTxClock(bool invert) {
|
||||
if (invert) {
|
||||
result = axiPtmeConfig->enableTxclockInversion();
|
||||
axiPtmeConfig->enableTxclockInversion();
|
||||
} else {
|
||||
result = axiPtmeConfig->disableTxclockInversion();
|
||||
axiPtmeConfig->disableTxclockInversion();
|
||||
}
|
||||
if (result != returnvalue::OK) {
|
||||
return CLK_INVERSION_FAILED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PtmeConfig::configTxManipulator(bool enable) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
void PtmeConfig::configTxManipulator(bool enable) {
|
||||
if (enable) {
|
||||
result = axiPtmeConfig->enableTxclockManipulator();
|
||||
axiPtmeConfig->enableTxclockManipulator();
|
||||
} else {
|
||||
result = axiPtmeConfig->disableTxclockManipulator();
|
||||
axiPtmeConfig->disableTxclockManipulator();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PtmeConfig::enableBatPriorityBit(bool enable) {
|
||||
void PtmeConfig::enableBatPriorityBit(bool enable) {
|
||||
if (enable) {
|
||||
return axiPtmeConfig->enableBatPriorityBit();
|
||||
axiPtmeConfig->enableBatPriorityBit();
|
||||
} else {
|
||||
return axiPtmeConfig->disableBatPriorityBit();
|
||||
axiPtmeConfig->disableBatPriorityBit();
|
||||
}
|
||||
}
|
||||
|
||||
void PtmeConfig::setPollThreshold(AxiPtmeConfig::IdlePollThreshold pollThreshold) {
|
||||
axiPtmeConfig->writePollThreshold(pollThreshold);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class PtmeConfig : public SystemObject {
|
||||
*
|
||||
* @return REUTRN_OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t invertTxClock(bool invert);
|
||||
void invertTxClock(bool invert);
|
||||
|
||||
/**
|
||||
* @brief Controls the tx clock manipulator of the PTME wrapper component
|
||||
@ -53,7 +53,7 @@ class PtmeConfig : public SystemObject {
|
||||
*
|
||||
* @return REUTRN_OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t configTxManipulator(bool enable);
|
||||
void configTxManipulator(bool enable);
|
||||
|
||||
/**
|
||||
* Enable the bat priority bit in the PTME wrapper component.
|
||||
@ -62,7 +62,9 @@ class PtmeConfig : public SystemObject {
|
||||
* @param enable
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t enableBatPriorityBit(bool enable);
|
||||
void enableBatPriorityBit(bool enable);
|
||||
|
||||
void setPollThreshold(AxiPtmeConfig::IdlePollThreshold pollThreshold);
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::RATE_SETTER;
|
||||
|
@ -17,7 +17,7 @@ static constexpr bool DEBUG_MODE = true;
|
||||
SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_,
|
||||
GpioIF& gpioInterface,
|
||||
PowerSwitchIF& mainLineSwitcher_,
|
||||
pcdu::Switches mainLineSwitch_,
|
||||
power::Switches mainLineSwitch_,
|
||||
gpioId_t deplSA1, gpioId_t deplSA2,
|
||||
SdCardMountedIF& sdcMountedIF)
|
||||
: SystemObject(setObjectId_),
|
||||
|
@ -107,7 +107,7 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF,
|
||||
* @param burnTimeMs Time duration the power will be applied to the burn wires.
|
||||
*/
|
||||
SolarArrayDeploymentHandler(object_id_t setObjectId, GpioIF& gpio,
|
||||
PowerSwitchIF& mainLineSwitcher, pcdu::Switches mainLineSwitch,
|
||||
PowerSwitchIF& mainLineSwitcher, power::Switches mainLineSwitch,
|
||||
gpioId_t deplSA1, gpioId_t deplSA2, SdCardMountedIF& sdcMountedIF);
|
||||
|
||||
virtual ~SolarArrayDeploymentHandler();
|
||||
|
@ -87,12 +87,11 @@ ReturnValue_t GyrAdis1650XHandler::scanForReply(const uint8_t *start, size_t rem
|
||||
getMode() == _MODE_POWER_DOWN) {
|
||||
return IGNORE_FULL_PACKET;
|
||||
}
|
||||
*foundLen = remainingSize;
|
||||
if (remainingSize != sizeof(acs::Adis1650XReply)) {
|
||||
*foundLen = remainingSize;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*foundId = adis1650x::REPLY;
|
||||
*foundLen = remainingSize;
|
||||
if (internalState == InternalState::SHUTDOWN) {
|
||||
commandExecuted = true;
|
||||
}
|
||||
|
@ -99,12 +99,11 @@ ReturnValue_t GyrL3gCustomHandler::scanForReply(const uint8_t *start, size_t len
|
||||
if (getMode() == _MODE_WAIT_OFF or getMode() == _MODE_WAIT_ON or getMode() == _MODE_POWER_DOWN) {
|
||||
return IGNORE_FULL_PACKET;
|
||||
}
|
||||
*foundLen = len;
|
||||
if (len != sizeof(acs::GyroL3gReply)) {
|
||||
*foundLen = len;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*foundId = l3gd20h::REPLY;
|
||||
*foundLen = len;
|
||||
*foundId = adis1650x::REPLY;
|
||||
if (internalState == InternalState::SHUTDOWN) {
|
||||
commandExecuted = true;
|
||||
}
|
||||
|
@ -151,19 +151,25 @@ void ImtqHandler::doStartUp() {
|
||||
}
|
||||
|
||||
void ImtqHandler::doShutDown() {
|
||||
updatePeriodicReply(false, imtq::cmdIds::REPLY_NO_TORQUE);
|
||||
updatePeriodicReply(false, imtq::cmdIds::REPLY_WITH_TORQUE);
|
||||
specialRequestActive = false;
|
||||
firstReplyCycle = true;
|
||||
internalState = InternalState::NONE;
|
||||
commandExecuted = false;
|
||||
statusSet.setValidity(false, true);
|
||||
rawMtmNoTorque.setValidity(false, true);
|
||||
rawMtmWithTorque.setValidity(false, true);
|
||||
hkDatasetNoTorque.setValidity(false, true);
|
||||
hkDatasetWithTorque.setValidity(false, true);
|
||||
calMtmMeasurementSet.setValidity(false, true);
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
if (internalState != InternalState::SHUTDOWN) {
|
||||
commandExecuted = false;
|
||||
internalState = InternalState::SHUTDOWN;
|
||||
}
|
||||
if (internalState == InternalState::SHUTDOWN and commandExecuted) {
|
||||
updatePeriodicReply(false, imtq::cmdIds::REPLY_NO_TORQUE);
|
||||
updatePeriodicReply(false, imtq::cmdIds::REPLY_WITH_TORQUE);
|
||||
specialRequestActive = false;
|
||||
firstReplyCycle = true;
|
||||
internalState = InternalState::NONE;
|
||||
commandExecuted = false;
|
||||
statusSet.setValidity(false, true);
|
||||
rawMtmNoTorque.setValidity(false, true);
|
||||
rawMtmWithTorque.setValidity(false, true);
|
||||
hkDatasetNoTorque.setValidity(false, true);
|
||||
hkDatasetWithTorque.setValidity(false, true);
|
||||
calMtmMeasurementSet.setValidity(false, true);
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
@ -178,7 +184,7 @@ ReturnValue_t ImtqHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
}
|
||||
default: {
|
||||
*id = imtq::cmdIds::REQUEST;
|
||||
request.request = imtq::RequestType::DO_NOTHING;
|
||||
request.requestType = imtq::RequestType::DO_NOTHING;
|
||||
request.specialRequest = imtq::SpecialRequest::NONE;
|
||||
expectedReply = DeviceHandlerIF::NO_COMMAND_ID;
|
||||
rawPacket = reinterpret_cast<uint8_t*>(&request);
|
||||
@ -190,7 +196,7 @@ ReturnValue_t ImtqHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
}
|
||||
|
||||
ReturnValue_t ImtqHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
||||
if (internalState == InternalState::STARTUP) {
|
||||
if (internalState == InternalState::STARTUP or internalState == InternalState::SHUTDOWN) {
|
||||
*id = imtq::cmdIds::REQUEST;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
@ -201,7 +207,7 @@ ReturnValue_t ImtqHandler::buildCommandFromCommand(DeviceCommandId_t deviceComma
|
||||
const uint8_t* commandData,
|
||||
size_t commandDataLen) {
|
||||
auto genericSpecialRequest = [&](imtq::SpecialRequest specialRequest) {
|
||||
request.request = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
request.requestType = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
request.specialRequest = specialRequest;
|
||||
expectedReply = imtq::cmdIds::REPLY_NO_TORQUE;
|
||||
specialRequestActive = true;
|
||||
@ -238,9 +244,16 @@ ReturnValue_t ImtqHandler::buildCommandFromCommand(DeviceCommandId_t deviceComma
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (imtq::cmdIds::REQUEST): {
|
||||
request.request = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
request.requestType = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
request.specialRequest = imtq::SpecialRequest::NONE;
|
||||
// 6 ms integration time instead of 10 ms.
|
||||
request.integrationTimeSel = 2;
|
||||
expectedReply = imtq::cmdIds::REPLY_NO_TORQUE;
|
||||
if (internalState == InternalState::SHUTDOWN) {
|
||||
request.mode = acs::SimpleSensorMode::OFF;
|
||||
} else {
|
||||
request.mode = acs::SimpleSensorMode::NORMAL;
|
||||
}
|
||||
rawPacket = reinterpret_cast<uint8_t*>(&request);
|
||||
rawPacketLen = sizeof(imtq::Request);
|
||||
return returnvalue::OK;
|
||||
@ -267,7 +280,7 @@ ReturnValue_t ImtqHandler::buildCommandFromCommand(DeviceCommandId_t deviceComma
|
||||
}
|
||||
|
||||
expectedReply = imtq::cmdIds::REPLY_WITH_TORQUE;
|
||||
request.request = imtq::RequestType::ACTUATE;
|
||||
request.requestType = imtq::RequestType::ACTUATE;
|
||||
request.specialRequest = imtq::SpecialRequest::NONE;
|
||||
std::memcpy(request.dipoles, dipoleSet.dipoles.value, sizeof(request.dipoles));
|
||||
request.torqueDuration = dipoleSet.currentTorqueDurationMs.value;
|
||||
@ -309,6 +322,9 @@ ReturnValue_t ImtqHandler::scanForReply(const uint8_t* start, size_t remainingSi
|
||||
if (getMode() == _MODE_WAIT_OFF or getMode() == _MODE_WAIT_ON or getMode() == _MODE_POWER_DOWN) {
|
||||
return IGNORE_FULL_PACKET;
|
||||
}
|
||||
if (internalState == InternalState::SHUTDOWN) {
|
||||
commandExecuted = true;
|
||||
}
|
||||
if (remainingSize > 0) {
|
||||
*foundLen = remainingSize;
|
||||
*foundId = expectedReply;
|
||||
@ -779,9 +795,9 @@ ReturnValue_t ImtqHandler::initializeLocalDataPool(localpool::DataPool& localDat
|
||||
localDataPoolMap.emplace(imtq::FINA_NEG_Z_COIL_Z_TEMPERATURE, new PoolEntry<int16_t>({0}));
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 12.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 30.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetWithTorque.getSid(), enableHkSets, 12.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(hkDatasetWithTorque.getSid(), enableHkSets, 30.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(rawMtmNoTorque.getSid(), false, 10.0));
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
|
@ -55,6 +55,10 @@ void RwHandler::doShutDown() {
|
||||
PoolReadGuard pg(&tmDataset);
|
||||
tmDataset.setValidity(false, true);
|
||||
}
|
||||
{
|
||||
PoolReadGuard pg(&rwSpeedActuationSet);
|
||||
rwSpeedActuationSet.setRwSpeed(0, 10);
|
||||
}
|
||||
// The power switch is handled by the assembly, so we can go off here directly.
|
||||
setMode(MODE_OFF);
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_ACSPOLLING_H_
|
||||
#define MISSION_DEVICES_DEVICEDEFINITIONS_ACSPOLLING_H_
|
||||
|
||||
#include <mission/acs/defs.h>
|
||||
|
||||
#include "fsfw/thermal/tcsDefinitions.h"
|
||||
#include "gyroAdisHelpers.h"
|
||||
|
||||
namespace acs {
|
||||
|
||||
enum SimpleSensorMode { NORMAL = 0, OFF = 1 };
|
||||
|
||||
struct Adis1650XRequest {
|
||||
SimpleSensorMode mode;
|
||||
adis1650x::Type type;
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
namespace acs {
|
||||
|
||||
enum class SimpleSensorMode { NORMAL = 0, OFF = 1 };
|
||||
|
||||
// These modes are the submodes of the ACS controller and the modes of the ACS subsystem.
|
||||
enum AcsMode : Mode_t {
|
||||
OFF = HasModesIF::MODE_OFF,
|
||||
|
@ -1,5 +1,26 @@
|
||||
#include "imtqHelpers.h"
|
||||
|
||||
uint16_t imtq::integrationTimeFromSelectValue(uint8_t value) {
|
||||
switch (value) {
|
||||
case (0):
|
||||
return 2;
|
||||
case (1):
|
||||
return 3;
|
||||
case (2):
|
||||
return 6;
|
||||
case (3):
|
||||
return 10;
|
||||
case (4):
|
||||
return 20;
|
||||
case (5):
|
||||
return 40;
|
||||
case (6):
|
||||
return 80;
|
||||
default:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
size_t imtq::getReplySize(CC::CC cc, size_t* optSecondSize) {
|
||||
switch (cc) {
|
||||
// Software reset is a bit special and can also cause a I2C NAK because
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <mission/acs/defs.h>
|
||||
|
||||
class ImtqHandler;
|
||||
|
||||
@ -13,6 +14,8 @@ class ImtqHandler;
|
||||
|
||||
namespace imtq {
|
||||
|
||||
uint16_t integrationTimeFromSelectValue(uint8_t value);
|
||||
|
||||
enum class RequestType : uint8_t { MEASURE_NO_ACTUATION, ACTUATE, DO_NOTHING };
|
||||
|
||||
enum class SpecialRequest : uint8_t {
|
||||
@ -27,7 +30,8 @@ enum class SpecialRequest : uint8_t {
|
||||
};
|
||||
|
||||
struct Request {
|
||||
imtq::RequestType request = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
|
||||
imtq::RequestType requestType = imtq::RequestType::MEASURE_NO_ACTUATION;
|
||||
imtq::SpecialRequest specialRequest = imtq::SpecialRequest::NONE;
|
||||
uint8_t integrationTimeSel = 3;
|
||||
int16_t dipoles[3]{};
|
||||
@ -57,9 +61,10 @@ static const ReturnValue_t CC_UNAVAILABLE = MAKE_RETURN_CODE(5);
|
||||
static const ReturnValue_t INTERNAL_PROCESSING_ERROR = MAKE_RETURN_CODE(6);
|
||||
static const ReturnValue_t REJECTED_WITHOUT_REASON = MAKE_RETURN_CODE(7);
|
||||
static const ReturnValue_t CMD_ERR_UNKNOWN = MAKE_RETURN_CODE(8);
|
||||
static constexpr ReturnValue_t STARTUP_CFG_ERROR = MAKE_RETURN_CODE(9);
|
||||
//! [EXPORT] : [COMMENT] The status reply to a self test command was received but no self test
|
||||
//! command has been sent. This should normally never happen.
|
||||
static const ReturnValue_t UNEXPECTED_SELF_TEST_REPLY = MAKE_RETURN_CODE(0xA7);
|
||||
static const ReturnValue_t UNEXPECTED_SELF_TEST_REPLY = MAKE_RETURN_CODE(10);
|
||||
|
||||
namespace cmdIds {
|
||||
|
||||
@ -162,6 +167,13 @@ enum CC : uint8_t {
|
||||
|
||||
} // namespace CC
|
||||
|
||||
namespace param {
|
||||
|
||||
static constexpr uint16_t SEL_MTM = 0x2002;
|
||||
static constexpr uint16_t INTEGRATION_TIME_SELECT = 0x2003;
|
||||
|
||||
} // namespace param
|
||||
|
||||
size_t getReplySize(CC::CC cc, size_t* optSecondSize = nullptr);
|
||||
|
||||
namespace mode {
|
||||
|
@ -56,6 +56,49 @@ StarTrackerHandler::StarTrackerHandler(object_id_t objectId, object_id_t comIF,
|
||||
|
||||
StarTrackerHandler::~StarTrackerHandler() {}
|
||||
|
||||
void StarTrackerHandler::doStartUp() {
|
||||
switch (startupState) {
|
||||
case StartupState::IDLE:
|
||||
startupState = StartupState::CHECK_PROGRAM;
|
||||
return;
|
||||
case StartupState::BOOT_BOOTLOADER:
|
||||
// This step is required in case the star tracker is already in firmware mode to harmonize
|
||||
// the device handler's submode to the star tracker's mode
|
||||
return;
|
||||
case StartupState::DONE:
|
||||
if (jcfgCountdown.isBusy()) {
|
||||
startupState = StartupState::WAIT_JCFG;
|
||||
return;
|
||||
}
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
case StartupState::WAIT_JCFG: {
|
||||
if (jcfgCountdown.hasTimedOut()) {
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
solutionSet.setReportingEnabled(true);
|
||||
startupState = StartupState::DONE;
|
||||
internalState = InternalState::IDLE;
|
||||
setMode(_MODE_TO_ON);
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doShutDown() {
|
||||
// If the star tracker is shutdown also stop all running processes in the image loader task
|
||||
strHelper->stopProcess();
|
||||
internalState = InternalState::IDLE;
|
||||
startupState = StartupState::IDLE;
|
||||
bootState = FwBootState::NONE;
|
||||
solutionSet.setReportingEnabled(false);
|
||||
reinitNextSetParam = false;
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::initialize() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = DeviceHandlerBase::initialize();
|
||||
@ -213,6 +256,8 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// In case the JSON has changed, reinitiate the next parameter set to update.
|
||||
reinitNextSetParam = true;
|
||||
return DeviceHandlerBase::executeAction(actionId, commandedBy, data, size);
|
||||
}
|
||||
|
||||
@ -232,49 +277,7 @@ void StarTrackerHandler::performOperationHook() {
|
||||
}
|
||||
}
|
||||
|
||||
Submode_t StarTrackerHandler::getInitialSubmode() { return SUBMODE_BOOTLOADER; }
|
||||
|
||||
void StarTrackerHandler::doStartUp() {
|
||||
switch (startupState) {
|
||||
case StartupState::IDLE:
|
||||
startupState = StartupState::CHECK_PROGRAM;
|
||||
return;
|
||||
case StartupState::BOOT_BOOTLOADER:
|
||||
// This step is required in case the star tracker is already in firmware mode to harmonize
|
||||
// the device handler's submode to the star tracker's mode
|
||||
return;
|
||||
case StartupState::DONE:
|
||||
if (jcfgCountdown.isBusy()) {
|
||||
startupState = StartupState::WAIT_JCFG;
|
||||
return;
|
||||
}
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
case StartupState::WAIT_JCFG: {
|
||||
if (jcfgCountdown.hasTimedOut()) {
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
solutionSet.setReportingEnabled(true);
|
||||
startupState = StartupState::DONE;
|
||||
internalState = InternalState::IDLE;
|
||||
setMode(_MODE_TO_ON);
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doShutDown() {
|
||||
// If the star tracker is shutdown also stop all running processes in the image loader task
|
||||
strHelper->stopProcess();
|
||||
internalState = InternalState::IDLE;
|
||||
startupState = StartupState::IDLE;
|
||||
bootState = FwBootState::NONE;
|
||||
solutionSet.setReportingEnabled(false);
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
Submode_t StarTrackerHandler::getInitialSubmode() { return startracker::SUBMODE_BOOTLOADER; }
|
||||
|
||||
ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
if (strHelperHandlingSpecialRequest) {
|
||||
@ -313,6 +316,8 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t
|
||||
if (bootCountdown.isBusy()) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
// Was already done.
|
||||
reinitNextSetParam = false;
|
||||
bootState = FwBootState::REQ_VERSION;
|
||||
}
|
||||
switch (bootState) {
|
||||
@ -461,7 +466,8 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::SUBSCRIPTION): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.subscription);
|
||||
result =
|
||||
prepareParamCommand(commandData, commandDataLen, jcfgs.subscription, reinitNextSetParam);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_SOLUTION): {
|
||||
@ -477,55 +483,60 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::LIMITS): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.limits);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.limits, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::MOUNTING): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.mounting);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.mounting, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::IMAGE_PROCESSOR): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.imageProcessor);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.imageProcessor,
|
||||
reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::CAMERA): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.camera);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.camera, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::CENTROIDING): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.centroiding);
|
||||
result =
|
||||
prepareParamCommand(commandData, commandDataLen, jcfgs.centroiding, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LISA): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.lisa);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.lisa, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::MATCHING): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.matching);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.matching, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::VALIDATION): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.validation);
|
||||
result =
|
||||
prepareParamCommand(commandData, commandDataLen, jcfgs.validation, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::ALGO): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.algo);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.algo, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::TRACKING): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.tracking);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.tracking, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LOGLEVEL): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LOGSUBSCRIPTION): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription);
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription,
|
||||
reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::DEBUG_CAMERA): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.debugCamera);
|
||||
result =
|
||||
prepareParamCommand(commandData, commandDataLen, jcfgs.debugCamera, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::CHECKSUM): {
|
||||
@ -694,7 +705,7 @@ ReturnValue_t StarTrackerHandler::isModeCombinationValid(Mode_t mode, Submode_t
|
||||
return INVALID_SUBMODE;
|
||||
}
|
||||
case MODE_ON:
|
||||
if (submode == SUBMODE_BOOTLOADER || submode == SUBMODE_FIRMWARE) {
|
||||
if (submode == startracker::SUBMODE_BOOTLOADER || submode == startracker::SUBMODE_FIRMWARE) {
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
return INVALID_SUBMODE;
|
||||
@ -725,6 +736,7 @@ void StarTrackerHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doOnTransition(Submode_t subModeFrom) {
|
||||
using namespace startracker;
|
||||
uint8_t dhbSubmode = getSubmode();
|
||||
// We hide that the transition to submode firmware actually goes through the submode bootloader.
|
||||
// This is because the startracker always starts in bootloader mode but we want to allow direct
|
||||
@ -751,6 +763,7 @@ void StarTrackerHandler::doOnTransition(Submode_t subModeFrom) {
|
||||
}
|
||||
|
||||
void StarTrackerHandler::doNormalTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
using namespace startracker;
|
||||
if (subModeFrom == SUBMODE_FIRMWARE) {
|
||||
setMode(MODE_NORMAL);
|
||||
} else if (subModeFrom == SUBMODE_BOOTLOADER) {
|
||||
@ -776,7 +789,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
|
||||
if (toMode == MODE_NORMAL) {
|
||||
setMode(toMode, 0);
|
||||
} else {
|
||||
setMode(toMode, SUBMODE_FIRMWARE);
|
||||
setMode(toMode, startracker::SUBMODE_FIRMWARE);
|
||||
}
|
||||
sif::info << "STR: Firmware boot success" << std::endl;
|
||||
internalState = InternalState::IDLE;
|
||||
@ -820,7 +833,6 @@ void StarTrackerHandler::bootBootloader() {
|
||||
ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
||||
DeviceCommandId_t* foundId, size_t* foundLen) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
size_t bytesLeft = 0;
|
||||
|
||||
if (remainingSize == 0) {
|
||||
*foundLen = remainingSize;
|
||||
@ -834,24 +846,24 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
|
||||
|
||||
switch (startracker::getReplyFrameType(start)) {
|
||||
case TMTC_ACTIONREPLY: {
|
||||
*foundLen = remainingSize - bytesLeft;
|
||||
result = scanForActionReply(startracker::getId(start), foundId);
|
||||
*foundLen = remainingSize;
|
||||
return scanForActionReply(startracker::getId(start), foundId);
|
||||
break;
|
||||
}
|
||||
case TMTC_SETPARAMREPLY: {
|
||||
*foundLen = remainingSize - bytesLeft;
|
||||
result = scanForSetParameterReply(startracker::getId(start), foundId);
|
||||
*foundLen = remainingSize;
|
||||
return scanForSetParameterReply(startracker::getId(start), foundId);
|
||||
break;
|
||||
}
|
||||
case TMTC_PARAMREPLY: {
|
||||
*foundLen = remainingSize - bytesLeft;
|
||||
result = scanForGetParameterReply(startracker::getId(start), foundId);
|
||||
*foundLen = remainingSize;
|
||||
return scanForGetParameterReply(startracker::getId(start), foundId);
|
||||
break;
|
||||
}
|
||||
case TMTC_TELEMETRYREPLYA:
|
||||
case TMTC_TELEMETRYREPLY: {
|
||||
*foundLen = remainingSize - bytesLeft;
|
||||
result = scanForTmReply(startracker::getId(start), foundId);
|
||||
*foundLen = remainingSize;
|
||||
return scanForTmReply(startracker::getId(start), foundId);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -859,9 +871,6 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
|
||||
result = returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
remainingSize = bytesLeft;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1690,12 +1699,19 @@ void StarTrackerHandler::prepareHistogramRequest() {
|
||||
|
||||
ReturnValue_t StarTrackerHandler::prepareParamCommand(const uint8_t* commandData,
|
||||
size_t commandDataLen,
|
||||
ArcsecJsonParamBase& paramSet) {
|
||||
ArcsecJsonParamBase& paramSet,
|
||||
bool reinitSet) {
|
||||
// Stopwatch watch;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (commandDataLen > MAX_PATH_SIZE) {
|
||||
return FILE_PATH_TOO_LONG;
|
||||
}
|
||||
if (reinitSet) {
|
||||
result = paramSet.init(paramJsonFile);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result = paramSet.create(commandBuffer);
|
||||
if (result != returnvalue::OK) {
|
||||
|
@ -54,9 +54,6 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
|
||||
Submode_t getInitialSubmode() override;
|
||||
|
||||
static const Submode_t SUBMODE_BOOTLOADER = 1;
|
||||
static const Submode_t SUBMODE_FIRMWARE = 2;
|
||||
|
||||
protected:
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
@ -287,6 +284,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
|
||||
InternalState internalState = InternalState::IDLE;
|
||||
|
||||
bool reinitNextSetParam = false;
|
||||
|
||||
bool strHelperHandlingSpecialRequest = false;
|
||||
|
||||
const power::Switch_t powerSwitch = power::NO_SWITCH;
|
||||
@ -409,7 +408,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
* @return returnvalue::OK if successful, otherwise error return Value
|
||||
*/
|
||||
ReturnValue_t prepareParamCommand(const uint8_t* commandData, size_t commandDataLen,
|
||||
ArcsecJsonParamBase& paramSet);
|
||||
ArcsecJsonParamBase& paramSet, bool reinitSet);
|
||||
|
||||
/**
|
||||
* @brief The following function will fill the command buffer with the command to request
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
namespace startracker {
|
||||
|
||||
static const Submode_t SUBMODE_BOOTLOADER = 1;
|
||||
static const Submode_t SUBMODE_FIRMWARE = 2;
|
||||
|
||||
/**
|
||||
* @brief Returns the frame type field of a decoded frame.
|
||||
*/
|
||||
|
@ -1,2 +1,11 @@
|
||||
target_sources(${LIB_EIVE_MISSION} PRIVATE SyrlinksHandler.cpp
|
||||
CcsdsIpCoreHandler.cpp)
|
||||
target_sources(
|
||||
${LIB_EIVE_MISSION}
|
||||
PRIVATE SyrlinksHandler.cpp
|
||||
CcsdsIpCoreHandler.cpp
|
||||
LiveTmTask.cpp
|
||||
PersistentLogTmStoreTask.cpp
|
||||
TmStoreTaskBase.cpp
|
||||
VirtualChannel.cpp
|
||||
VirtualChannelWithQueue.cpp
|
||||
PersistentSingleTmStoreTask.cpp
|
||||
LiveTmTask.cpp)
|
||||
|
@ -15,9 +15,11 @@
|
||||
|
||||
CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDestination,
|
||||
PtmeConfig& ptmeConfig, std::atomic_bool& linkState,
|
||||
GpioIF* gpioIF, PtmeGpios gpioIds)
|
||||
GpioIF* gpioIF, PtmeGpios gpioIds,
|
||||
std::atomic_bool& ptmeLocked)
|
||||
: SystemObject(objectId),
|
||||
linkState(linkState),
|
||||
ptmeLocked(ptmeLocked),
|
||||
tcDestination(tcDestination),
|
||||
parameterHelper(this),
|
||||
actionHelper(this, nullptr),
|
||||
@ -29,12 +31,14 @@ CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDesti
|
||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
||||
eventQueue =
|
||||
QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
||||
ptmeLocked = true;
|
||||
}
|
||||
|
||||
CcsdsIpCoreHandler::~CcsdsIpCoreHandler() = default;
|
||||
|
||||
ReturnValue_t CcsdsIpCoreHandler::performOperation(uint8_t operationCode) {
|
||||
readCommandQueue();
|
||||
performPtmeUpdateWhenApplicable();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -71,11 +75,11 @@ ReturnValue_t CcsdsIpCoreHandler::initialize() {
|
||||
}
|
||||
|
||||
// This also pulls the PTME out of reset state.
|
||||
if (batPriorityParam == 0) {
|
||||
disablePrioritySelectMode();
|
||||
} else {
|
||||
enablePrioritySelectMode();
|
||||
}
|
||||
updateBatPriorityFromParam();
|
||||
ptmeConfig.setPollThreshold(
|
||||
static_cast<AxiPtmeConfig::IdlePollThreshold>(params.pollThresholdParam));
|
||||
resetPtme();
|
||||
ptmeLocked = false;
|
||||
|
||||
#if OBSW_SYRLINKS_SIMULATED == 1
|
||||
// Update data on rising edge
|
||||
@ -117,7 +121,10 @@ ReturnValue_t CcsdsIpCoreHandler::getParameter(uint8_t domainId, uint8_t uniqueI
|
||||
ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if ((domainId == 0) and (uniqueIdentifier == ParamId::BAT_PRIORITY)) {
|
||||
if (domainId != 0) {
|
||||
return HasParametersIF::INVALID_DOMAIN_ID;
|
||||
}
|
||||
if (uniqueIdentifier == ParamId::BAT_PRIORITY) {
|
||||
uint8_t newVal = 0;
|
||||
ReturnValue_t result = newValues->getElement(&newVal);
|
||||
if (result != returnvalue::OK) {
|
||||
@ -126,11 +133,33 @@ ReturnValue_t CcsdsIpCoreHandler::getParameter(uint8_t domainId, uint8_t uniqueI
|
||||
if (newVal > 1) {
|
||||
return HasParametersIF::INVALID_VALUE;
|
||||
}
|
||||
parameterWrapper->set(batPriorityParam);
|
||||
if (mode == MODE_ON) {
|
||||
updateBatPriorityOnTxOff = true;
|
||||
} else if (mode == MODE_OFF) {
|
||||
updateBatPriorityFromParam();
|
||||
parameterWrapper->set(params.batPriorityParam);
|
||||
if (newVal != params.batPriorityParam) {
|
||||
// This ensures that the BAT priority is updated at some point when an update of the PTME is
|
||||
// allowed
|
||||
updateContext.updateBatPrio = true;
|
||||
// If we are off, we can do the update after X cycles. Otherwise, wait until the transmitter
|
||||
// goes off.
|
||||
if (mode == MODE_OFF) {
|
||||
initPtmeUpdateAfterXCycles();
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
} else if (uniqueIdentifier == ParamId::POLL_THRESHOLD) {
|
||||
uint8_t newVal = 0;
|
||||
ReturnValue_t result = newValues->getElement(&newVal);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (newVal > static_cast<uint8_t>(AxiPtmeConfig::NEVER)) {
|
||||
return HasParametersIF::INVALID_VALUE;
|
||||
}
|
||||
parameterWrapper->set(newVal);
|
||||
if (newVal != params.pollThresholdParam) {
|
||||
updateContext.updatePollThreshold = true;
|
||||
if (mode == MODE_OFF) {
|
||||
initPtmeUpdateAfterXCycles();
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@ -148,50 +177,33 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
const uint8_t* data, size_t size) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
switch (actionId) {
|
||||
case SET_LOW_RATE: {
|
||||
submode = static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW);
|
||||
result = ptmeConfig.setRate(RATE_100KBPS);
|
||||
break;
|
||||
}
|
||||
case SET_HIGH_RATE: {
|
||||
submode = static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH);
|
||||
result = ptmeConfig.setRate(RATE_500KBPS);
|
||||
break;
|
||||
}
|
||||
case ARBITRARY_RATE: {
|
||||
uint32_t bitrate = 0;
|
||||
SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG);
|
||||
result = ptmeConfig.setRate(bitrate);
|
||||
result = SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
ptmeConfig.setRate(bitrate);
|
||||
updateContext.updateClockRate = true;
|
||||
if (mode == MODE_OFF) {
|
||||
initPtmeUpdateAfterXCycles();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EN_TRANSMITTER: {
|
||||
enableTransmit();
|
||||
if (mode == HasModesIF::MODE_OFF) {
|
||||
mode = HasModesIF::MODE_ON;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case DISABLE_TRANSMITTER: {
|
||||
disableTransmit();
|
||||
if (mode == HasModesIF::MODE_ON) {
|
||||
mode = HasModesIF::MODE_OFF;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case ENABLE_TX_CLK_MANIPULATOR: {
|
||||
result = ptmeConfig.configTxManipulator(true);
|
||||
ptmeConfig.configTxManipulator(true);
|
||||
break;
|
||||
}
|
||||
case DISABLE_TX_CLK_MANIPULATOR: {
|
||||
result = ptmeConfig.configTxManipulator(false);
|
||||
ptmeConfig.configTxManipulator(false);
|
||||
break;
|
||||
}
|
||||
case UPDATE_ON_RISING_EDGE: {
|
||||
result = ptmeConfig.invertTxClock(false);
|
||||
ptmeConfig.invertTxClock(false);
|
||||
break;
|
||||
}
|
||||
case UPDATE_ON_FALLING_EDGE: {
|
||||
result = ptmeConfig.invertTxClock(true);
|
||||
ptmeConfig.invertTxClock(true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -206,12 +218,8 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu
|
||||
void CcsdsIpCoreHandler::updateLinkState() { linkState = LINK_UP; }
|
||||
|
||||
void CcsdsIpCoreHandler::enableTransmit() {
|
||||
// Reset PTME on each transmit enable.
|
||||
updateBatPriorityFromParam();
|
||||
#ifndef TE0720_1CFA
|
||||
gpioIF->pullHigh(ptmeGpios.enableTxClock);
|
||||
gpioIF->pullHigh(ptmeGpios.enableTxData);
|
||||
#endif
|
||||
linkState = LINK_UP;
|
||||
}
|
||||
|
||||
@ -236,34 +244,23 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
|
||||
auto rateSet = [&](uint32_t rate) {
|
||||
ReturnValue_t result = ptmeConfig.setRate(rate);
|
||||
if (result == returnvalue::OK) {
|
||||
this->mode = HasModesIF::MODE_ON;
|
||||
}
|
||||
};
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
if (mode == HasModesIF::MODE_ON) {
|
||||
enableTransmit();
|
||||
if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_DEFAULT)) {
|
||||
com::Datarate currentDatarate = com::getCurrentDatarate();
|
||||
if (currentDatarate == com::Datarate::LOW_RATE_MODULATION_BPSK) {
|
||||
rateSet(RATE_100KBPS);
|
||||
} else if (currentDatarate == com::Datarate::HIGH_RATE_MODULATION_0QPSK) {
|
||||
rateSet(RATE_500KBPS);
|
||||
}
|
||||
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH)) {
|
||||
rateSet(RATE_500KBPS);
|
||||
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW)) {
|
||||
rateSet(RATE_100KBPS);
|
||||
if (this->submode != submode) {
|
||||
initPtmeUpdateAfterXCycles();
|
||||
updateContext.enableTransmitAfterPtmeUpdate = true;
|
||||
updateContext.updateClockRate = true;
|
||||
this->submode = submode;
|
||||
this->mode = mode;
|
||||
updateContext.setModeAfterUpdate = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// No rate change, so enable transmitter right away.
|
||||
enableTransmit();
|
||||
} else if (mode == HasModesIF::MODE_OFF) {
|
||||
disableTransmit();
|
||||
this->mode = HasModesIF::MODE_OFF;
|
||||
}
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
setMode(mode, submode);
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
|
||||
@ -274,9 +271,9 @@ void CcsdsIpCoreHandler::disableTransmit() {
|
||||
gpioIF->pullLow(ptmeGpios.enableTxData);
|
||||
#endif
|
||||
linkState = LINK_DOWN;
|
||||
if (updateBatPriorityOnTxOff) {
|
||||
updateBatPriorityFromParam();
|
||||
updateBatPriorityOnTxOff = false;
|
||||
// Some parameters need update and transmitter is off now.
|
||||
if (updateContext.updateBatPrio or updateContext.updateClockRate) {
|
||||
initPtmeUpdateAfterXCycles();
|
||||
}
|
||||
}
|
||||
|
||||
@ -294,26 +291,95 @@ ModeTreeChildIF& CcsdsIpCoreHandler::getModeTreeChildIF() { return *this; }
|
||||
|
||||
object_id_t CcsdsIpCoreHandler::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
void CcsdsIpCoreHandler::enablePrioritySelectMode() {
|
||||
ptmeConfig.enableBatPriorityBit(true);
|
||||
// Reset the PTME
|
||||
gpioIF->pullLow(ptmeGpios.ptmeResetn);
|
||||
usleep(10);
|
||||
gpioIF->pullHigh(ptmeGpios.ptmeResetn);
|
||||
}
|
||||
void CcsdsIpCoreHandler::enablePrioritySelectMode() { ptmeConfig.enableBatPriorityBit(true); }
|
||||
|
||||
void CcsdsIpCoreHandler::disablePrioritySelectMode() {
|
||||
ptmeConfig.enableBatPriorityBit(false);
|
||||
// Reset the PTME
|
||||
gpioIF->pullLow(ptmeGpios.ptmeResetn);
|
||||
usleep(10);
|
||||
gpioIF->pullHigh(ptmeGpios.ptmeResetn);
|
||||
}
|
||||
void CcsdsIpCoreHandler::disablePrioritySelectMode() { ptmeConfig.enableBatPriorityBit(false); }
|
||||
|
||||
void CcsdsIpCoreHandler::updateBatPriorityFromParam() {
|
||||
if (batPriorityParam == 0) {
|
||||
if (params.batPriorityParam == 0) {
|
||||
disablePrioritySelectMode();
|
||||
} else {
|
||||
enablePrioritySelectMode();
|
||||
}
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::setMode(Mode_t mode, Submode_t submode) {
|
||||
this->submode = submode;
|
||||
this->mode = mode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::performPtmeUpdateWhenApplicable() {
|
||||
if (not updateContext.performPtmeUpdateAfterXCycles) {
|
||||
return;
|
||||
}
|
||||
if (updateContext.ptmeUpdateCycleCount >= 2) {
|
||||
bool doResetPtme = false;
|
||||
if (updateContext.updateBatPrio) {
|
||||
updateBatPriorityFromParam();
|
||||
updateContext.updateBatPrio = false;
|
||||
doResetPtme = true;
|
||||
}
|
||||
if (updateContext.updatePollThreshold) {
|
||||
ptmeConfig.setPollThreshold(
|
||||
static_cast<AxiPtmeConfig::IdlePollThreshold>(params.pollThresholdParam));
|
||||
updateContext.updatePollThreshold = false;
|
||||
doResetPtme = true;
|
||||
}
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (updateContext.updateClockRate) {
|
||||
if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_DEFAULT)) {
|
||||
com::Datarate currentDatarate = com::getCurrentDatarate();
|
||||
if (currentDatarate == com::Datarate::LOW_RATE_MODULATION_BPSK) {
|
||||
result = ptmeConfig.setRate(RATE_100KBPS);
|
||||
} else if (currentDatarate == com::Datarate::HIGH_RATE_MODULATION_0QPSK) {
|
||||
result = ptmeConfig.setRate(RATE_500KBPS);
|
||||
}
|
||||
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH)) {
|
||||
result = ptmeConfig.setRate(RATE_500KBPS);
|
||||
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW)) {
|
||||
result = ptmeConfig.setRate(RATE_100KBPS);
|
||||
}
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "CcsdsIpCoreHandler: Setting datarate failed" << std::endl;
|
||||
}
|
||||
updateContext.updateClockRate = false;
|
||||
doResetPtme = true;
|
||||
}
|
||||
finishPtmeUpdateAfterXCycles(doResetPtme);
|
||||
return;
|
||||
}
|
||||
updateContext.ptmeUpdateCycleCount++;
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::resetPtme() {
|
||||
gpioIF->pullLow(ptmeGpios.ptmeResetn);
|
||||
usleep(10);
|
||||
gpioIF->pullHigh(ptmeGpios.ptmeResetn);
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::initPtmeUpdateAfterXCycles() {
|
||||
if (not updateContext.performPtmeUpdateAfterXCycles) {
|
||||
updateContext.performPtmeUpdateAfterXCycles = true;
|
||||
updateContext.ptmeUpdateCycleCount = 0;
|
||||
ptmeLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
void CcsdsIpCoreHandler::finishPtmeUpdateAfterXCycles(bool doResetPtme) {
|
||||
if (doResetPtme) {
|
||||
resetPtme();
|
||||
}
|
||||
ptmeLocked = false;
|
||||
updateContext.performPtmeUpdateAfterXCycles = false;
|
||||
updateContext.ptmeUpdateCycleCount = 0;
|
||||
if (updateContext.enableTransmitAfterPtmeUpdate) {
|
||||
enableTransmit();
|
||||
updateContext.enableTransmitAfterPtmeUpdate = false;
|
||||
}
|
||||
if (updateContext.setModeAfterUpdate) {
|
||||
setMode(mode, submode);
|
||||
updateContext.setModeAfterUpdate = false;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define CCSDSHANDLER_H_
|
||||
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
@ -60,7 +60,7 @@ class CcsdsIpCoreHandler : public SystemObject,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public HasActionsIF {
|
||||
public:
|
||||
enum ParamId : uint8_t { BAT_PRIORITY = 0 };
|
||||
enum ParamId : uint8_t { BAT_PRIORITY = 0, POLL_THRESHOLD = 1 };
|
||||
|
||||
static const bool LINK_UP = true;
|
||||
static const bool LINK_DOWN = false;
|
||||
@ -79,7 +79,8 @@ class CcsdsIpCoreHandler : public SystemObject,
|
||||
* @param enTxData GPIO ID of RS485 tx data enable
|
||||
*/
|
||||
CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDestination, PtmeConfig& ptmeConfig,
|
||||
std::atomic_bool& linkState, GpioIF* gpioIF, PtmeGpios gpioIds);
|
||||
std::atomic_bool& linkState, GpioIF* gpioIF, PtmeGpios gpioIds,
|
||||
std::atomic_bool& ptmeLocked);
|
||||
|
||||
~CcsdsIpCoreHandler();
|
||||
|
||||
@ -137,9 +138,8 @@ class CcsdsIpCoreHandler : public SystemObject,
|
||||
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xA0);
|
||||
|
||||
// using VirtualChannelMap = std::unordered_map<VcId_t, VirtualChannelWithQueue*>;
|
||||
// VirtualChannelMap virtualChannelMap;
|
||||
std::atomic_bool& linkState;
|
||||
std::atomic_bool& ptmeLocked;
|
||||
|
||||
object_id_t tcDestination;
|
||||
|
||||
@ -156,9 +156,22 @@ class CcsdsIpCoreHandler : public SystemObject,
|
||||
|
||||
PtmeConfig& ptmeConfig;
|
||||
PtmeGpios ptmeGpios;
|
||||
// BAT priority bit on by default to enable priority selection mode for the PTME.
|
||||
uint8_t batPriorityParam = 0;
|
||||
bool updateBatPriorityOnTxOff = false;
|
||||
struct Parameters {
|
||||
// BAT priority bit on by default to enable priority selection mode for the PTME.
|
||||
uint8_t batPriorityParam = 0;
|
||||
uint8_t pollThresholdParam = static_cast<uint8_t>(AxiPtmeConfig::IdlePollThreshold::POLL_4);
|
||||
|
||||
} params;
|
||||
|
||||
struct UpdateContext {
|
||||
bool updateBatPrio = false;
|
||||
bool updateClockRate = false;
|
||||
bool updatePollThreshold = false;
|
||||
bool enableTransmitAfterPtmeUpdate = false;
|
||||
uint8_t ptmeUpdateCycleCount = 0;
|
||||
bool performPtmeUpdateAfterXCycles = false;
|
||||
bool setModeAfterUpdate = false;
|
||||
} updateContext{};
|
||||
|
||||
GpioIF* gpioIF = nullptr;
|
||||
|
||||
@ -180,6 +193,8 @@ class CcsdsIpCoreHandler : public SystemObject,
|
||||
*/
|
||||
void disableTransmit();
|
||||
|
||||
void performPtmeUpdateWhenApplicable();
|
||||
|
||||
/**
|
||||
* The following set of functions configure the mode of the PTME bandwith allocation table (BAT)
|
||||
* module. This consists of the following 2 steps:
|
||||
@ -189,6 +204,11 @@ class CcsdsIpCoreHandler : public SystemObject,
|
||||
void enablePrioritySelectMode();
|
||||
void disablePrioritySelectMode();
|
||||
void updateBatPriorityFromParam();
|
||||
|
||||
void setMode(Mode_t mode, Submode_t submode);
|
||||
void resetPtme();
|
||||
void initPtmeUpdateAfterXCycles();
|
||||
void finishPtmeUpdateAfterXCycles(bool doResetPtme);
|
||||
};
|
||||
|
||||
#endif /* CCSDSHANDLER_H_ */
|
||||
|
107
mission/com/LiveTmTask.cpp
Normal file
107
mission/com/LiveTmTask.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "LiveTmTask.h"
|
||||
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/subsystem/helper.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
|
||||
LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
|
||||
VirtualChannelWithQueue& channel, const std::atomic_bool& ptmeLocked)
|
||||
: SystemObject(objectId),
|
||||
modeHelper(this),
|
||||
pusFunnel(pusFunnel),
|
||||
cfdpFunnel(cfdpFunnel),
|
||||
channel(channel),
|
||||
ptmeLocked(ptmeLocked) {
|
||||
requestQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
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);
|
||||
if (result == DirectTmSinkIF::IS_BUSY) {
|
||||
sif::error << "Lost live TM, PAPB busy" << std::endl;
|
||||
}
|
||||
if (result == MessageQueueIF::EMPTY) {
|
||||
if (tmFunnelCd.hasTimedOut()) {
|
||||
pusFunnel.performOperation(0);
|
||||
cfdpFunnel.performOperation(0);
|
||||
tmFunnelCd.resetTimer();
|
||||
}
|
||||
// Read command queue during idle times.
|
||||
readCommandQueue();
|
||||
// 40 ms IDLE delay. Might tweak this in the future.
|
||||
TaskFactory::delayTask(40);
|
||||
} else {
|
||||
packetCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t LiveTmTask::getCommandQueue() const { return requestQueue->getId(); }
|
||||
|
||||
void LiveTmTask::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
if (mode != nullptr) {
|
||||
*mode = this->mode;
|
||||
}
|
||||
if (submode != nullptr) {
|
||||
*submode = SUBMODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t LiveTmTask::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) {
|
||||
if (mode == MODE_ON or mode == MODE_OFF) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
void LiveTmTask::startTransition(Mode_t mode, Submode_t submode) {
|
||||
this->mode = mode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
}
|
||||
|
||||
void LiveTmTask::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, SUBMODE_NONE); }
|
||||
|
||||
object_id_t LiveTmTask::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
const HasHealthIF* LiveTmTask::getOptHealthIF() const { return nullptr; }
|
||||
|
||||
const HasModesIF& LiveTmTask::getModeIF() const { return *this; }
|
||||
|
||||
ReturnValue_t LiveTmTask::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
||||
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
|
||||
}
|
||||
|
||||
void LiveTmTask::readCommandQueue(void) {
|
||||
CommandMessage commandMessage;
|
||||
ReturnValue_t result = returnvalue::FAILED;
|
||||
|
||||
result = requestQueue->receiveMessage(&commandMessage);
|
||||
if (result == returnvalue::OK) {
|
||||
result = modeHelper.handleModeCommand(&commandMessage);
|
||||
if (result == returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
|
||||
requestQueue->reply(&reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ModeTreeChildIF& LiveTmTask::getModeTreeChildIF() { return *this; }
|
||||
|
||||
ReturnValue_t LiveTmTask::initialize() {
|
||||
modeHelper.initialize();
|
||||
return returnvalue::OK;
|
||||
}
|
57
mission/com/LiveTmTask.h
Normal file
57
mission/com/LiveTmTask.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef MISSION_TMTC_LIVETMTASK_H_
|
||||
#define MISSION_TMTC_LIVETMTASK_H_
|
||||
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/subsystem/ModeTreeChildIF.h>
|
||||
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/timemanager/Countdown.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
#include <mission/tmtc/CfdpTmFunnel.h>
|
||||
#include <mission/tmtc/PusTmFunnel.h>
|
||||
|
||||
class LiveTmTask : public SystemObject,
|
||||
public HasModesIF,
|
||||
public ExecutableObjectIF,
|
||||
public ModeTreeChildIF,
|
||||
public ModeTreeConnectionIF {
|
||||
public:
|
||||
LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
|
||||
VirtualChannelWithQueue& channel, const std::atomic_bool& ptmeLocked);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
|
||||
|
||||
private:
|
||||
MessageQueueIF* requestQueue;
|
||||
ModeHelper modeHelper;
|
||||
Mode_t mode = HasModesIF::MODE_OFF;
|
||||
Countdown tmFunnelCd = Countdown(100);
|
||||
PusTmFunnel& pusFunnel;
|
||||
CfdpTmFunnel& cfdpFunnel;
|
||||
VirtualChannelWithQueue& channel;
|
||||
uint32_t packetCounter = 0;
|
||||
const std::atomic_bool& ptmeLocked;
|
||||
|
||||
void readCommandQueue(void);
|
||||
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
void getMode(Mode_t* mode, Submode_t* submode) override;
|
||||
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) override;
|
||||
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
|
||||
void announceMode(bool recursive) override;
|
||||
|
||||
object_id_t getObjectId() const override;
|
||||
const HasHealthIF* getOptHealthIF() const override;
|
||||
const HasModesIF& getModeIF() const override;
|
||||
ModeTreeChildIF& getModeTreeChildIF() override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_LIVETMTASK_H_ */
|
@ -5,8 +5,9 @@
|
||||
|
||||
PersistentLogTmStoreTask::PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore,
|
||||
LogStores stores, VirtualChannel& channel,
|
||||
SdCardMountedIF& sdcMan)
|
||||
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan),
|
||||
SdCardMountedIF& sdcMan,
|
||||
const std::atomic_bool& ptmeLocked)
|
||||
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan, ptmeLocked),
|
||||
stores(stores),
|
||||
okStoreContext(persTmStore::DUMP_OK_STORE_DONE, persTmStore::DUMP_OK_CANCELLED),
|
||||
notOkStoreContext(persTmStore::DUMP_NOK_STORE_DONE, persTmStore::DUMP_NOK_CANCELLED),
|
||||
@ -27,6 +28,8 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
|
||||
}
|
||||
};
|
||||
while (true) {
|
||||
readCommandQueue();
|
||||
|
||||
if (not cyclicStoreCheck()) {
|
||||
continue;
|
||||
}
|
||||
@ -40,6 +43,7 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
|
||||
TaskFactory::delayTask(100);
|
||||
} else if (vcBusyDuringDump) {
|
||||
// TODO: Might not be necessary
|
||||
sif::debug << "VC busy, delaying" << std::endl;
|
||||
TaskFactory::delayTask(10);
|
||||
}
|
||||
}
|
||||
@ -54,3 +58,17 @@ bool PersistentLogTmStoreTask::initStoresIfPossible() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PersistentLogTmStoreTask::startTransition(Mode_t mode, Submode_t submode) {
|
||||
if (mode == MODE_OFF) {
|
||||
bool channelIsOn = channel.isTxOn();
|
||||
cancelDump(okStoreContext, stores.okStore, channelIsOn);
|
||||
cancelDump(notOkStoreContext, stores.notOkStore, channelIsOn);
|
||||
cancelDump(miscStoreContext, stores.miscStore, channelIsOn);
|
||||
this->mode = MODE_OFF;
|
||||
} else if (mode == MODE_ON) {
|
||||
this->mode = MODE_ON;
|
||||
}
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
}
|
@ -5,11 +5,11 @@
|
||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||
#include <mission/com/TmStoreTaskBase.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
#include <mission/genericFactory.h>
|
||||
#include <mission/tmtc/PersistentTmStore.h>
|
||||
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
|
||||
#include <mission/tmtc/TmStoreTaskBase.h>
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
|
||||
struct LogStores {
|
||||
LogStores(PersistentTmStores& stores)
|
||||
@ -22,7 +22,8 @@ struct LogStores {
|
||||
class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF {
|
||||
public:
|
||||
PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, LogStores tmStore,
|
||||
VirtualChannel& channel, SdCardMountedIF& sdcMan);
|
||||
VirtualChannel& channel, SdCardMountedIF& sdcMan,
|
||||
const std::atomic_bool& ptmeLocked);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
|
||||
@ -36,6 +37,7 @@ class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObject
|
||||
bool someFileWasSwapped = false;
|
||||
|
||||
bool initStoresIfPossible() override;
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_PERSISTENTLOGTMSTORETASK_H_ */
|
@ -1,17 +1,21 @@
|
||||
#include "PersistentSingleTmStoreTask.h"
|
||||
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <mission/tmtc/PersistentSingleTmStoreTask.h>
|
||||
#include <unistd.h>
|
||||
|
||||
PersistentSingleTmStoreTask::PersistentSingleTmStoreTask(
|
||||
object_id_t objectId, StorageManagerIF& ipcStore, PersistentTmStoreWithTmQueue& tmStore,
|
||||
VirtualChannel& channel, Event eventIfDumpDone, Event eventIfCancelled, SdCardMountedIF& sdcMan)
|
||||
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan),
|
||||
VirtualChannel& channel, Event eventIfDumpDone, Event eventIfCancelled, SdCardMountedIF& sdcMan,
|
||||
const std::atomic_bool& ptmeLocked)
|
||||
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan, ptmeLocked),
|
||||
storeWithQueue(tmStore),
|
||||
dumpContext(eventIfDumpDone, eventIfCancelled) {}
|
||||
|
||||
ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
|
||||
while (true) {
|
||||
readCommandQueue();
|
||||
|
||||
// Delay done by the check
|
||||
if (not cyclicStoreCheck()) {
|
||||
continue;
|
||||
@ -20,8 +24,12 @@ 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.
|
||||
TaskFactory::delayTask(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,3 +41,14 @@ bool PersistentSingleTmStoreTask::initStoresIfPossible() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PersistentSingleTmStoreTask::startTransition(Mode_t mode, Submode_t submode) {
|
||||
if (mode == MODE_OFF) {
|
||||
cancelDump(dumpContext, storeWithQueue, channel.isTxOn());
|
||||
this->mode = MODE_OFF;
|
||||
} else if (mode == MODE_ON) {
|
||||
this->mode = MODE_ON;
|
||||
}
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
}
|
@ -3,16 +3,16 @@
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <mission/com/TmStoreTaskBase.h>
|
||||
#include <mission/com/VirtualChannel.h>
|
||||
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
|
||||
#include <mission/tmtc/TmStoreTaskBase.h>
|
||||
#include <mission/tmtc/VirtualChannel.h>
|
||||
|
||||
class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF {
|
||||
public:
|
||||
PersistentSingleTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore,
|
||||
PersistentTmStoreWithTmQueue& storeWithQueue, VirtualChannel& channel,
|
||||
Event eventIfDumpDone, Event eventIfCancelled,
|
||||
SdCardMountedIF& sdcMan);
|
||||
SdCardMountedIF& sdcMan, const std::atomic_bool& ptmeLocked);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
|
||||
@ -23,6 +23,8 @@ class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObj
|
||||
Countdown graceDelayDuringDumping = Countdown(100);
|
||||
|
||||
bool initStoresIfPossible() override;
|
||||
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_PERSISTENTSINGLETMSTORETASK_H_ */
|
@ -27,8 +27,9 @@ void SyrlinksHandler::doStartUp() {
|
||||
if (internalState == InternalState::ENABLE_TEMPERATURE_PROTECTION) {
|
||||
if (commandExecuted) {
|
||||
// Go to normal mode immediately and disable transmitter on startup.
|
||||
setMode(_MODE_TO_NORMAL);
|
||||
setMode(_MODE_TO_ON);
|
||||
internalState = InternalState::IDLE;
|
||||
transState = TransitionState::IDLE;
|
||||
commandExecuted = false;
|
||||
}
|
||||
}
|
||||
@ -36,14 +37,16 @@ void SyrlinksHandler::doStartUp() {
|
||||
|
||||
void SyrlinksHandler::doShutDown() {
|
||||
// In any case, always disable TX first.
|
||||
if (internalState != InternalState::SET_TX_STANDBY) {
|
||||
internalState = InternalState::SET_TX_STANDBY;
|
||||
if (internalState != InternalState::TX_TRANSITION) {
|
||||
internalState = InternalState::TX_TRANSITION;
|
||||
transState = TransitionState::SET_TX_STANDBY;
|
||||
commandExecuted = false;
|
||||
}
|
||||
if (internalState == InternalState::SET_TX_STANDBY) {
|
||||
if (internalState == InternalState::TX_TRANSITION) {
|
||||
if (commandExecuted) {
|
||||
temperatureSet.setValidity(false, true);
|
||||
internalState = InternalState::OFF;
|
||||
transState = TransitionState::IDLE;
|
||||
commandExecuted = false;
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
@ -97,33 +100,47 @@ ReturnValue_t SyrlinksHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
}
|
||||
|
||||
ReturnValue_t SyrlinksHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
||||
if (transState == TransitionState::CMD_PENDING or transState == TransitionState::DONE) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
switch (internalState) {
|
||||
case InternalState::ENABLE_TEMPERATURE_PROTECTION: {
|
||||
*id = syrlinks::WRITE_LCL_CONFIG;
|
||||
transState = TransitionState::CMD_PENDING;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case InternalState::SET_TX_MODULATION: {
|
||||
*id = syrlinks::SET_TX_MODE_MODULATION;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case InternalState::SELECT_MODULATION_BPSK: {
|
||||
*id = syrlinks::SET_WAVEFORM_BPSK;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case InternalState::SELECT_MODULATION_0QPSK: {
|
||||
*id = syrlinks::SET_WAVEFORM_0QPSK;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case InternalState::SET_TX_CW: {
|
||||
*id = syrlinks::SET_TX_MODE_CW;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case InternalState::SET_TX_STANDBY: {
|
||||
*id = syrlinks::SET_TX_MODE_STANDBY;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
default:
|
||||
case InternalState::TX_TRANSITION: {
|
||||
switch (transState) {
|
||||
case TransitionState::SET_TX_MODULATION: {
|
||||
*id = syrlinks::SET_TX_MODE_MODULATION;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case TransitionState::SELECT_MODULATION_BPSK: {
|
||||
*id = syrlinks::SET_WAVEFORM_BPSK;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case TransitionState::SELECT_MODULATION_0QPSK: {
|
||||
*id = syrlinks::SET_WAVEFORM_0QPSK;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case TransitionState::SET_TX_CW: {
|
||||
*id = syrlinks::SET_TX_MODE_CW;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case TransitionState::SET_TX_STANDBY: {
|
||||
*id = syrlinks::SET_TX_MODE_STANDBY;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
default: {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
}
|
||||
transState = TransitionState::CMD_PENDING;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
@ -442,7 +459,6 @@ ReturnValue_t SyrlinksHandler::interpretDeviceReply(DeviceCommandId_t id, const
|
||||
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
|
||||
}
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -620,8 +636,6 @@ void SyrlinksHandler::parseAgcHighByte(const uint8_t* packet) {
|
||||
agcValueHighByte = convertHexStringToUint8(reinterpret_cast<const char*>(packet + offset));
|
||||
}
|
||||
|
||||
void SyrlinksHandler::setNormalDatapoolEntriesInvalid() {}
|
||||
|
||||
uint32_t SyrlinksHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 2500; }
|
||||
|
||||
ReturnValue_t SyrlinksHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
@ -650,11 +664,11 @@ ReturnValue_t SyrlinksHandler::initializeLocalDataPool(localpool::DataPool& loca
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(rxDataset.getSid(), enableHkSets, 60.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(temperatureSet.getSid(), enableHkSets, 20.0));
|
||||
subdp::RegularHkPeriodicParams(temperatureSet.getSid(), enableHkSets, 120.0));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void SyrlinksHandler::setModeNormal() { setMode(MODE_NORMAL); }
|
||||
void SyrlinksHandler::setModeNormal() { setMode(_MODE_TO_NORMAL); }
|
||||
|
||||
float SyrlinksHandler::calcTempVal(uint16_t raw) { return 0.126984 * raw - 67.87; }
|
||||
|
||||
@ -673,15 +687,37 @@ ReturnValue_t SyrlinksHandler::handleAckReply(const uint8_t* packet) {
|
||||
break;
|
||||
}
|
||||
case (syrlinks::SET_WAVEFORM_BPSK):
|
||||
case (syrlinks::SET_WAVEFORM_0QPSK):
|
||||
case (syrlinks::SET_TX_MODE_STANDBY):
|
||||
case (syrlinks::SET_TX_MODE_MODULATION):
|
||||
case (syrlinks::SET_TX_MODE_CW): {
|
||||
case (syrlinks::SET_WAVEFORM_0QPSK): {
|
||||
if (result == returnvalue::OK and isTransitionalMode()) {
|
||||
transState = TransitionState::SET_TX_MODULATION;
|
||||
commandExecuted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (syrlinks::SET_TX_MODE_STANDBY): {
|
||||
if (result == returnvalue::OK and isTransitionalMode()) {
|
||||
transState = TransitionState::DONE;
|
||||
commandExecuted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (syrlinks::SET_TX_MODE_MODULATION): {
|
||||
if (result == returnvalue::OK and isTransitionalMode()) {
|
||||
transState = TransitionState::DONE;
|
||||
commandExecuted = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (syrlinks::SET_TX_MODE_CW): {
|
||||
if (result == returnvalue::OK and isTransitionalMode()) {
|
||||
commandExecuted = true;
|
||||
transState = TransitionState::DONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sif::error << "Syrlinks: Unexpected ACK reply" << std::endl;
|
||||
}
|
||||
}
|
||||
switch (rememberCommandId) {
|
||||
case (syrlinks::SET_TX_MODE_STANDBY): {
|
||||
@ -699,7 +735,7 @@ ReturnValue_t SyrlinksHandler::handleAckReply(const uint8_t* packet) {
|
||||
|
||||
ReturnValue_t SyrlinksHandler::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||
if (mode == HasModesIF::MODE_ON or mode == DeviceHandlerIF::MODE_NORMAL) {
|
||||
if (submode >= com::Submode::NUM_SUBMODES) {
|
||||
if (submode >= com::Submode::NUM_SUBMODES or submode < com::Submode::RX_ONLY) {
|
||||
return HasModesIF::INVALID_SUBMODE;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -726,68 +762,54 @@ void SyrlinksHandler::setDebugMode(bool enable) { this->debugMode = enable; }
|
||||
|
||||
void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
Mode_t tgtMode = getBaseMode(getMode());
|
||||
auto commandDone = [&]() {
|
||||
setMode(tgtMode);
|
||||
auto doneHandler = [&]() {
|
||||
internalState = InternalState::IDLE;
|
||||
transState = TransitionState::IDLE;
|
||||
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
|
||||
};
|
||||
auto txOnHandler = [&](InternalState selMod) {
|
||||
if (internalState == InternalState::IDLE) {
|
||||
commandExecuted = false;
|
||||
internalState = selMod;
|
||||
}
|
||||
// Select modulation first (BPSK or 0QPSK).
|
||||
if (internalState == selMod) {
|
||||
if (commandExecuted) {
|
||||
internalState = InternalState::SET_TX_MODULATION;
|
||||
commandExecuted = false;
|
||||
}
|
||||
}
|
||||
// Now go into modulation mode.
|
||||
if (internalState == InternalState::SET_TX_MODULATION) {
|
||||
if (commandExecuted) {
|
||||
commandDone();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (transState == TransitionState::DONE) {
|
||||
return doneHandler();
|
||||
}
|
||||
auto txStandbyHandler = [&]() {
|
||||
if (internalState == InternalState::IDLE) {
|
||||
internalState = InternalState::SET_TX_STANDBY;
|
||||
commandExecuted = false;
|
||||
}
|
||||
if (internalState == InternalState::SET_TX_STANDBY) {
|
||||
if (commandExecuted) {
|
||||
commandDone();
|
||||
return;
|
||||
}
|
||||
}
|
||||
txDataset.setReportingEnabled(false);
|
||||
poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0);
|
||||
transState = TransitionState::SET_TX_STANDBY;
|
||||
internalState = InternalState::TX_TRANSITION;
|
||||
};
|
||||
auto txOnHandler = [&](TransitionState tgtTransitionState) {
|
||||
txDataset.setReportingEnabled(true);
|
||||
poolManager.changeCollectionInterval(txDataset.getSid(), 10.0);
|
||||
poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0);
|
||||
transState = tgtTransitionState;
|
||||
internalState = InternalState::TX_TRANSITION;
|
||||
};
|
||||
|
||||
if (tgtMode == HasModesIF::MODE_ON or tgtMode == DeviceHandlerIF::MODE_NORMAL) {
|
||||
// If submode has not changed, no special transition handling necessary.
|
||||
if (getSubmode() == subModeFrom) {
|
||||
return doneHandler();
|
||||
}
|
||||
// Transition is on-going, wait for it to finish.
|
||||
if (transState != TransitionState::IDLE) {
|
||||
return;
|
||||
}
|
||||
// Transition start logic.
|
||||
switch (getSubmode()) {
|
||||
case (com::Submode::RX_AND_TX_DEFAULT_DATARATE): {
|
||||
auto currentDatarate = com::getCurrentDatarate();
|
||||
if (currentDatarate == com::Datarate::LOW_RATE_MODULATION_BPSK) {
|
||||
if (txOnHandler(InternalState::SELECT_MODULATION_BPSK)) {
|
||||
return;
|
||||
}
|
||||
txOnHandler(TransitionState::SELECT_MODULATION_BPSK);
|
||||
} else if (currentDatarate == com::Datarate::HIGH_RATE_MODULATION_0QPSK) {
|
||||
if (txOnHandler(InternalState::SELECT_MODULATION_0QPSK)) {
|
||||
return;
|
||||
}
|
||||
txOnHandler(TransitionState::SELECT_MODULATION_0QPSK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (com::Submode::RX_AND_TX_LOW_DATARATE): {
|
||||
if (txOnHandler(InternalState::SELECT_MODULATION_BPSK)) {
|
||||
return;
|
||||
}
|
||||
txOnHandler(TransitionState::SELECT_MODULATION_BPSK);
|
||||
break;
|
||||
}
|
||||
case (com::Submode::RX_AND_TX_HIGH_DATARATE): {
|
||||
if (txOnHandler(InternalState::SELECT_MODULATION_0QPSK)) {
|
||||
return;
|
||||
}
|
||||
txOnHandler(TransitionState::SELECT_MODULATION_0QPSK);
|
||||
break;
|
||||
}
|
||||
case (com::Submode::RX_ONLY): {
|
||||
@ -795,21 +817,17 @@ void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
return;
|
||||
}
|
||||
case (com::Submode::RX_AND_TX_CW): {
|
||||
if (internalState == InternalState::IDLE) {
|
||||
internalState = InternalState::SET_TX_STANDBY;
|
||||
commandExecuted = false;
|
||||
}
|
||||
if (commandExecuted) {
|
||||
commandDone();
|
||||
return;
|
||||
}
|
||||
txOnHandler(TransitionState::SET_TX_CW);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
commandDone();
|
||||
sif::error << "SyrlinksHandler: Unexpected submode " << getSubmode() << std::endl;
|
||||
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
|
||||
}
|
||||
}
|
||||
} else if (tgtMode == HasModesIF::MODE_OFF) {
|
||||
txStandbyHandler();
|
||||
} else {
|
||||
return doneHandler();
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ class SyrlinksHandler : public DeviceHandlerBase {
|
||||
size_t* foundLen) override;
|
||||
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
|
||||
ReturnValue_t getSwitches(const uint8_t** switches, uint8_t* numberOfSwitches) override;
|
||||
void setNormalDatapoolEntriesInvalid() override;
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
@ -118,15 +117,20 @@ class SyrlinksHandler : public DeviceHandlerBase {
|
||||
enum class InternalState {
|
||||
OFF,
|
||||
ENABLE_TEMPERATURE_PROTECTION,
|
||||
TX_TRANSITION,
|
||||
IDLE
|
||||
} internalState = InternalState::OFF;
|
||||
|
||||
enum class TransitionState {
|
||||
IDLE,
|
||||
SELECT_MODULATION_BPSK,
|
||||
SELECT_MODULATION_0QPSK,
|
||||
SET_TX_MODULATION,
|
||||
SET_TX_CW,
|
||||
SET_TX_STANDBY,
|
||||
IDLE
|
||||
};
|
||||
|
||||
InternalState internalState = InternalState::OFF;
|
||||
CMD_PENDING,
|
||||
DONE
|
||||
} transState = TransitionState::IDLE;
|
||||
|
||||
/**
|
||||
* This object is used to store the id of the next command to execute. This controls the
|
||||
|
228
mission/com/TmStoreTaskBase.cpp
Normal file
228
mission/com/TmStoreTaskBase.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
#include "TmStoreTaskBase.h"
|
||||
|
||||
#include <fsfw/ipc/CommandMessageIF.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/subsystem/helper.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw/tmstorage/TmStoreMessage.h>
|
||||
|
||||
#include "mission/persistentTmStoreDefs.h"
|
||||
|
||||
TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore,
|
||||
VirtualChannel& channel, SdCardMountedIF& sdcMan,
|
||||
const std::atomic_bool& ptmeLocked)
|
||||
: SystemObject(objectId),
|
||||
modeHelper(this),
|
||||
ipcStore(ipcStore),
|
||||
tmReader(&timeReader),
|
||||
channel(channel),
|
||||
sdcMan(sdcMan),
|
||||
ptmeLocked(ptmeLocked) {
|
||||
requestQueue = QueueFactory::instance()->createMessageQueue(10);
|
||||
}
|
||||
|
||||
bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
|
||||
DumpContext& dumpContext) {
|
||||
ReturnValue_t result;
|
||||
bool tmToStoreReceived = false;
|
||||
bool tcRequestReceived = false;
|
||||
bool dumpPerformed = false;
|
||||
fileHasSwapped = false;
|
||||
dumpContext.packetWasDumped = false;
|
||||
dumpContext.vcBusyDuringDump = false;
|
||||
|
||||
// Store TM persistently
|
||||
result = store.handleNextTm();
|
||||
if (result == returnvalue::OK) {
|
||||
tmToStoreReceived = true;
|
||||
}
|
||||
// Dump TMs
|
||||
if (store.getState() == PersistentTmStore::State::DUMPING) {
|
||||
if (handleOneDump(store, dumpContext, dumpPerformed) != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
Command_t execCmd;
|
||||
// Handle TC requests, for example deletion or retrieval requests.
|
||||
result = store.handleCommandQueue(ipcStore, execCmd);
|
||||
if (result == returnvalue::OK) {
|
||||
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
|
||||
cancelDumpCd.resetTimer();
|
||||
tmSinkBusyCd.resetTimer();
|
||||
dumpContext.reset();
|
||||
}
|
||||
tcRequestReceived = true;
|
||||
}
|
||||
}
|
||||
if (tcRequestReceived or tmToStoreReceived or dumpPerformed) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TmStoreTaskBase::cyclicStoreCheck() {
|
||||
if (not storesInitialized) {
|
||||
storesInitialized = initStoresIfPossible();
|
||||
if (not storesInitialized) {
|
||||
TaskFactory::delayTask(400);
|
||||
return false;
|
||||
}
|
||||
} else if (sdCardCheckCd.hasTimedOut()) {
|
||||
if (not sdcMan.isSdCardUsable(std::nullopt)) {
|
||||
// Might be due to imminent shutdown or SD card switch.
|
||||
storesInitialized = false;
|
||||
TaskFactory::delayTask(100);
|
||||
return false;
|
||||
}
|
||||
sdCardCheckCd.resetTimer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void TmStoreTaskBase::cancelDump(DumpContext& ctx, PersistentTmStore& store, bool isTxOn) {
|
||||
ctx.reset();
|
||||
if (store.getState() == PersistentTmStore::State::DUMPING) {
|
||||
triggerEvent(ctx.eventIfCancelled, ctx.numberOfDumpedPackets, ctx.dumpedBytes);
|
||||
}
|
||||
store.cancelDump();
|
||||
if (isTxOn) {
|
||||
channel.cancelTransfer();
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t TmStoreTaskBase::handleOneDump(PersistentTmStoreWithTmQueue& store,
|
||||
DumpContext& dumpContext, bool& dumpPerformed) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
// The PTME might have been reset an transmitter state change, so there is no point in continuing
|
||||
// the dump.
|
||||
// TODO: Will be solved in a cleaner way, this is kind of a hack.
|
||||
if (not channel.isTxOn()) {
|
||||
cancelDump(dumpContext, store, false);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// It is assumed that the PTME will only be locked for a short period (e.g. to change datarate).
|
||||
if (not channel.isBusy() and not ptmeLocked) {
|
||||
performDump(store, dumpContext, dumpPerformed);
|
||||
} else {
|
||||
// The PTME might be at full load, so it might sense to delay for a bit to let it do
|
||||
// its work until some more bandwidth is available. Set a flag here so the upper layer can
|
||||
// do ths.
|
||||
dumpContext.vcBusyDuringDump = true;
|
||||
dumpContext.ptmeBusyCounter++;
|
||||
if (dumpContext.ptmeBusyCounter == 100) {
|
||||
// If this happens, something is probably wrong.
|
||||
sif::warning << "PTME busy for longer period. Cancelling dump" << std::endl;
|
||||
cancelDump(dumpContext, store, channel.isTxOn());
|
||||
}
|
||||
}
|
||||
if (cancelDumpCd.hasTimedOut() or tmSinkBusyCd.hasTimedOut()) {
|
||||
cancelDump(dumpContext, store, channel.isTxOn());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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 (result != returnvalue::OK) {
|
||||
sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl;
|
||||
} else if (fileHasSwapped or result == PersistentTmStore::DUMP_DONE) {
|
||||
// This can happen if a file is corrupted and the next file swap completes the dump.
|
||||
dumpDoneHandler();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
dumpedLen = tmReader.getFullPacketLen();
|
||||
// Only write to VC if mode is on, but always confirm the dump.
|
||||
// If the mode is OFF, it is assumed the PTME is not usable and is not allowed to be written
|
||||
// (e.g. to confirm a reset or the transmitter is off anyway).
|
||||
if (mode == MODE_ON) {
|
||||
result = channel.write(tmReader.getFullData(), dumpedLen);
|
||||
if (result == DirectTmSinkIF::IS_BUSY) {
|
||||
sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl;
|
||||
} else if (result != returnvalue::OK) {
|
||||
sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl;
|
||||
}
|
||||
}
|
||||
result = store.confirmDump(tmReader, fileHasSwapped);
|
||||
if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK)) {
|
||||
dumpPerformed = true;
|
||||
if (dumpedLen > 0) {
|
||||
dumpContext.dumpedBytes += dumpedLen;
|
||||
dumpContext.numberOfDumpedPackets += 1;
|
||||
dumpContext.packetWasDumped = true;
|
||||
}
|
||||
}
|
||||
if (result == PersistentTmStore::DUMP_DONE) {
|
||||
dumpDoneHandler();
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t TmStoreTaskBase::initialize() {
|
||||
modeHelper.initialize();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void TmStoreTaskBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
if (mode != nullptr) {
|
||||
*mode = this->mode;
|
||||
}
|
||||
if (submode != nullptr) {
|
||||
*submode = SUBMODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t TmStoreTaskBase::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) {
|
||||
if (mode == MODE_ON or mode == MODE_OFF) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
MessageQueueId_t TmStoreTaskBase::getCommandQueue() const { return requestQueue->getId(); }
|
||||
|
||||
void TmStoreTaskBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, SUBMODE_NONE); }
|
||||
|
||||
object_id_t TmStoreTaskBase::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
const HasHealthIF* TmStoreTaskBase::getOptHealthIF() const { return nullptr; }
|
||||
|
||||
const HasModesIF& TmStoreTaskBase::getModeIF() const { return *this; }
|
||||
|
||||
ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
||||
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
|
||||
}
|
||||
|
||||
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
|
||||
|
||||
void TmStoreTaskBase::readCommandQueue(void) {
|
||||
CommandMessage commandMessage;
|
||||
ReturnValue_t result = returnvalue::FAILED;
|
||||
|
||||
result = requestQueue->receiveMessage(&commandMessage);
|
||||
if (result == returnvalue::OK) {
|
||||
result = modeHelper.handleModeCommand(&commandMessage);
|
||||
if (result == returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
CommandMessage reply;
|
||||
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
|
||||
requestQueue->reply(&reply);
|
||||
return;
|
||||
}
|
||||
}
|
@ -1,15 +1,22 @@
|
||||
#ifndef MISSION_TMTC_TMSTORETASKBASE_H_
|
||||
#define MISSION_TMTC_TMSTORETASKBASE_H_
|
||||
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <fsfw/subsystem/ModeTreeChildIF.h>
|
||||
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
|
||||
#include <fsfw/timemanager/CdsShortTimeStamper.h>
|
||||
#include <fsfw/timemanager/Countdown.h>
|
||||
#include <mission/com/VirtualChannel.h>
|
||||
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
|
||||
#include <mission/tmtc/VirtualChannel.h>
|
||||
|
||||
/**
|
||||
* Generic class which composes a Virtual Channel and a persistent TM stores. This allows dumping
|
||||
* the TM store into the virtual channel directly.
|
||||
*/
|
||||
class TmStoreTaskBase : public SystemObject {
|
||||
class TmStoreTaskBase : public SystemObject,
|
||||
public HasModesIF,
|
||||
public ModeTreeChildIF,
|
||||
public ModeTreeConnectionIF {
|
||||
public:
|
||||
struct DumpContext {
|
||||
DumpContext(Event eventIfDone, Event eventIfCancelled)
|
||||
@ -33,19 +40,35 @@ class TmStoreTaskBase : public SystemObject {
|
||||
};
|
||||
|
||||
TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel,
|
||||
SdCardMountedIF& sdcMan);
|
||||
SdCardMountedIF& sdcMan, const std::atomic_bool& ptmeLocked);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
|
||||
|
||||
protected:
|
||||
ModeHelper modeHelper;
|
||||
MessageQueueIF* requestQueue;
|
||||
StorageManagerIF& ipcStore;
|
||||
PusTmReader tmReader;
|
||||
CdsShortTimeStamper timeReader;
|
||||
VirtualChannel& channel;
|
||||
SdCardMountedIF& sdcMan;
|
||||
const std::atomic_bool& ptmeLocked;
|
||||
|
||||
Mode_t mode = HasModesIF::MODE_OFF;
|
||||
Countdown sdCardCheckCd = Countdown(800);
|
||||
// 20 minutes are allowed as maximum dump time.
|
||||
Countdown cancelDumpCd = Countdown(60 * 20 * 1000);
|
||||
// If the TM sink is busy for 1 minute for whatever reason, cancel the dump.
|
||||
Countdown tmSinkBusyCd = Countdown(60 * 1000);
|
||||
VirtualChannel& channel;
|
||||
|
||||
bool storesInitialized = false;
|
||||
bool fileHasSwapped = false;
|
||||
SdCardMountedIF& sdcMan;
|
||||
|
||||
void readCommandQueue(void);
|
||||
|
||||
virtual bool initStoresIfPossible() = 0;
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode) = 0;
|
||||
|
||||
void cancelDump(DumpContext& ctx, PersistentTmStore& store, bool isTxOn);
|
||||
/**
|
||||
@ -58,6 +81,8 @@ class TmStoreTaskBase : public SystemObject {
|
||||
|
||||
ReturnValue_t handleOneDump(PersistentTmStoreWithTmQueue& store, DumpContext& dumpContext,
|
||||
bool& dumpPerformed);
|
||||
ReturnValue_t performDump(PersistentTmStoreWithTmQueue& store, DumpContext& dumpContext,
|
||||
bool& dumpPerformed);
|
||||
|
||||
/**
|
||||
* Occasionally check whether SD card is okay to be used. If not, poll whether it is ready to
|
||||
@ -65,7 +90,17 @@ class TmStoreTaskBase : public SystemObject {
|
||||
*/
|
||||
bool cyclicStoreCheck();
|
||||
|
||||
virtual bool initStoresIfPossible() = 0;
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
void getMode(Mode_t* mode, Submode_t* submode) override;
|
||||
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) override;
|
||||
void announceMode(bool recursive) override;
|
||||
object_id_t getObjectId() const override;
|
||||
const HasHealthIF* getOptHealthIF() const override;
|
||||
const HasModesIF& getModeIF() const override;
|
||||
ModeTreeChildIF& getModeTreeChildIF() override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_TMSTORETASKBASE_H_ */
|
@ -1,4 +1,4 @@
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
#include "VirtualChannelWithQueue.h"
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
@ -19,7 +19,7 @@ VirtualChannelWithQueue::VirtualChannelWithQueue(object_id_t objectId, uint8_t v
|
||||
|
||||
const char* VirtualChannelWithQueue::getName() const { return VirtualChannel::getName(); }
|
||||
|
||||
ReturnValue_t VirtualChannelWithQueue::sendNextTm() {
|
||||
ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
|
||||
TmTcMessage message;
|
||||
ReturnValue_t result = tmQueue->receiveMessage(&message);
|
||||
if (result == MessageQueueIF::EMPTY) {
|
||||
@ -36,7 +36,9 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = write(data, size);
|
||||
if (performWriteOp) {
|
||||
result = write(data, size);
|
||||
}
|
||||
// Try delete in any case, ignore failures (which should not happen), it is more important to
|
||||
// propagate write errors.
|
||||
tmStore.deleteData(storeId);
|
@ -4,7 +4,7 @@
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <linux/ipcore/PtmeIF.h>
|
||||
#include <mission/tmtc/VirtualChannel.h>
|
||||
#include <mission/com/VirtualChannel.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
@ -34,7 +34,7 @@ class VirtualChannelWithQueue : public VirtualChannel, public AcceptsTelemetryIF
|
||||
|
||||
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override;
|
||||
[[nodiscard]] const char* getName() const override;
|
||||
ReturnValue_t sendNextTm();
|
||||
ReturnValue_t handleNextTm(bool performWriteOp);
|
||||
|
||||
private:
|
||||
MessageQueueIF* tmQueue = nullptr;
|
@ -3,6 +3,8 @@
|
||||
#include <fsfw/ipc/MutexFactory.h>
|
||||
#include <fsfw/ipc/MutexGuard.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
com::Datarate DATARATE_CFG_RAW = com::Datarate::LOW_RATE_MODULATION_BPSK;
|
||||
MutexIF* DATARATE_LOCK = nullptr;
|
||||
|
||||
|
@ -221,9 +221,8 @@ void AcsController::performSafe() {
|
||||
|
||||
updateCtrlValData(errAng);
|
||||
updateActuatorCmdData(cmdDipolMtqs);
|
||||
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
// acsParameters.magnetorquesParameter.torqueDuration, 0, 0, 0, 0,
|
||||
// acsParameters.rwHandlingParameters.rampTime);
|
||||
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
// acsParameters.magnetorquerParameter.torqueDuration);
|
||||
}
|
||||
|
||||
void AcsController::performDetumble() {
|
||||
@ -472,6 +471,18 @@ void AcsController::performPointingCtrl() {
|
||||
// acsParameters.rwHandlingParameters.rampTime);
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
uint16_t dipoleTorqueDuration) {
|
||||
{
|
||||
PoolReadGuard pg(&dipoleSet);
|
||||
MutexGuard mg(torquer::lazyLock(), torquer::LOCK_TYPE, torquer::LOCK_TIMEOUT,
|
||||
torquer::LOCK_CTX);
|
||||
torquer::NEW_ACTUATION_FLAG = true;
|
||||
dipoleSet.setDipoles(xDipole, yDipole, zDipole, dipoleTorqueDuration);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
uint16_t dipoleTorqueDuration, int32_t rw1Speed,
|
||||
int32_t rw2Speed, int32_t rw3Speed, int32_t rw4Speed,
|
||||
@ -565,7 +576,7 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_3_RM3100_UT, &mgm3VecRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_IMTQ_CAL_NT, &imtqMgmVecRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_IMTQ_CAL_ACT_STATUS, &imtqCalActStatus);
|
||||
poolManager.subscribeForRegularPeriodicPacket({mgmDataRaw.getSid(), false, 5.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({mgmDataRaw.getSid(), false, 10.0});
|
||||
// MGM Processed
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_0_VEC, &mgm0VecProc);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_1_VEC, &mgm1VecProc);
|
||||
@ -575,7 +586,7 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_VEC_TOT, &mgmVecTot);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MGM_VEC_TOT_DERIVATIVE, &mgmVecTotDer);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MAG_IGRF_MODEL, &magIgrf);
|
||||
poolManager.subscribeForRegularPeriodicPacket({mgmDataProcessed.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({mgmDataProcessed.getSid(), enableHkSets, 10.0});
|
||||
// SUS Raw
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_0_N_LOC_XFYFZM_PT_XF, &sus0ValRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_1_N_LOC_XBYFZM_PT_XB, &sus1ValRaw);
|
||||
@ -589,7 +600,7 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_9_R_LOC_XBYBZB_PT_YF, &sus9ValRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_10_N_LOC_XMYBZF_PT_ZF, &sus10ValRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_11_R_LOC_XBYMZB_PT_ZB, &sus11ValRaw);
|
||||
poolManager.subscribeForRegularPeriodicPacket({susDataRaw.getSid(), false, 5.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({susDataRaw.getSid(), false, 10.0});
|
||||
// SUS Processed
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_0_VEC, &sus0VecProc);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_1_VEC, &sus1VecProc);
|
||||
@ -606,43 +617,43 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_VEC_TOT, &susVecTot);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUS_VEC_TOT_DERIVATIVE, &susVecTotDer);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SUN_IJK_MODEL, &sunIjk);
|
||||
poolManager.subscribeForRegularPeriodicPacket({susDataProcessed.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({susDataProcessed.getSid(), enableHkSets, 10.0});
|
||||
// GYR Raw
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_0_ADIS, &gyr0VecRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_1_L3, &gyr1VecRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_2_ADIS, &gyr2VecRaw);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_3_L3, &gyr3VecRaw);
|
||||
poolManager.subscribeForDiagPeriodicPacket({gyrDataRaw.getSid(), false, 5.0});
|
||||
poolManager.subscribeForDiagPeriodicPacket({gyrDataRaw.getSid(), false, 10.0});
|
||||
// GYR Processed
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_0_VEC, &gyr0VecProc);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_1_VEC, &gyr1VecProc);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_2_VEC, &gyr2VecProc);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_3_VEC, &gyr3VecProc);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GYR_VEC_TOT, &gyrVecTot);
|
||||
poolManager.subscribeForDiagPeriodicPacket({gyrDataProcessed.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForDiagPeriodicPacket({gyrDataProcessed.getSid(), enableHkSets, 10.0});
|
||||
// GPS Processed
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GC_LATITUDE, &gcLatitude);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GD_LONGITUDE, &gdLongitude);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ALTITUDE, &altitude);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GPS_POSITION, &gpsPosition);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::GPS_VELOCITY, &gpsVelocity);
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsDataProcessed.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({gpsDataProcessed.getSid(), enableHkSets, 30.0});
|
||||
// MEKF
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::QUAT_MEKF, &quatMekf);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SAT_ROT_RATE_MEKF, &satRotRateMekf);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MEKF_STATUS, &mekfStatus);
|
||||
poolManager.subscribeForDiagPeriodicPacket({mekfData.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForDiagPeriodicPacket({mekfData.getSid(), enableHkSets, 10.0});
|
||||
// Ctrl Values
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TGT_QUAT, &tgtQuat);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ERROR_QUAT, &errQuat);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ERROR_ANG, &errAng);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TGT_ROT_RATE, &tgtRotRate);
|
||||
poolManager.subscribeForRegularPeriodicPacket({ctrlValData.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({ctrlValData.getSid(), enableHkSets, 10.0});
|
||||
// Actuator CMD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_TORQUE, &rwTargetTorque);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_SPEED, &rwTargetSpeed);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MTQ_TARGET_DIPOLE, &mtqTargetDipole);
|
||||
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 12.0});
|
||||
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 10.0});
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -105,6 +105,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void modeChanged(Mode_t mode, Submode_t submode);
|
||||
void announceMode(bool recursive);
|
||||
|
||||
ReturnValue_t commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
uint16_t dipoleTorqueDuration);
|
||||
ReturnValue_t commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
uint16_t dipoleTorqueDuration, int32_t rw1Speed, int32_t rw2Speed,
|
||||
int32_t rw3Speed, int32_t rw4Speed, uint16_t rampTime);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
#include <mission/acs/susMax1227Helpers.h>
|
||||
#include <mission/com/syrlinksDefs.h>
|
||||
#include <mission/controller/controllerdefinitions/ThermalControllerDefinitions.h>
|
||||
#include <mission/controller/tcsDefs.h>
|
||||
#include <mission/payload/payloadPcduDefinitions.h>
|
||||
#include <mission/power/bpxBattDefs.h>
|
||||
#include <mission/power/gsDefs.h>
|
||||
@ -45,17 +45,73 @@ struct TempLimits {
|
||||
float nopUpperLimit;
|
||||
};
|
||||
|
||||
struct ThermalState {
|
||||
uint8_t errorCounter;
|
||||
bool heating;
|
||||
uint32_t heaterStartTime;
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
class ThermalController : public ExtendedControllerBase {
|
||||
public:
|
||||
static const uint16_t INVALID_TEMPERATURE = 999;
|
||||
static const uint8_t NUMBER_OF_SENSORS = 16;
|
||||
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
|
||||
static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160;
|
||||
|
||||
ThermalController(object_id_t objectId, HeaterHandler& heater);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
protected:
|
||||
void performThermalModuleCtrl();
|
||||
struct HeaterContext {
|
||||
public:
|
||||
HeaterContext(heater::Switchers switchNr, heater::Switchers redundantSwitchNr,
|
||||
const TempLimits& tempLimit)
|
||||
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
|
||||
bool doHeaterHandling = true;
|
||||
heater::Switchers switchNr;
|
||||
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
|
||||
heater::Switchers redSwitchNr;
|
||||
const TempLimits& tempLimit;
|
||||
};
|
||||
|
||||
void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates);
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
void performControlOperation() override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
@ -67,16 +123,7 @@ class ThermalController : public ExtendedControllerBase {
|
||||
uint32_t* msToReachTheMode) override;
|
||||
|
||||
private:
|
||||
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);
|
||||
static constexpr Event SYRLINKS_OVERHEATING = MAKE_EVENT(2, severity::HIGH);
|
||||
static constexpr Event PLOC_OVERHEATING = MAKE_EVENT(3, severity::HIGH);
|
||||
static constexpr Event OBC_OVERHEATING = MAKE_EVENT(4, severity::HIGH);
|
||||
static constexpr Event HPA_OVERHEATING = MAKE_EVENT(5, severity::HIGH);
|
||||
static constexpr Event PLPCDU_OVERHEATING = MAKE_EVENT(6, severity::HIGH);
|
||||
|
||||
static const uint32_t DELAY = 500;
|
||||
static const uint32_t INIT_DELAY = 1500;
|
||||
|
||||
static const uint32_t TEMP_OFFSET = 5;
|
||||
|
||||
@ -96,22 +143,22 @@ class ThermalController : public ExtendedControllerBase {
|
||||
DeviceHandlerThermalSet imtqThermalSet;
|
||||
|
||||
// Temperature Sensors
|
||||
MAX31865::PrimarySet max31865Set0;
|
||||
MAX31865::PrimarySet max31865Set1;
|
||||
MAX31865::PrimarySet max31865Set2;
|
||||
MAX31865::PrimarySet max31865Set3;
|
||||
MAX31865::PrimarySet max31865Set4;
|
||||
MAX31865::PrimarySet max31865Set5;
|
||||
MAX31865::PrimarySet max31865Set6;
|
||||
MAX31865::PrimarySet max31865Set7;
|
||||
MAX31865::PrimarySet max31865Set8;
|
||||
MAX31865::PrimarySet max31865Set9;
|
||||
MAX31865::PrimarySet max31865Set10;
|
||||
MAX31865::PrimarySet max31865Set11;
|
||||
MAX31865::PrimarySet max31865Set12;
|
||||
MAX31865::PrimarySet max31865Set13;
|
||||
MAX31865::PrimarySet max31865Set14;
|
||||
MAX31865::PrimarySet max31865Set15;
|
||||
MAX31865::PrimarySet maxSet0PlocHspd;
|
||||
MAX31865::PrimarySet maxSet1PlocMissionBrd;
|
||||
MAX31865::PrimarySet maxSet2PlCam;
|
||||
MAX31865::PrimarySet maxSet3DacHspd;
|
||||
MAX31865::PrimarySet maxSet4Str;
|
||||
MAX31865::PrimarySet maxSet5Rw1MxMy;
|
||||
MAX31865::PrimarySet maxSet6Dro;
|
||||
MAX31865::PrimarySet maxSet7Scex;
|
||||
MAX31865::PrimarySet maxSet8X8;
|
||||
MAX31865::PrimarySet maxSet9Hpa;
|
||||
MAX31865::PrimarySet maxSet10EbandTx;
|
||||
MAX31865::PrimarySet maxSet11Mpa;
|
||||
MAX31865::PrimarySet maxSet31865Set12;
|
||||
MAX31865::PrimarySet maxSet13PlPcduHspd;
|
||||
MAX31865::PrimarySet maxSet14TcsBrd;
|
||||
MAX31865::PrimarySet maxSet15Imtq;
|
||||
|
||||
TMP1075::Tmp1075Dataset tmp1075SetTcs0;
|
||||
TMP1075::Tmp1075Dataset tmp1075SetTcs1;
|
||||
@ -191,18 +238,38 @@ class ThermalController : public ExtendedControllerBase {
|
||||
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 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);
|
||||
|
||||
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 strTooHotFlag = false;
|
||||
bool rwTooHotFlag = false;
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners
|
||||
Countdown initialCountdown = Countdown(DELAY);
|
||||
bool transitionToOff = false;
|
||||
uint32_t transitionToOffCycles = 0;
|
||||
uint32_t cycles = 0;
|
||||
std::array<ThermalState, 30> thermalStates{};
|
||||
std::array<HeaterState, 7> heaterStates{};
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners.
|
||||
// Also, wait for system initialization to complete.
|
||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||
|
||||
#if OBSW_THREAD_TRACING == 1
|
||||
uint32_t opCounter = 0;
|
||||
@ -221,16 +288,20 @@ class ThermalController : public ExtendedControllerBase {
|
||||
|
||||
static constexpr dur_millis_t MUTEX_TIMEOUT = 50;
|
||||
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
|
||||
void resetSensorsArray();
|
||||
void copySensors();
|
||||
void copySus();
|
||||
void copyDevices();
|
||||
|
||||
void ctrlComponentTemperature(heater::Switchers switchNr, heater::Switchers redSwitchNr,
|
||||
TempLimits& tempLimit);
|
||||
void ctrlHeater(heater::Switchers switchNr, heater::Switchers redSwitchNr, TempLimits& tempLimit);
|
||||
void ctrlComponentTemperature(HeaterContext& heaterContext);
|
||||
void checkLimitsAndCtrlHeater(HeaterContext& heaterContext);
|
||||
bool heaterCtrlCheckUpperLimits(HeaterContext& heaterContext);
|
||||
void heaterCtrlTempTooHighHandler(HeaterContext& heaterContext, const char* whatLimit);
|
||||
|
||||
bool chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr);
|
||||
bool selectAndReadSensorTemp();
|
||||
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
|
||||
|
||||
void ctrlAcsBoard();
|
||||
void ctrlMgt();
|
||||
@ -255,6 +326,11 @@ class ThermalController : public ExtendedControllerBase {
|
||||
void ctrlTx();
|
||||
void ctrlMpa();
|
||||
void ctrlScexBoard();
|
||||
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
|
||||
void setMode(Mode_t mode);
|
||||
uint32_t tempFloatToU32() const;
|
||||
bool tooHotHandler(object_id_t object, bool& oneShotFlag);
|
||||
void tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag);
|
||||
};
|
||||
|
||||
#endif /* MISSION_CONTROLLER_THERMALCONTROLLER_H_ */
|
||||
|
@ -5,9 +5,19 @@
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
|
||||
#include "devices/heaterSwitcherList.h"
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
|
||||
namespace tcsCtrl {
|
||||
|
||||
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);
|
||||
static constexpr Event SYRLINKS_OVERHEATING = MAKE_EVENT(2, severity::HIGH);
|
||||
static constexpr Event OBC_OVERHEATING = MAKE_EVENT(4, severity::HIGH);
|
||||
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);
|
||||
|
||||
enum SetId : uint32_t {
|
||||
SENSOR_TEMPERATURES = 0,
|
||||
DEVICE_TEMPERATURES = 1,
|
||||
@ -93,34 +103,33 @@ static const uint8_t ENTRIES_SUS_TEMPERATURE_SET = 12;
|
||||
*/
|
||||
class SensorTemperatures : public StaticLocalDataSet<ENTRIES_SENSOR_TEMPERATURE_SET> {
|
||||
public:
|
||||
SensorTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SENSOR_TEMPERATURES) {}
|
||||
explicit SensorTemperatures(HasLocalDataPoolIF* owner)
|
||||
: StaticLocalDataSet(owner, SENSOR_TEMPERATURES) {}
|
||||
|
||||
SensorTemperatures(object_id_t objectId)
|
||||
explicit SensorTemperatures(object_id_t objectId)
|
||||
: StaticLocalDataSet(sid_t(objectId, SENSOR_TEMPERATURES)) {}
|
||||
|
||||
lp_var_t<float> sensor_ploc_heatspreader =
|
||||
lp_var_t<float> plocHeatspreader =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SENSOR_PLOC_HEATSPREADER, this);
|
||||
lp_var_t<float> sensor_ploc_missionboard =
|
||||
lp_var_t<float> plocMissionboard =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SENSOR_PLOC_MISSIONBOARD, this);
|
||||
lp_var_t<float> sensor_4k_camera = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_4K_CAMERA, this);
|
||||
lp_var_t<float> sensor_dac_heatspreader =
|
||||
lp_var_t<float> payload4kCamera = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_4K_CAMERA, this);
|
||||
lp_var_t<float> dacHeatspreader =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SENSOR_DAC_HEATSPREADER, this);
|
||||
lp_var_t<float> sensor_startracker =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SENSOR_STARTRACKER, this);
|
||||
lp_var_t<float> sensor_rw1 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_RW1, this);
|
||||
lp_var_t<float> sensor_scex = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_SCEX, this);
|
||||
lp_var_t<float> sensor_tx_modul = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TX_MODUL, this);
|
||||
lp_var_t<float> startracker = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_STARTRACKER, this);
|
||||
lp_var_t<float> rw1 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_RW1, this);
|
||||
lp_var_t<float> scex = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_SCEX, this);
|
||||
lp_var_t<float> eBandTx = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TX_MODUL, this);
|
||||
// E-Band module
|
||||
lp_var_t<float> sensor_dro = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_DRO, this);
|
||||
lp_var_t<float> sensor_mpa = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_MPA, this);
|
||||
lp_var_t<float> sensor_x8 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_X8, this);
|
||||
lp_var_t<float> sensor_hpa = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_HPA, this);
|
||||
lp_var_t<float> sensor_acu = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_ACU, this);
|
||||
lp_var_t<float> sensor_plpcdu_heatspreader =
|
||||
lp_var_t<float> dro = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_DRO, this);
|
||||
lp_var_t<float> mpa = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_MPA, this);
|
||||
lp_var_t<float> x8 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_X8, this);
|
||||
lp_var_t<float> hpa = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_HPA, this);
|
||||
lp_var_t<float> acu = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_ACU, this);
|
||||
lp_var_t<float> plpcduHeatspreader =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SENSOR_PLPCDU_HEATSPREADER, this);
|
||||
lp_var_t<float> sensor_tcs_board = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TCS_BOARD, this);
|
||||
lp_var_t<float> sensor_magnettorquer =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SENSOR_MAGNETTORQUER, this);
|
||||
lp_var_t<float> tcsBoard = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TCS_BOARD, this);
|
||||
lp_var_t<float> mgt = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_MAGNETTORQUER, this);
|
||||
lp_var_t<float> tmp1075Tcs0 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_TCS_0, this);
|
||||
lp_var_t<float> tmp1075Tcs1 = lp_var_t<float>(sid.objectId, PoolIds::SENSOR_TMP1075_TCS_1, this);
|
||||
lp_var_t<float> tmp1075PlPcdu0 =
|
||||
@ -137,9 +146,10 @@ class SensorTemperatures : public StaticLocalDataSet<ENTRIES_SENSOR_TEMPERATURE_
|
||||
*/
|
||||
class DeviceTemperatures : public StaticLocalDataSet<ENTRIES_DEVICE_TEMPERATURE_SET> {
|
||||
public:
|
||||
DeviceTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, DEVICE_TEMPERATURES) {}
|
||||
explicit DeviceTemperatures(HasLocalDataPoolIF* owner)
|
||||
: StaticLocalDataSet(owner, DEVICE_TEMPERATURES) {}
|
||||
|
||||
DeviceTemperatures(object_id_t objectId)
|
||||
explicit DeviceTemperatures(object_id_t objectId)
|
||||
: StaticLocalDataSet(sid_t(objectId, DEVICE_TEMPERATURES)) {}
|
||||
|
||||
lp_var_t<float> q7s = lp_var_t<float>(sid.objectId, PoolIds::TEMP_Q7S, this);
|
||||
@ -178,9 +188,11 @@ class DeviceTemperatures : public StaticLocalDataSet<ENTRIES_DEVICE_TEMPERATURE_
|
||||
*/
|
||||
class SusTemperatures : public StaticLocalDataSet<ENTRIES_SUS_TEMPERATURE_SET> {
|
||||
public:
|
||||
SusTemperatures(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SUS_TEMPERATURES) {}
|
||||
explicit SusTemperatures(HasLocalDataPoolIF* owner)
|
||||
: StaticLocalDataSet(owner, SUS_TEMPERATURES) {}
|
||||
|
||||
SusTemperatures(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, SUS_TEMPERATURES)) {}
|
||||
explicit SusTemperatures(object_id_t objectId)
|
||||
: StaticLocalDataSet(sid_t(objectId, SUS_TEMPERATURES)) {}
|
||||
|
||||
lp_var_t<float> sus_0_n_loc_xfyfzm_pt_xf =
|
||||
lp_var_t<float>(sid.objectId, PoolIds::SUS_0_N_LOC_XFYFZM_PT_XF, this);
|
@ -192,8 +192,8 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
|
||||
// HK store and PUS funnel to HK store routing
|
||||
{
|
||||
PersistentTmStoreArgs storeArgs(objects::HK_TM_STORE, "tm", "hk", RolloverInterval::MINUTELY,
|
||||
15, *ramToFileStore, sdcMan);
|
||||
PersistentTmStoreArgs storeArgs(objects::HK_TM_STORE, "tm", "hk", RolloverInterval::MINUTELY, 2,
|
||||
*ramToFileStore, sdcMan);
|
||||
stores.hkStore =
|
||||
new PersistentTmStoreWithTmQueue(storeArgs, "HK STORE", config::HK_STORE_QUEUE_SIZE);
|
||||
(*pusFunnel)
|
||||
@ -295,7 +295,7 @@ void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF&
|
||||
{new HealthDevice(objects::HEATER_7_SYRLINKS, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_7},
|
||||
}});
|
||||
heaterHandler = new HeaterHandler(objects::HEATER_HANDLER, &gpioIF, helper, &pwrSwitcher,
|
||||
pcdu::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V);
|
||||
power::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V);
|
||||
heaterHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
}
|
||||
|
||||
@ -347,7 +347,8 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher,
|
||||
AcsBoardHelper acsBoardHelper = AcsBoardHelper(
|
||||
objects::MGM_0_LIS3_HANDLER, objects::MGM_1_RM3100_HANDLER, objects::MGM_2_LIS3_HANDLER,
|
||||
objects::MGM_3_RM3100_HANDLER, objects::GYRO_0_ADIS_HANDLER, objects::GYRO_1_L3G_HANDLER,
|
||||
objects::GYRO_2_ADIS_HANDLER, objects::GYRO_3_L3G_HANDLER, objects::GPS_CONTROLLER);
|
||||
objects::GYRO_2_ADIS_HANDLER, objects::GYRO_3_L3G_HANDLER, objects::GPS_CONTROLLER,
|
||||
objects::GPS_0_HEALTH_DEV, objects::GPS_1_HEALTH_DEV);
|
||||
auto acsAss =
|
||||
new AcsBoardAssembly(objects::ACS_BOARD_ASS, &pwrSwitcher, acsBoardHelper, gpioComIF);
|
||||
for (auto& assChild : assemblyDhbs) {
|
||||
@ -358,13 +359,17 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher,
|
||||
}
|
||||
}
|
||||
gpsCtrl->connectModeTreeParent(*acsAss);
|
||||
auto* gps0HealthDev = new HealthDevice(objects::GPS_0_HEALTH_DEV, acsAss->getCommandQueue());
|
||||
auto* gps1HealthDev = new HealthDevice(objects::GPS_1_HEALTH_DEV, acsAss->getCommandQueue());
|
||||
acsAss->registerChild(objects::GPS_0_HEALTH_DEV, gps0HealthDev->getCommandQueue());
|
||||
acsAss->registerChild(objects::GPS_1_HEALTH_DEV, gps1HealthDev->getCommandQueue());
|
||||
acsAss->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
}
|
||||
|
||||
TcsBoardAssembly* ObjectFactory::createTcsBoardAssy(PowerSwitchIF& pwrSwitcher) {
|
||||
TcsBoardHelper helper(RTD_INFOS);
|
||||
auto* tcsBoardAss = new TcsBoardAssembly(objects::TCS_BOARD_ASS, &pwrSwitcher,
|
||||
pcdu::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
|
||||
power::Switches::PDU1_CH0_TCS_BOARD_3V3, helper);
|
||||
tcsBoardAss->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
return tcsBoardAss;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define MISSION_CORE_GENERICFACTORY_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <fsfw/devicehandlers/HealthDevice.h>
|
||||
#include <mission/memory/SdCardMountedIF.h>
|
||||
#include <mission/persistentTmStoreDefs.h>
|
||||
#include <mission/tcs/Max31865Definitions.h>
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
|
||||
#include "eive/definitions.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
|
||||
using std::ofstream;
|
||||
@ -27,6 +28,7 @@ void ScexDeviceHandler::doStartUp() { setMode(MODE_ON); }
|
||||
void ScexDeviceHandler::doShutDown() {
|
||||
reader.reset();
|
||||
commandActive = false;
|
||||
fileNameSet = false;
|
||||
multiFileFinishOutstanding = false;
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
@ -205,50 +207,13 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
using namespace scex;
|
||||
|
||||
ReturnValue_t status = OK;
|
||||
auto oneFileHandler = [&](std::string cmdName) {
|
||||
auto activeSd = sdcMan.getActiveSdCard();
|
||||
if (not activeSd) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
fileId = date_time_string();
|
||||
std::ostringstream oss;
|
||||
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||
if (prefix == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
||||
fileName = oss.str();
|
||||
ofstream out(fileName, ofstream::binary);
|
||||
if (out.bad()) {
|
||||
sif::error << "ScexDeviceHandler::interpretDeviceReply: Could not open file " << fileName
|
||||
<< std::endl;
|
||||
return FAILED;
|
||||
}
|
||||
out << helper;
|
||||
return OK;
|
||||
};
|
||||
auto multiFileHandler = [&](std::string cmdName) {
|
||||
auto multiFileHandler = [&](const char* cmdName) {
|
||||
if ((helper.getPacketCounter() == 1) or (not fileNameSet)) {
|
||||
auto activeSd = sdcMan.getActiveSdCard();
|
||||
if (not activeSd) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
status = generateNewScexFile(cmdName);
|
||||
if (status != returnvalue::OK) {
|
||||
return status;
|
||||
}
|
||||
fileId = date_time_string();
|
||||
std::ostringstream oss;
|
||||
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||
if (prefix == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
oss << prefix << "/scex/scex-" << cmdName << fileId << ".bin";
|
||||
fileName = oss.str();
|
||||
fileNameSet = true;
|
||||
ofstream out(fileName, ofstream::binary);
|
||||
if (out.bad()) {
|
||||
sif::error << "ScexDeviceHandler::handleValidReply: Could not open file " << fileName
|
||||
<< std::endl;
|
||||
return FAILED;
|
||||
}
|
||||
out << helper;
|
||||
} else {
|
||||
ofstream out(fileName,
|
||||
ofstream::binary | ofstream::app); // append
|
||||
@ -264,31 +229,31 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
id = helper.getCmd();
|
||||
switch (id) {
|
||||
case (PING): {
|
||||
status = oneFileHandler("ping_");
|
||||
status = generateNewScexFile(PING_IDLE_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
case (ION_CMD): {
|
||||
status = oneFileHandler("ion_");
|
||||
status = generateNewScexFile(ION_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
case (TEMP_CMD): {
|
||||
status = oneFileHandler("temp_");
|
||||
status = generateNewScexFile(TEMPERATURE_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
case (EXP_STATUS_CMD): {
|
||||
status = oneFileHandler("exp_status_");
|
||||
status = generateNewScexFile(EXP_STATUS_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
case (FRAM): {
|
||||
status = multiFileHandler("fram_");
|
||||
status = multiFileHandler(FRAM_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
case (ONE_CELL): {
|
||||
status = multiFileHandler("one_cell_");
|
||||
status = multiFileHandler(ONE_CELL_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
case (ALL_CELLS_CMD): {
|
||||
status = multiFileHandler("multi_cell_");
|
||||
status = multiFileHandler(ALL_CELLS_BASE_NAME);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -354,37 +319,41 @@ ReturnValue_t ScexDeviceHandler::initializeLocalDataPool(localpool::DataPool& lo
|
||||
return OK;
|
||||
}
|
||||
|
||||
std::string ScexDeviceHandler::date_time_string() {
|
||||
using namespace std;
|
||||
string date_time;
|
||||
Clock::TimeOfDay_t tod;
|
||||
Clock::getDateAndTime(&tod);
|
||||
ostringstream oss(std::ostringstream::ate);
|
||||
|
||||
if (tod.hour < 10) {
|
||||
oss << tod.year << tod.month << tod.day << "_0" << tod.hour;
|
||||
} else {
|
||||
oss << tod.year << tod.month << tod.day << "_" << tod.hour;
|
||||
}
|
||||
if (tod.minute < 10) {
|
||||
oss << 0 << tod.minute;
|
||||
|
||||
} else {
|
||||
oss << tod.minute;
|
||||
}
|
||||
if (tod.second < 10) {
|
||||
oss << 0 << tod.second;
|
||||
} else {
|
||||
oss << tod.second;
|
||||
ReturnValue_t ScexDeviceHandler::generateNewScexFile(const char* cmdName) {
|
||||
char timeString[64]{};
|
||||
auto activeSd = sdcMan.getActiveSdCard();
|
||||
if (not activeSd) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
}
|
||||
|
||||
date_time = oss.str();
|
||||
|
||||
return date_time;
|
||||
std::ostringstream oss;
|
||||
auto prefix = sdcMan.getCurrentMountPrefix();
|
||||
if (prefix == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
timeval tv;
|
||||
Clock::getClock_timeval(&tv);
|
||||
time_t epoch = tv.tv_sec;
|
||||
struct tm* time = gmtime(&epoch);
|
||||
size_t writtenBytes = strftime(reinterpret_cast<char*>(timeString), sizeof(timeString),
|
||||
config::FILE_DATE_FORMAT, time);
|
||||
if (writtenBytes == 0) {
|
||||
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
oss << prefix << "/scex/scex-" << cmdName << "-" << timeString << ".bin";
|
||||
fileName = oss.str();
|
||||
ofstream out(fileName, ofstream::binary);
|
||||
if (out.bad()) {
|
||||
sif::error << "ScexDeviceHandler::interpretDeviceReply: Could not open file " << fileName
|
||||
<< std::endl;
|
||||
return FAILED;
|
||||
}
|
||||
out << helper;
|
||||
return OK;
|
||||
}
|
||||
|
||||
void ScexDeviceHandler::modeChanged() {}
|
||||
|
||||
void ScexDeviceHandler::setPowerSwitcher(PowerSwitchIF& powerSwitcher, power::Switch_t switchId) {
|
||||
DeviceHandlerBase::setPowerSwitcher(&powerSwitcher);
|
||||
this->switchId = switchId;
|
||||
|
@ -13,6 +13,14 @@ class SdCardMountedIF;
|
||||
|
||||
class ScexDeviceHandler : public DeviceHandlerBase {
|
||||
public:
|
||||
static constexpr char FRAM_BASE_NAME[] = "framContent";
|
||||
static constexpr char ION_BASE_NAME[] = "ion";
|
||||
static constexpr char TEMPERATURE_BASE_NAME[] = "temperature";
|
||||
static constexpr char EXP_STATUS_BASE_NAME[] = "expStatus";
|
||||
static constexpr char ONE_CELL_BASE_NAME[] = "oneCell";
|
||||
static constexpr char ALL_CELLS_BASE_NAME[] = "allCells";
|
||||
static constexpr char PING_IDLE_BASE_NAME[] = "pingIdle";
|
||||
|
||||
ScexDeviceHandler(object_id_t objectId, ScexUartReader &reader, CookieIF *cookie,
|
||||
SdCardMountedIF &sdcMan);
|
||||
void setPowerSwitcher(PowerSwitchIF &powerSwitcher, power::Switch_t switchId);
|
||||
@ -35,8 +43,6 @@ class ScexDeviceHandler : public DeviceHandlerBase {
|
||||
SdCardMountedIF &sdcMan;
|
||||
Countdown finishCountdown = Countdown(LONG_CD);
|
||||
|
||||
std::string date_time_string();
|
||||
|
||||
// DeviceHandlerBase private function implementation
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
@ -59,7 +65,8 @@ class ScexDeviceHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
void modeChanged() override;
|
||||
|
||||
ReturnValue_t generateNewScexFile(const char *cmdName);
|
||||
};
|
||||
|
||||
#endif /* MISSION_PAYLOAD_SCEXDEVICEHANDLER_H_ */
|
||||
|
@ -26,10 +26,11 @@ ReturnValue_t pst::pstSyrlinks(FixedTimeslotTaskIF *thisSequence) {
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.25, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.25, DeviceHandlerIF::GET_READ);
|
||||
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.4, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.7, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.7, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.75, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::SYRLINKS_HANDLER, length * 0.75, DeviceHandlerIF::GET_READ);
|
||||
|
||||
static_cast<void>(length);
|
||||
|
||||
@ -102,25 +103,25 @@ ReturnValue_t pst::pstGompaceCan(FixedTimeslotTaskIF *thisSequence) {
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0, DeviceHandlerIF::GET_WRITE);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::SEND_READ);
|
||||
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::P60DOCK_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::PDU1_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::PDU2_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ);
|
||||
thisSequence->addSlot(objects::ACU_HANDLER, length * 0.5, DeviceHandlerIF::GET_READ);
|
||||
if (thisSequence->checkSequence() != returnvalue::OK) {
|
||||
sif::error << "GomSpace PST initialization failed" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
|
@ -149,9 +149,9 @@ ReturnValue_t ACUHandler::initializeLocalDataPool(localpool::DataPool &localData
|
||||
localDataPoolMap.emplace(pool::ACU_WDT_GND_LEFT, new PoolEntry<uint32_t>({0}));
|
||||
|
||||
poolManager.subscribeForDiagPeriodicPacket(
|
||||
subdp::DiagnosticsHkPeriodicParams(coreHk.getSid(), enableHkSets, 20.0));
|
||||
subdp::DiagnosticsHkPeriodicParams(coreHk.getSid(), enableHkSets, 30.0));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(auxHk.getSid(), enableHkSets, 3000.0));
|
||||
subdp::RegularHkPeriodicParams(auxHk.getSid(), enableHkSets, 6000.0));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user