eive-obsw/mission/acs/rwHelpers.h

339 lines
13 KiB
C
Raw Normal View History

2023-02-15 17:02:22 +01:00
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_RWHELPERS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_RWHELPERS_H_
2021-06-21 09:50:26 +02:00
#include <fsfw/datapoollocal/LocalPoolVariable.h>
2022-01-17 15:58:27 +01:00
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
2021-06-21 09:50:26 +02:00
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
2022-01-17 15:58:27 +01:00
2023-02-15 19:58:32 +01:00
#include "eive/resultClassIds.h"
2022-09-14 13:18:50 +02:00
#include "events/subsystemIdRanges.h"
2021-06-21 09:50:26 +02:00
#include "objects/systemObjectList.h"
2023-02-15 17:02:22 +01:00
namespace rws {
2023-02-15 19:58:32 +01:00
void encodeHdlc(const uint8_t* sourceBuf, size_t sourceLen, uint8_t* encodedBuffer,
size_t& encodedLen);
2023-02-16 14:10:59 +01:00
size_t idToPacketLen(DeviceCommandId_t id);
2023-02-15 19:58:32 +01:00
2023-02-15 17:02:22 +01:00
static const size_t SIZE_GET_RESET_STATUS = 5;
static const size_t SIZE_CLEAR_RESET_STATUS = 4;
static const size_t SIZE_INIT_RW = 4;
static const size_t SIZE_GET_RW_STATUS = 14;
static const size_t SIZE_SET_SPEED_REPLY = 4;
static const size_t SIZE_GET_TEMPERATURE_REPLY = 8;
/** Max size when requesting telemetry */
static const size_t SIZE_GET_TELEMETRY_REPLY = 91;
2023-02-15 19:58:32 +01:00
//! This is the end and start marker of the frame datalinklayer. Also called frame delimiter
//! in the NanoAvionics datasheet.
static constexpr uint8_t FRAME_DELIMITER = 0x7E;
enum class SpecialRwRequest : uint8_t {
2023-02-15 17:02:22 +01:00
REQUEST_NONE = 0,
RESET_MCU = 1,
INIT_RW_CONTROLLER = 2,
GET_TM = 3,
NUM_REQUESTS
};
static const uint8_t INTERFACE_ID = CLASS_ID::RW_HANDLER;
static const ReturnValue_t SPI_WRITE_FAILURE = MAKE_RETURN_CODE(0xB0);
//! [EXPORT] : [COMMENT] Used by the spi send function to tell a failing read call
static const ReturnValue_t SPI_READ_FAILURE = MAKE_RETURN_CODE(0xB1);
//! [EXPORT] : [COMMENT] Can be used by the HDLC decoding mechanism to inform about a missing
//! start sign 0x7E
static const ReturnValue_t MISSING_START_SIGN = MAKE_RETURN_CODE(0xB2);
//! [EXPORT] : [COMMENT] Can be used by the HDLC decoding mechanism to inform about an invalid
//! substitution combination
static const ReturnValue_t INVALID_SUBSTITUTE = MAKE_RETURN_CODE(0xB3);
//! [EXPORT] : [COMMENT] HDLC decoding mechanism never receives the end sign 0x7E
static const ReturnValue_t MISSING_END_SIGN = MAKE_RETURN_CODE(0xB4);
//! [EXPORT] : [COMMENT] Reaction wheel only responds with empty frames.
static const ReturnValue_t NO_REPLY = MAKE_RETURN_CODE(0xB5);
//! [EXPORT] : [COMMENT] Expected a start marker as first byte
static const ReturnValue_t NO_START_MARKER = MAKE_RETURN_CODE(0xB6);
2023-02-17 02:10:08 +01:00
//! [EXPORT] : [COMMENT] Timeout when reading reply
static const ReturnValue_t SPI_READ_TIMEOUT = MAKE_RETURN_CODE(0xB7);
2021-06-21 09:50:26 +02:00
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::RW_HANDLER;
//! [EXPORT] : [COMMENT] Reaction wheel signals an error state
static constexpr Event ERROR_STATE = MAKE_EVENT(1, severity::HIGH);
2022-05-11 15:45:38 +02:00
static constexpr Event RESET_OCCURED = event::makeEvent(SUBSYSTEM_ID, 2, severity::LOW);
2023-02-15 17:02:22 +01:00
//! Minimal delay as specified by the datasheet.
2023-02-17 02:10:08 +01:00
static const uint32_t SPI_REPLY_DELAY = 20000; // us
2022-01-17 15:58:27 +01:00
enum PoolIds : lp_id_t {
TEMPERATURE_C,
CURR_SPEED,
REFERENCE_SPEED,
STATE,
CLC_MODE,
LAST_RESET_STATUS,
CURRRENT_RESET_STATUS,
TM_LAST_RESET_STATUS,
TM_MCU_TEMPERATURE,
PRESSURE_SENSOR_TEMPERATURE,
PRESSURE,
TM_RW_STATE,
TM_CLC_MODE,
TM_RW_CURR_SPEED,
TM_RW_REF_SPEED,
INVALID_CRC_PACKETS,
INVALID_LEN_PACKETS,
INVALID_CMD_PACKETS,
EXECUTED_REPLIES,
COMMAND_REPLIES,
UART_BYTES_WRITTEN,
UART_BYTES_READ,
UART_PARITY_ERRORS,
UART_NOISE_ERRORS,
UART_FRAME_ERRORS,
UART_REG_OVERRUN_ERRORS,
UART_TOTAL_ERRORS,
TOTAL_ERRORS,
SPI_BYTES_WRITTEN,
SPI_BYTES_READ,
SPI_REG_OVERRUN_ERRORS,
2023-02-09 17:11:23 +01:00
SPI_TOTAL_ERRORS,
RW_SPEED,
2023-02-10 11:26:46 +01:00
RAMP_TIME,
2021-06-21 09:50:26 +02:00
};
2022-01-17 15:58:27 +01:00
enum States : uint8_t { STATE_ERROR, IDLE, COASTING, RUNNING_SPEED_STABLE, RUNNING_SPEED_CHANGING };
2022-05-11 15:45:38 +02:00
enum LastResetStatusBitPos : uint8_t {
PIN_RESET = 0,
POR_PDR_BOR_RESET = 1,
SOFTWARE_RESET = 2,
INDEPENDENT_WATCHDOG_RESET = 3,
WINDOW_WATCHDOG_RESET = 4,
LOW_POWER_RESET = 5
2021-06-29 16:08:20 +02:00
};
2023-02-16 14:10:59 +01:00
enum DeviceCommandId : DeviceCommandId_t {
RESET_MCU = 1,
GET_LAST_RESET_STATUS = 2,
CLEAR_LAST_RESET_STATUS = 3,
GET_RW_STATUS = 4,
INIT_RW_CONTROLLER = 5,
SET_SPEED = 6,
GET_TEMPERATURE = 8,
GET_TM = 9
};
static constexpr DeviceCommandId_t REQUEST_ID = 0x77;
static constexpr DeviceCommandId_t REPLY_ID = 0x78;
2021-06-21 09:50:26 +02:00
2023-02-09 17:11:23 +01:00
enum SetIds : uint32_t {
2023-02-16 14:10:59 +01:00
TEMPERATURE_SET_ID = DeviceCommandId::GET_TEMPERATURE,
STATUS_SET_ID = DeviceCommandId::GET_RW_STATUS,
LAST_RESET_ID = DeviceCommandId::GET_LAST_RESET_STATUS,
TM_SET_ID = DeviceCommandId::GET_TM,
2023-02-09 17:55:20 +01:00
SPEED_CMD_SET = 10,
2023-02-09 17:11:23 +01:00
};
2021-06-21 09:50:26 +02:00
/** Set speed command has maximum size */
2021-06-24 12:04:36 +02:00
static const size_t MAX_CMD_SIZE = 9;
2021-06-30 15:07:26 +02:00
/**
* Max reply is reached when each byte is replaced by its substitude which should normally never
* happen.
*/
static const size_t MAX_REPLY_SIZE = 2 * SIZE_GET_TELEMETRY_REPLY;
2021-06-21 09:50:26 +02:00
2021-06-29 16:08:20 +02:00
static const uint8_t LAST_RESET_ENTRIES = 2;
2022-05-10 18:34:39 +02:00
static const uint8_t STATUS_SET_ENTRIES = 5;
static const uint8_t TM_SET_ENTRIES = 24;
2021-06-21 09:50:26 +02:00
/**
2022-05-10 18:34:39 +02:00
* @brief This dataset can be used to store the data periodically polled from the RW
2021-06-21 09:50:26 +02:00
*/
2022-01-17 15:58:27 +01:00
class StatusSet : public StaticLocalDataSet<STATUS_SET_ENTRIES> {
public:
2023-02-15 17:02:22 +01:00
StatusSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, rws::SetIds::STATUS_SET_ID) {}
2022-01-17 15:58:27 +01:00
2023-02-09 17:11:23 +01:00
StatusSet(object_id_t objectId)
2023-02-15 17:02:22 +01:00
: StaticLocalDataSet(sid_t(objectId, rws::SetIds::STATUS_SET_ID)) {}
2022-01-17 15:58:27 +01:00
2022-05-10 18:34:39 +02:00
lp_var_t<int32_t> temperatureCelcius =
lp_var_t<int32_t>(sid.objectId, PoolIds::TEMPERATURE_C, this);
2022-01-17 15:58:27 +01:00
lp_var_t<int32_t> currSpeed = lp_var_t<int32_t>(sid.objectId, PoolIds::CURR_SPEED, this);
lp_var_t<int32_t> referenceSpeed =
lp_var_t<int32_t>(sid.objectId, PoolIds::REFERENCE_SPEED, this);
lp_var_t<uint8_t> state = lp_var_t<uint8_t>(sid.objectId, PoolIds::STATE, this);
lp_var_t<uint8_t> clcMode = lp_var_t<uint8_t>(sid.objectId, PoolIds::CLC_MODE, this);
2021-06-21 09:50:26 +02:00
};
/**
* @brief This dataset stores the last reset status.
*/
2022-01-17 15:58:27 +01:00
class LastResetSatus : public StaticLocalDataSet<LAST_RESET_ENTRIES> {
public:
2023-02-09 17:11:23 +01:00
LastResetSatus(HasLocalDataPoolIF* owner)
2023-02-15 17:02:22 +01:00
: StaticLocalDataSet(owner, rws::SetIds::LAST_RESET_ID) {}
2022-01-17 15:58:27 +01:00
2023-02-09 17:11:23 +01:00
LastResetSatus(object_id_t objectId)
2023-02-15 17:02:22 +01:00
: StaticLocalDataSet(sid_t(objectId, rws::SetIds::LAST_RESET_ID)) {}
2022-01-17 15:58:27 +01:00
// If a reset occurs, the status code will be cached into this variable
lp_var_t<uint8_t> lastNonClearedResetStatus =
2022-01-17 15:58:27 +01:00
lp_var_t<uint8_t>(sid.objectId, PoolIds::LAST_RESET_STATUS, this);
// This will always contain the last polled reset status
2022-05-05 13:40:43 +02:00
lp_var_t<uint8_t> currentResetStatus =
2022-01-17 15:58:27 +01:00
lp_var_t<uint8_t>(sid.objectId, PoolIds::CURRRENT_RESET_STATUS, this);
};
2021-06-30 08:21:14 +02:00
/**
* @brief This dataset stores telemetry data as specified in the datasheet of the nano avionics
* reaction wheels. https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/
* EIVE_IRS/Arbeitsdaten/08_Used%20Components/Nanoavionics_Reactionwheels&fileid=181622
*/
2022-01-17 15:58:27 +01:00
class TmDataset : public StaticLocalDataSet<TM_SET_ENTRIES> {
public:
2023-02-15 17:02:22 +01:00
TmDataset(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, rws::SetIds::TM_SET_ID) {}
2022-01-17 15:58:27 +01:00
2023-02-15 17:02:22 +01:00
TmDataset(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, rws::SetIds::TM_SET_ID)) {}
2022-01-17 15:58:27 +01:00
lp_var_t<uint8_t> lastResetStatus =
lp_var_t<uint8_t>(sid.objectId, PoolIds::TM_LAST_RESET_STATUS, this);
lp_var_t<int32_t> mcuTemperature =
lp_var_t<int32_t>(sid.objectId, PoolIds::TM_MCU_TEMPERATURE, this);
lp_var_t<float> pressureSensorTemperature =
lp_var_t<float>(sid.objectId, PoolIds::PRESSURE_SENSOR_TEMPERATURE, this);
lp_var_t<float> pressure = lp_var_t<float>(sid.objectId, PoolIds::PRESSURE, this);
lp_var_t<uint8_t> rwState = lp_var_t<uint8_t>(sid.objectId, PoolIds::TM_RW_STATE, this);
lp_var_t<uint8_t> rwClcMode = lp_var_t<uint8_t>(sid.objectId, PoolIds::TM_CLC_MODE, this);
lp_var_t<int32_t> rwCurrSpeed = lp_var_t<int32_t>(sid.objectId, PoolIds::TM_RW_CURR_SPEED, this);
lp_var_t<int32_t> rwRefSpeed = lp_var_t<int32_t>(sid.objectId, PoolIds::TM_RW_REF_SPEED, this);
lp_var_t<uint32_t> numOfInvalidCrcPackets =
lp_var_t<uint32_t>(sid.objectId, PoolIds::INVALID_CRC_PACKETS, this);
lp_var_t<uint32_t> numOfInvalidLenPackets =
lp_var_t<uint32_t>(sid.objectId, PoolIds::INVALID_LEN_PACKETS, this);
lp_var_t<uint32_t> numOfInvalidCmdPackets =
lp_var_t<uint32_t>(sid.objectId, PoolIds::INVALID_CMD_PACKETS, this);
lp_var_t<uint32_t> numOfCmdExecutedReplies =
lp_var_t<uint32_t>(sid.objectId, PoolIds::EXECUTED_REPLIES, this);
lp_var_t<uint32_t> numOfCmdReplies =
lp_var_t<uint32_t>(sid.objectId, PoolIds::COMMAND_REPLIES, this);
lp_var_t<uint32_t> uartNumOfBytesWritten =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_BYTES_WRITTEN, this);
lp_var_t<uint32_t> uartNumOfBytesRead =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_BYTES_READ, this);
lp_var_t<uint32_t> uartNumOfParityErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_PARITY_ERRORS, this);
lp_var_t<uint32_t> uartNumOfNoiseErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_NOISE_ERRORS, this);
lp_var_t<uint32_t> uartNumOfFrameErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_FRAME_ERRORS, this);
lp_var_t<uint32_t> uartNumOfRegisterOverrunErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_REG_OVERRUN_ERRORS, this);
lp_var_t<uint32_t> uartTotalNumOfErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::UART_TOTAL_ERRORS, this);
lp_var_t<uint32_t> spiNumOfBytesWritten =
lp_var_t<uint32_t>(sid.objectId, PoolIds::SPI_BYTES_WRITTEN, this);
lp_var_t<uint32_t> spiNumOfBytesRead =
lp_var_t<uint32_t>(sid.objectId, PoolIds::SPI_BYTES_READ, this);
lp_var_t<uint32_t> spiNumOfRegisterOverrunErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::SPI_REG_OVERRUN_ERRORS, this);
lp_var_t<uint32_t> spiTotalNumOfErrors =
lp_var_t<uint32_t>(sid.objectId, PoolIds::SPI_TOTAL_ERRORS, this);
2021-06-30 08:21:14 +02:00
};
2023-02-10 11:26:46 +01:00
class RwSpeedActuationSet : public StaticLocalDataSet<2> {
2023-02-09 17:55:20 +01:00
friend class RwHandler;
2023-02-09 17:11:23 +01:00
public:
RwSpeedActuationSet(HasLocalDataPoolIF& owner)
2023-02-15 17:02:22 +01:00
: StaticLocalDataSet(&owner, rws::SetIds::SPEED_CMD_SET) {}
2023-02-09 17:11:23 +01:00
RwSpeedActuationSet(object_id_t objectId)
2023-02-15 17:02:22 +01:00
: StaticLocalDataSet(sid_t(objectId, rws::SetIds::SPEED_CMD_SET)) {}
2023-02-09 17:11:23 +01:00
2023-02-10 11:26:46 +01:00
void setRwSpeed(int32_t rwSpeed_, uint16_t rampTime_) {
2023-02-09 17:11:23 +01:00
if (rwSpeed.value != rwSpeed_) {
2023-02-10 11:26:46 +01:00
rwSpeed = rwSpeed_;
}
if (rampTime.value != rampTime_) {
rampTime = rampTime_;
2023-02-09 17:11:23 +01:00
}
}
2023-02-10 11:26:46 +01:00
void getRwSpeed(int32_t& rwSpeed_, uint16_t& rampTime_) {
rwSpeed_ = rwSpeed.value;
rampTime_ = rampTime.value;
}
2023-02-09 17:11:23 +01:00
private:
2023-02-15 17:02:22 +01:00
lp_var_t<int32_t> rwSpeed = lp_var_t<int32_t>(sid.objectId, rws::PoolIds::RW_SPEED, this);
lp_var_t<uint16_t> rampTime = lp_var_t<uint16_t>(sid.objectId, rws::PoolIds::RAMP_TIME, this);
2023-02-09 17:11:23 +01:00
};
2023-02-15 17:02:22 +01:00
} // namespace rws
2021-06-21 09:50:26 +02:00
2023-02-17 02:10:08 +01:00
/**
* Raw pointer overlay to hold the different frames received from the reaction
* wheel in a raw buffer and send them to the device handler.
*/
struct RwReplies {
friend class RwPollingTask;
public:
RwReplies(const uint8_t* rawData) : rawData(const_cast<uint8_t*>(rawData)) { initPointers(); }
2023-02-17 02:10:08 +01:00
const uint8_t* getClearLastResetStatusReply() const { return clearLastResetStatusReply + 1; }
bool wasClearLastRsetStatusReplyRead() const { return clearLastResetStatusReply[0]; }
2023-02-17 02:10:08 +01:00
const uint8_t* getGetLastResetStatusReply() const { return getLastResetStatusReply + 1; }
bool wasGetLastStatusReplyRead() const { return getLastResetStatusReply[0]; }
2023-02-17 02:10:08 +01:00
const uint8_t* getHkDataReply() const { return hkDataReply + 1; }
bool wasHkDataReplyRead() const { return hkDataReply[0]; }
2023-02-17 02:10:08 +01:00
const uint8_t* getInitRwControllerReply() const { return initRwControllerReply + 1; }
bool wasInitRwControllerReplyRead() const { return initRwControllerReply[0]; }
const uint8_t* getRawData() const { return rawData; }
2023-02-17 02:10:08 +01:00
const uint8_t* getReadTemperatureReply() const { return readTemperatureReply + 1; }
bool wasReadTemperatureReplySet() const { return readTemperatureReply[0]; }
2023-02-17 02:10:08 +01:00
const uint8_t* getRwStatusReply() const { return rwStatusReply + 1; }
bool wasRwStatusRead() const { return rwStatusReply[0]; }
2023-02-17 02:10:08 +01:00
const uint8_t* getSetSpeedReply() const { return setSpeedReply + 1; }
bool wasSetSpeedReplyRead() const { return setSpeedReply[0]; }
private:
RwReplies(uint8_t* rwData) : rawData(rwData) { initPointers(); }
2023-02-17 02:10:08 +01:00
/**
* The first byte of the reply buffers contains a flag which shows whether that
* frame was read from the reaction wheel at least once.
*/
void initPointers() {
rwStatusReply = rawData;
2023-02-17 02:10:08 +01:00
setSpeedReply = rawData + rws::SIZE_GET_RW_STATUS + 1;
getLastResetStatusReply = setSpeedReply + rws::SIZE_SET_SPEED_REPLY + 1;
clearLastResetStatusReply = getLastResetStatusReply + rws::SIZE_GET_RESET_STATUS + 1;
readTemperatureReply = clearLastResetStatusReply + rws::SIZE_CLEAR_RESET_STATUS + 1;
hkDataReply = readTemperatureReply + rws::SIZE_GET_TEMPERATURE_REPLY + 1;
initRwControllerReply = hkDataReply + rws::SIZE_GET_TELEMETRY_REPLY + 1;
dummyPointer = initRwControllerReply + rws::SIZE_INIT_RW + 1;
}
uint8_t* rawData;
uint8_t* rwStatusReply;
uint8_t* setSpeedReply;
uint8_t* getLastResetStatusReply;
uint8_t* clearLastResetStatusReply;
uint8_t* readTemperatureReply;
uint8_t* hkDataReply;
uint8_t* initRwControllerReply;
uint8_t* dummyPointer;
};
2023-02-15 17:02:22 +01:00
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_RWHELPERS_H_ */