Merge branch 'main' into gps-changes
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good

This commit is contained in:
Marius Eggert 2023-08-07 16:58:46 +02:00
commit 99dbab9311
12 changed files with 137 additions and 84 deletions

View File

@ -16,6 +16,8 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [unreleased]
# [v6.3.0] 2023-08-03
## Fixed ## Fixed
- Small SCEX fix: The temperatur check option was not passed - Small SCEX fix: The temperatur check option was not passed
@ -24,16 +26,26 @@ will consitute of a breaking change warranting a new major release:
- ACS Controller strategy is now actually written to the dataset for detumbling. - ACS Controller strategy is now actually written to the dataset for detumbling.
- During detumble the fused rotation rate is now calculated. - During detumble the fused rotation rate is now calculated.
- Detumbling is now exited when its exit value is undercut and not its entry value. - Detumbling is now exited when its exit value is undercut and not its entry value.
- Rotation rate of last cycle is now stored in all cases for the fused rotational rate
calculation.
- Fused rotation rate estimation during eclipse can be disabled. This will also prevent
detumbling during eclipse, as no relevant rotational rate is available for now.
- `EiveSystem`: Add a small delay between triggering an event for FDIR reboots and sending the - `EiveSystem`: Add a small delay between triggering an event for FDIR reboots and sending the
command to the core controller. command to the core controller.
- PL PDU: Fixed bounds checking logic. Bound checks will only be performed for modules which are
enabled.
## Changed ## Changed
- SCEX: Only perform filesystem checks when not in OFF mode. - SCEX: Only perform filesystem checks when not in OFF mode.
- The `EiveSystem` now only sends reboot commands targetting the same image. - The `EiveSystem` now only sends reboot commands targetting the same image.
- Added 200 ms delay between switching HPA/MPA/TX/X8 and DRO GPIO pin OFF.
- PL PCDU ADC set is now automatically enabled for `NORMAL` mode transitions. It is automatically
disabled for `OFF` mode transitions.
## Added ## Added
- PL PCDU for EM build.
- SCEX: Add warning event if filesystem is unusable. - SCEX: Add warning event if filesystem is unusable.
# [v6.2.0] 2023-07-26 # [v6.2.0] 2023-07-26

View File

@ -10,7 +10,7 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 6) set(OBSW_VERSION_MAJOR 6)
set(OBSW_VERSION_MINOR 2) set(OBSW_VERSION_MINOR 3)
set(OBSW_VERSION_REVISION 0) set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE) # set(CMAKE_VERBOSE TRUE)
@ -144,7 +144,7 @@ set(OBSW_ADD_RAD_SENSORS
${INIT_VAL} ${INIT_VAL}
CACHE STRING "Add Rad Sensor module") CACHE STRING "Add Rad Sensor module")
set(OBSW_ADD_PL_PCDU set(OBSW_ADD_PL_PCDU
${INIT_VAL} 1
CACHE STRING "Add Payload PCDU modukle") CACHE STRING "Add Payload PCDU modukle")
set(OBSW_ADD_SYRLINKS set(OBSW_ADD_SYRLINKS
1 1

View File

@ -94,6 +94,9 @@ void ObjectFactory::produce(void* args) {
#if OBSW_ADD_ACS_BOARD == 1 #if OBSW_ADD_ACS_BOARD == 1
dummyCfg.addAcsBoardDummies = false; dummyCfg.addAcsBoardDummies = false;
#endif #endif
#if OBSW_ADD_PL_PCDU == 0
dummyCfg.addPlPcduDummy = true;
#endif
PowerSwitchIF* pwrSwitcher = nullptr; PowerSwitchIF* pwrSwitcher = nullptr;
#if OBSW_ADD_GOMSPACE_PCDU == 0 #if OBSW_ADD_GOMSPACE_PCDU == 0
@ -107,6 +110,8 @@ void ObjectFactory::produce(void* args) {
new CoreController(objects::CORE_CONTROLLER, enableHkSets); new CoreController(objects::CORE_CONTROLLER, enableHkSets);
auto* stackHandler = new Stack5VHandler(*pwrSwitcher);
// Initialize chip select to avoid SPI bus issues. // Initialize chip select to avoid SPI bus issues.
createRadSensorChipSelect(gpioComIF); createRadSensorChipSelect(gpioComIF);
@ -146,6 +151,9 @@ void ObjectFactory::produce(void* args) {
createStrComponents(pwrSwitcher); createStrComponents(pwrSwitcher);
#endif /* OBSW_ADD_STAR_TRACKER == 1 */ #endif /* OBSW_ADD_STAR_TRACKER == 1 */
#if OBSW_ADD_PL_PCDU == 1
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
#endif
createPayloadComponents(gpioComIF, *pwrSwitcher); createPayloadComponents(gpioComIF, *pwrSwitcher);
#if OBSW_ADD_CCSDS_IP_CORES == 1 #if OBSW_ADD_CCSDS_IP_CORES == 1

View File

@ -81,7 +81,9 @@ void ObjectFactory::produce(void* args) {
createTmpComponents(tmpDevsToAdd); createTmpComponents(tmpDevsToAdd);
#endif #endif
createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF); createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF);
#if OBSW_ADD_PL_PCDU == 1
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler); createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
#endif
#if OBSW_ADD_SYRLINKS == 1 #if OBSW_ADD_SYRLINKS == 1
createSyrlinksComponents(pwrSwitcher); createSyrlinksComponents(pwrSwitcher);
#endif /* OBSW_ADD_SYRLINKS == 1 */ #endif /* OBSW_ADD_SYRLINKS == 1 */

View File

@ -902,8 +902,6 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF*
new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
gpioComIF, SdCardManager::instance(), stackHandler, false); gpioComIF, SdCardManager::instance(), stackHandler, false);
spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler); spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler);
// plPcduHandler->enablePeriodicPrintout(true, 5);
// static_cast<void>(plPcduHandler);
#if OBSW_TEST_PL_PCDU == 1 #if OBSW_TEST_PL_PCDU == 1
plPcduHandler->setStartUpImmediately(); plPcduHandler->setStartUpImmediately();
#endif #endif

View File

@ -248,9 +248,11 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy); auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM); scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
} }
auto* plPcduDummy = if (cfg.addPlPcduDummy) {
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); auto* plPcduDummy =
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM); new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
if (cfg.addPlocDummies) { if (cfg.addPlocDummies) {
auto* plocMpsocDummy = auto* plocMpsocDummy =
new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);

View File

@ -30,6 +30,7 @@ struct DummyCfg {
bool addStrDummy = true; bool addStrDummy = true;
bool addTmpDummies = true; bool addTmpDummies = true;
bool addRadSensorDummy = true; bool addRadSensorDummy = true;
bool addPlPcduDummy = false;
Tmp1075Cfg tmp1075Cfg; Tmp1075Cfg tmp1075Cfg;
bool addCamSwitcherDummy = false; bool addCamSwitcherDummy = false;
bool addScexDummy = false; bool addScexDummy = false;

View File

@ -26,6 +26,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
case 0x1: case 0x1:
parameterWrapper->set(onBoardParams.mekfViolationTimer); parameterWrapper->set(onBoardParams.mekfViolationTimer);
break; break;
case 0x2:
parameterWrapper->set(onBoardParams.fusedRateSafeDuringEclipse);
break;
default: default:
return INVALID_IDENTIFIER_ID; return INVALID_IDENTIFIER_ID;
} }

View File

@ -19,6 +19,7 @@ class AcsParameters : public HasParametersIF {
struct OnBoardParams { struct OnBoardParams {
double sampleTime = 0.4; // [s] double sampleTime = 0.4; // [s]
uint16_t mekfViolationTimer = 750; uint16_t mekfViolationTimer = 750;
uint8_t fusedRateSafeDuringEclipse = true;
} onBoardParams; } onBoardParams;
struct InertiaEIVE { struct InertiaEIVE {

View File

@ -18,10 +18,18 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double)); std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->setValidity(false, true); fusedRotRateData->setValidity(false, true);
} }
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
return; return;
} }
if (not susDataProcessed->susVecTot.isValid()) { if (not susDataProcessed->susVecTot.isValid()) {
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData); estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
return; return;
} }
@ -42,6 +50,10 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
fusedRotRateParallel, 3); fusedRotRateParallel, 3);
} else { } else {
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData); estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
return; return;
} }
@ -58,11 +70,6 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
double fusedRotRateTotal[3] = {0, 0, 0}; double fusedRotRateTotal[3] = {0, 0, 0};
VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal); VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal);
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
{ {
PoolReadGuard pg(fusedRotRateData); PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal, std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal,
@ -71,11 +78,17 @@ void FusedRotationEstimation::estimateFusedRotationRateSafe(
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double)); std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
fusedRotRateData->setValidity(true, true); fusedRotRateData->setValidity(true, true);
} }
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
} }
void FusedRotationEstimation::estimateFusedRotationRateEclipse( void FusedRotationEstimation::estimateFusedRotationRateEclipse(
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) { acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
if (not gyrDataProcessed->gyrVecTot.isValid() or if (not acsParameters->onBoardParams.fusedRateSafeDuringEclipse or
not gyrDataProcessed->gyrVecTot.isValid() or
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) { VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
{ {
PoolReadGuard pg(fusedRotRateData); PoolReadGuard pg(fusedRotRateData);

View File

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

View File

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