2022-02-02 17:53:07 +01:00
|
|
|
#include <fsfw/datapool/PoolReadGuard.h>
|
2023-06-17 19:17:50 +02:00
|
|
|
#include <fsfw/globalfunctions/arrayprinter.h>
|
2023-03-26 16:13:54 +02:00
|
|
|
#include <mission/power/BpxBatteryHandler.h>
|
2022-01-17 15:35:46 +01:00
|
|
|
|
2023-03-26 15:28:00 +02:00
|
|
|
BpxBatteryHandler::BpxBatteryHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
|
|
|
bool enableHkSets)
|
|
|
|
: DeviceHandlerBase(objectId, comIF, comCookie),
|
|
|
|
enableHkSets(enableHkSets),
|
|
|
|
hkSet(this),
|
|
|
|
cfgSet(this) {}
|
2022-01-17 15:35:46 +01:00
|
|
|
|
|
|
|
BpxBatteryHandler::~BpxBatteryHandler() {}
|
|
|
|
|
2022-02-02 16:07:28 +01:00
|
|
|
void BpxBatteryHandler::doStartUp() {
|
2022-02-02 16:33:36 +01:00
|
|
|
if (state == States::CHECK_COM) {
|
|
|
|
if (commandExecuted) {
|
2022-02-02 16:07:28 +01:00
|
|
|
state = States::IDLE;
|
|
|
|
commandExecuted = false;
|
2022-02-02 16:33:36 +01:00
|
|
|
if (goToNormalModeImmediately) {
|
2022-02-02 16:07:28 +01:00
|
|
|
setMode(MODE_NORMAL);
|
|
|
|
} else {
|
|
|
|
setMode(_MODE_TO_ON);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-17 15:35:46 +01:00
|
|
|
|
2022-02-02 16:07:28 +01:00
|
|
|
void BpxBatteryHandler::doShutDown() {
|
|
|
|
// Perform a COM check on reboot
|
|
|
|
state = States::CHECK_COM;
|
2023-04-06 22:35:23 +02:00
|
|
|
setMode(MODE_OFF);
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
2022-01-17 15:35:46 +01:00
|
|
|
|
|
|
|
ReturnValue_t BpxBatteryHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
2023-04-06 22:35:23 +02:00
|
|
|
*id = bpxBat::GET_HK;
|
2022-02-02 16:07:28 +01:00
|
|
|
return buildCommandFromCommand(*id, nullptr, 0);
|
2022-01-17 15:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t BpxBatteryHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
2022-02-03 13:37:48 +01:00
|
|
|
if (state == States::CHECK_COM) {
|
2023-04-06 22:35:23 +02:00
|
|
|
*id = bpxBat::PING;
|
2022-02-02 17:53:07 +01:00
|
|
|
return buildCommandFromCommand(*id, nullptr, 0);
|
|
|
|
}
|
2022-08-24 17:27:47 +02:00
|
|
|
return returnvalue::OK;
|
2022-01-17 15:35:46 +01:00
|
|
|
}
|
|
|
|
|
2022-01-17 17:11:27 +01:00
|
|
|
void BpxBatteryHandler::fillCommandAndReplyMap() {
|
2023-04-06 22:35:23 +02:00
|
|
|
using namespace bpxBat;
|
2022-02-03 16:04:06 +01:00
|
|
|
insertInCommandAndReplyMap(GET_HK, 1, &hkSet, GET_HK_REPLY_LEN);
|
2023-04-06 22:35:23 +02:00
|
|
|
insertInCommandAndReplyMap(bpxBat::PING, 1, nullptr, PING_REPLY_LEN);
|
|
|
|
insertInCommandAndReplyMap(bpxBat::REBOOT, 1, nullptr, 0);
|
|
|
|
insertInCommandAndReplyMap(bpxBat::RESET_COUNTERS, 1, nullptr, EMPTY_REPLY_LEN);
|
|
|
|
insertInCommandAndReplyMap(bpxBat::CONFIG_CMD, 1, nullptr, EMPTY_REPLY_LEN);
|
|
|
|
insertInCommandAndReplyMap(bpxBat::CONFIG_GET, 1, &cfgSet, CONFIG_GET_REPLY_LEN);
|
2023-06-17 19:17:50 +02:00
|
|
|
insertInCommandAndReplyMap(bpxBat::CONFIG_SET, 1, nullptr, EMPTY_REPLY_LEN);
|
|
|
|
insertInCommandAndReplyMap(bpxBat::MAN_HEAT_ON, 1, nullptr, MAN_HEAT_REPLY_LEN);
|
|
|
|
insertInCommandAndReplyMap(bpxBat::MAN_HEAT_OFF, 1, nullptr, MAN_HEAT_REPLY_LEN);
|
2022-01-17 17:11:27 +01:00
|
|
|
}
|
2022-01-17 15:35:46 +01:00
|
|
|
|
|
|
|
ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
|
|
|
const uint8_t* commandData,
|
|
|
|
size_t commandDataLen) {
|
2022-02-02 16:33:36 +01:00
|
|
|
switch (deviceCommand) {
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::GET_HK): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_GET_HK;
|
2022-02-03 13:37:48 +01:00
|
|
|
this->rawPacketLen = 1;
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::PING): {
|
2022-02-02 17:53:07 +01:00
|
|
|
if (commandDataLen == 1 and commandData != nullptr) {
|
2022-02-02 16:33:36 +01:00
|
|
|
sentPingByte = commandData[0];
|
|
|
|
} else {
|
2023-04-06 22:35:23 +02:00
|
|
|
sentPingByte = bpxBat::DEFAULT_PING_SENT_BYTE;
|
2022-02-02 16:33:36 +01:00
|
|
|
}
|
2022-02-02 16:07:28 +01:00
|
|
|
|
2023-04-06 22:35:23 +02:00
|
|
|
cmdBuf[0] = bpxBat::PORT_PING;
|
2022-02-02 16:33:36 +01:00
|
|
|
cmdBuf[1] = sentPingByte;
|
|
|
|
this->rawPacketLen = 2;
|
|
|
|
break;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::REBOOT): {
|
|
|
|
sif::info << "BPX BATT: Executing reboot command" << std::endl;
|
|
|
|
cmdBuf[0] = bpxBat::PORT_REBOOT;
|
2022-02-02 16:33:36 +01:00
|
|
|
cmdBuf[1] = 0x80;
|
|
|
|
cmdBuf[2] = 0x07;
|
|
|
|
cmdBuf[3] = 0x80;
|
|
|
|
cmdBuf[4] = 0x07;
|
|
|
|
this->rawPacketLen = 5;
|
|
|
|
// This instructs the FDIR to set the device mode off and on again
|
|
|
|
// to ensure the I2C communication is also verified
|
|
|
|
triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT);
|
|
|
|
break;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::RESET_COUNTERS): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_RESET_COUNTERS;
|
|
|
|
cmdBuf[1] = bpxBat::RESET_COUNTERS_MAGIC_VALUE;
|
2022-02-02 16:33:36 +01:00
|
|
|
this->rawPacketLen = 2;
|
|
|
|
break;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::CONFIG_CMD): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_CONFIG_CMD;
|
2022-02-02 16:33:36 +01:00
|
|
|
// Needs to be set to 0x01 according to datasheet
|
|
|
|
cmdBuf[1] = 0x01;
|
|
|
|
this->rawPacketLen = 2;
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::CONFIG_GET): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_CONFIG_GET;
|
2022-02-02 16:33:36 +01:00
|
|
|
this->rawPacketLen = 1;
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::CONFIG_SET): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_CONFIG_SET;
|
2022-02-02 16:33:36 +01:00
|
|
|
if (commandDataLen != 3) {
|
|
|
|
return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
|
|
|
|
}
|
|
|
|
for (uint8_t idx = 0; idx < 3; idx++) {
|
|
|
|
cmdBuf[idx + 1] = commandData[idx];
|
|
|
|
}
|
|
|
|
this->rawPacketLen = 4;
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::MAN_HEAT_ON): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_MAN_HEAT_ON;
|
2022-02-02 16:33:36 +01:00
|
|
|
if (commandDataLen != 2) {
|
|
|
|
return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
|
|
|
|
}
|
|
|
|
for (uint8_t idx = 0; idx < 2; idx++) {
|
|
|
|
cmdBuf[idx + 1] = commandData[idx];
|
|
|
|
}
|
|
|
|
this->rawPacketLen = 3;
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::MAN_HEAT_OFF): {
|
|
|
|
cmdBuf[0] = bpxBat::PORT_MAN_HEAT_OFF;
|
2022-02-02 16:33:36 +01:00
|
|
|
this->rawPacketLen = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
return DeviceHandlerIF::COMMAND_NOT_SUPPORTED;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
this->rawPacket = cmdBuf.data();
|
|
|
|
|
|
|
|
lastCmd = deviceCommand;
|
2022-08-24 17:27:47 +02:00
|
|
|
return returnvalue::OK;
|
2022-01-17 15:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t BpxBatteryHandler::scanForReply(const uint8_t* start, size_t remainingSize,
|
|
|
|
DeviceCommandId_t* foundId, size_t* foundLen) {
|
2023-04-06 22:35:23 +02:00
|
|
|
using namespace bpxBat;
|
2022-02-02 16:33:36 +01:00
|
|
|
switch (lastCmd) {
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::GET_HK): {
|
2022-02-03 16:04:06 +01:00
|
|
|
if (remainingSize != GET_HK_REPLY_LEN) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return DeviceHandlerIF::LENGTH_MISSMATCH;
|
|
|
|
}
|
|
|
|
break;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::PING):
|
|
|
|
case (bpxBat::MAN_HEAT_ON):
|
|
|
|
case (bpxBat::MAN_HEAT_OFF): {
|
2023-06-17 19:17:50 +02:00
|
|
|
if (remainingSize != MAN_HEAT_REPLY_LEN) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return DeviceHandlerIF::LENGTH_MISSMATCH;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::REBOOT): {
|
2022-02-03 16:04:06 +01:00
|
|
|
// Ignore
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::RESET_COUNTERS):
|
|
|
|
case (bpxBat::CONFIG_CMD):
|
|
|
|
case (bpxBat::CONFIG_SET): {
|
2022-02-03 16:04:06 +01:00
|
|
|
if (remainingSize != EMPTY_REPLY_LEN) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return DeviceHandlerIF::LENGTH_MISSMATCH;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::CONFIG_GET): {
|
2022-02-03 16:04:06 +01:00
|
|
|
if (remainingSize != CONFIG_GET_REPLY_LEN) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return DeviceHandlerIF::LENGTH_MISSMATCH;
|
|
|
|
}
|
2022-02-03 13:37:48 +01:00
|
|
|
|
2022-02-02 16:33:36 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
|
|
|
}
|
2022-02-03 13:37:48 +01:00
|
|
|
*foundLen = remainingSize;
|
2022-02-02 16:07:28 +01:00
|
|
|
*foundId = lastCmd;
|
2022-08-24 17:27:47 +02:00
|
|
|
return returnvalue::OK;
|
2022-01-17 15:35:46 +01:00
|
|
|
}
|
|
|
|
|
2022-02-02 16:33:36 +01:00
|
|
|
ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) {
|
2023-04-06 22:35:23 +02:00
|
|
|
if (id != bpxBat::REBOOT and packet[1] != 0) {
|
2022-02-03 15:03:35 +01:00
|
|
|
return DeviceHandlerIF::DEVICE_REPORTED_ERROR;
|
|
|
|
}
|
2022-02-02 16:33:36 +01:00
|
|
|
switch (id) {
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::GET_HK): {
|
2022-02-02 17:53:07 +01:00
|
|
|
PoolReadGuard rg(&hkSet);
|
2022-02-03 13:37:48 +01:00
|
|
|
ReturnValue_t result = hkSet.parseRawHk(packet + 2, 21);
|
2022-02-03 15:03:35 +01:00
|
|
|
hkSet.setValidity(true, true);
|
2022-08-24 17:27:47 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return result;
|
|
|
|
}
|
2022-04-26 10:37:25 +02:00
|
|
|
if (debugMode) {
|
|
|
|
sif::info << "BPX Battery HK output:" << std::endl;
|
|
|
|
sif::info << "Charge current [mA]: " << hkSet.chargeCurrent << std::endl;
|
|
|
|
sif::info << "Discharge current [mA]: " << hkSet.dischargeCurrent << std::endl;
|
|
|
|
sif::info << "Heater current [mA]: " << hkSet.heaterCurrent << std::endl;
|
|
|
|
sif::info << "Battery voltage [mV]: " << hkSet.battVoltage << std::endl;
|
|
|
|
sif::info << "Battery Temperature 1 [C]: " << hkSet.battTemp1 << std::endl;
|
|
|
|
sif::info << "Battery Temperature 2 [C]: " << hkSet.battTemp2 << std::endl;
|
|
|
|
sif::info << "Battery Temperature 3 [C]: " << hkSet.battTemp3 << std::endl;
|
|
|
|
sif::info << "Battery Temperature 4 [C]: " << hkSet.battTemp4 << std::endl;
|
|
|
|
sif::info << "Battery Reboot Counter: " << hkSet.rebootCounter << std::endl;
|
|
|
|
sif::info << "Battery Boot Cause: " << static_cast<int>(hkSet.bootcause.value) << std::endl;
|
|
|
|
}
|
2022-02-02 16:33:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::PING): {
|
2022-02-03 13:37:48 +01:00
|
|
|
if (packet[2] != sentPingByte) {
|
2022-02-03 16:04:24 +01:00
|
|
|
return DeviceHandlerIF::INVALID_DATA;
|
2022-02-02 16:33:36 +01:00
|
|
|
}
|
2022-11-02 10:20:14 +01:00
|
|
|
if (getMode() == _MODE_START_UP) {
|
2022-02-03 12:02:25 +01:00
|
|
|
commandExecuted = true;
|
|
|
|
}
|
2022-02-02 16:33:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::RESET_COUNTERS):
|
|
|
|
case (bpxBat::CONFIG_CMD):
|
|
|
|
case (bpxBat::CONFIG_SET): {
|
2022-02-02 16:33:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::MAN_HEAT_ON):
|
|
|
|
case (bpxBat::MAN_HEAT_OFF): {
|
2022-02-03 13:37:48 +01:00
|
|
|
if (packet[2] != 0x01) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return DeviceHandlerIF::DEVICE_DID_NOT_EXECUTE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::CONFIG_GET): {
|
2022-02-02 17:53:07 +01:00
|
|
|
PoolReadGuard rg(&cfgSet);
|
2022-02-03 13:37:48 +01:00
|
|
|
ReturnValue_t result = cfgSet.parseRawHk(packet + 2, 3);
|
2022-08-24 17:27:47 +02:00
|
|
|
if (result != returnvalue::OK) {
|
2022-02-02 16:33:36 +01:00
|
|
|
return result;
|
|
|
|
}
|
2022-02-03 15:31:18 +01:00
|
|
|
cfgSet.setValidity(true, true);
|
2022-02-02 16:33:36 +01:00
|
|
|
break;
|
|
|
|
}
|
2023-04-06 22:35:23 +02:00
|
|
|
case (bpxBat::REBOOT): {
|
2022-02-03 16:04:06 +01:00
|
|
|
break;
|
|
|
|
}
|
2022-02-02 16:33:36 +01:00
|
|
|
default: {
|
|
|
|
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
|
2022-02-02 16:07:28 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-24 17:27:47 +02:00
|
|
|
return returnvalue::OK;
|
2022-01-17 15:35:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t BpxBatteryHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 10000; }
|
|
|
|
|
|
|
|
ReturnValue_t BpxBatteryHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
|
|
|
LocalDataPoolManager& poolManager) {
|
2023-04-06 22:35:23 +02:00
|
|
|
localDataPoolMap.emplace(bpxBat::BATT_TEMP_1, &battTemp1);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BATT_TEMP_2, &battTemp2);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BATT_TEMP_3, &battTemp3);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BATT_TEMP_4, &battTemp4);
|
|
|
|
localDataPoolMap.emplace(bpxBat::CHARGE_CURRENT, &chargeCurrent);
|
|
|
|
localDataPoolMap.emplace(bpxBat::DISCHARGE_CURRENT, &dischargeCurrent);
|
|
|
|
localDataPoolMap.emplace(bpxBat::HEATER_CURRENT, &heaterCurrent);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BATT_VOLTAGE, &battVolt);
|
|
|
|
localDataPoolMap.emplace(bpxBat::REBOOT_COUNTER, &rebootCounter);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BOOTCAUSE, &bootCause);
|
2022-02-03 15:31:18 +01:00
|
|
|
|
2023-04-06 22:35:23 +02:00
|
|
|
localDataPoolMap.emplace(bpxBat::BATTERY_HEATER_MODE, &battheatMode);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BATTHEAT_LOW_LIMIT, &battheatLow);
|
|
|
|
localDataPoolMap.emplace(bpxBat::BATTHEAT_HIGH_LIMIT, &battheatHigh);
|
2023-03-26 15:28:00 +02:00
|
|
|
|
2022-08-15 11:57:57 +02:00
|
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
2023-03-26 15:28:00 +02:00
|
|
|
subdp::RegularHkPeriodicParams(hkSet.getSid(), enableHkSets, 20.0));
|
2023-03-14 16:44:47 +01:00
|
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
|
|
|
subdp::RegularHkPeriodicParams(cfgSet.getSid(), false, 30.0));
|
2022-08-24 17:27:47 +02:00
|
|
|
return returnvalue::OK;
|
2022-01-17 15:35:46 +01:00
|
|
|
}
|
2022-02-02 17:36:40 +01:00
|
|
|
|
|
|
|
void BpxBatteryHandler::setToGoToNormalMode(bool enable) {
|
|
|
|
this->goToNormalModeImmediately = enable;
|
|
|
|
}
|
2022-04-26 10:37:25 +02:00
|
|
|
|
|
|
|
void BpxBatteryHandler::setDebugMode(bool enable) { this->debugMode = enable; }
|
2023-02-14 10:59:35 +01:00
|
|
|
|
|
|
|
void BpxBatteryHandler::performOperationHook() {
|
|
|
|
#if OBSW_THREAD_TRACING == 1
|
|
|
|
trace::threadTrace(opCounter, "BPX BATT");
|
|
|
|
#endif
|
|
|
|
}
|