eive-obsw/mission/devices/RwHandler.cpp

405 lines
15 KiB
C++
Raw Normal View History

2021-06-21 09:50:26 +02:00
#include "RwHandler.h"
#include "OBSWConfig.h"
#include <fsfw/globalfunctions/CRC.h>
#include <fsfw/datapool/PoolReadGuard.h>
2021-06-22 13:48:30 +02:00
RwHandler::RwHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie,
LinuxLibgpioIF* gpioComIF, gpioId_t enableGpio) :
2021-06-24 12:04:36 +02:00
DeviceHandlerBase(objectId, comIF, comCookie), gpioComIF(gpioComIF), enableGpio(enableGpio),
temperatureSet(this), statusSet(this), lastResetStatusSet(this) {
2021-06-22 13:48:30 +02:00
if (comCookie == NULL) {
sif::error << "RwHandler: Invalid com cookie" << std::endl;
}
if (gpioComIF == NULL) {
sif::error << "RwHandler: Invalid gpio communication interface" << std::endl;
}
2021-06-21 09:50:26 +02:00
}
RwHandler::~RwHandler() {
}
void RwHandler::doStartUp() {
2021-06-29 16:08:20 +02:00
internalState = InternalState::GET_RESET_STATUS;
if(gpioComIF->pullHigh(enableGpio) != RETURN_OK) {
sif::debug << "RwHandler::doStartUp: Failed to pull enable gpio to high";
}
2021-06-28 14:07:37 +02:00
2021-06-21 09:50:26 +02:00
#if OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP == 1
setMode(MODE_NORMAL);
#else
setMode(_MODE_TO_ON);
#endif
}
void RwHandler::doShutDown() {
2021-06-24 12:04:36 +02:00
if(gpioComIF->pullLow(enableGpio) != RETURN_OK) {
sif::debug << "RwHandler::doStartUp: Failed to pull enable gpio to low";
}
2021-06-21 09:50:26 +02:00
}
ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t * id) {
2021-06-29 16:08:20 +02:00
switch (internalState) {
case InternalState::GET_RESET_STATUS:
*id = RwDefinitions::GET_LAST_RESET_STATUS;
2021-06-29 16:08:20 +02:00
internalState = InternalState::READ_TEMPERATURE;
break;
case InternalState::CLEAR_RESET_STATUS:
*id = RwDefinitions::CLEAR_LAST_RESET_STATUS;
/** After reset status is cleared, reset status will be polled again for verification */
internalState = InternalState::GET_RESET_STATUS;
break;
2021-06-29 16:08:20 +02:00
case InternalState::READ_TEMPERATURE:
2021-06-21 09:50:26 +02:00
*id = RwDefinitions::GET_TEMPERATURE;
2021-06-29 16:08:20 +02:00
internalState = InternalState::GET_RW_SATUS;
2021-06-21 09:50:26 +02:00
break;
2021-06-29 16:08:20 +02:00
case InternalState::GET_RW_SATUS:
2021-06-21 09:50:26 +02:00
*id = RwDefinitions::GET_RW_STATUS;
2021-06-29 16:08:20 +02:00
internalState = InternalState::GET_RESET_STATUS;
2021-06-21 09:50:26 +02:00
break;
default:
sif::debug << "RwHandler::buildNormalDeviceCommand: Invalid communication step"
<< std::endl;
break;
}
return buildCommandFromCommand(*id, NULL, 0);
}
ReturnValue_t RwHandler::buildTransitionDeviceCommand(DeviceCommandId_t * id) {
2021-06-29 16:08:20 +02:00
return RETURN_OK;
2021-06-21 09:50:26 +02:00
}
ReturnValue_t RwHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t * commandData, size_t commandDataLen) {
ReturnValue_t result = RETURN_OK;
switch (deviceCommand) {
case (RwDefinitions::RESET_MCU): {
2021-06-29 16:08:20 +02:00
prepareResetMcuCommand();
return RETURN_OK;
}
case (RwDefinitions::GET_LAST_RESET_STATUS): {
prepareGetLastResetStatusCommand();
return RETURN_OK;
}
case (RwDefinitions::CLEAR_LAST_RESET_STATUS): {
prepareClearResetStatusCommand();
return RETURN_OK;
}
2021-06-21 09:50:26 +02:00
case (RwDefinitions::GET_RW_STATUS): {
prepareGetStatusCmd(commandData, commandDataLen);
return RETURN_OK;
}
2021-06-25 16:00:32 +02:00
case (RwDefinitions::INIT_RW_CONTROLLER): {
prepareInitRwCommand();
return RETURN_OK;
}
2021-06-21 09:50:26 +02:00
case (RwDefinitions::SET_SPEED): {
if (commandDataLen != 6) {
sif::error << "RwHandler::buildCommandFromCommand: Received set speed command with"
<< " invalid length" << std::endl;
return SET_SPEED_COMMAND_INVALID_LENGTH;
}
result = checkSpeedAndRampTime(commandData, commandDataLen);
if (result != RETURN_OK) {
return result;
}
prepareSetSpeedCmd(commandData, commandDataLen);
return result;
}
case (RwDefinitions::GET_TEMPERATURE): {
prepareGetTemperatureCmd();
return RETURN_OK;
}
default:
return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED;
}
return HasReturnvaluesIF::RETURN_FAILED;
}
void RwHandler::fillCommandAndReplyMap() {
2021-06-28 14:07:37 +02:00
this->insertInCommandMap(RwDefinitions::RESET_MCU);
this->insertInCommandAndReplyMap(RwDefinitions::GET_LAST_RESET_STATUS, 1, &lastResetStatusSet,
RwDefinitions::SIZE_GET_RESET_STATUS);
this->insertInCommandAndReplyMap(RwDefinitions::CLEAR_LAST_RESET_STATUS, 1, nullptr,
RwDefinitions::SIZE_CLEAR_RESET_STATUS);
this->insertInCommandAndReplyMap(RwDefinitions::GET_RW_STATUS, 1, &statusSet,
RwDefinitions::SIZE_GET_RW_STATUS);
this->insertInCommandAndReplyMap(RwDefinitions::INIT_RW_CONTROLLER, 1, nullptr,
RwDefinitions::SIZE_INIT_RW);
this->insertInCommandAndReplyMap(RwDefinitions::GET_TEMPERATURE, 1, &temperatureSet,
RwDefinitions::SIZE_GET_TEMPERATURE_REPLY);
this->insertInCommandAndReplyMap(RwDefinitions::SET_SPEED, 1, nullptr,
RwDefinitions::SIZE_SET_SPEED_REPLY);
2021-06-21 09:50:26 +02:00
}
ReturnValue_t RwHandler::scanForReply(const uint8_t *start, size_t remainingSize,
DeviceCommandId_t *foundId, size_t *foundLen) {
switch (*(start)) {
case (static_cast<uint8_t>(RwDefinitions::GET_LAST_RESET_STATUS)): {
*foundLen = RwDefinitions::SIZE_GET_RESET_STATUS;
*foundId = RwDefinitions::GET_LAST_RESET_STATUS;
break;
}
2021-06-28 14:07:37 +02:00
case (static_cast<uint8_t>(RwDefinitions::CLEAR_LAST_RESET_STATUS)): {
*foundLen = RwDefinitions::SIZE_CLEAR_RESET_STATUS;
*foundId = RwDefinitions::CLEAR_LAST_RESET_STATUS;
break;
}
2021-06-21 09:50:26 +02:00
case (static_cast<uint8_t>(RwDefinitions::GET_RW_STATUS)): {
*foundLen = RwDefinitions::SIZE_GET_RW_STATUS;
*foundId = RwDefinitions::GET_RW_STATUS;
break;
}
2021-06-28 14:07:37 +02:00
case (static_cast<uint8_t>(RwDefinitions::INIT_RW_CONTROLLER)): {
*foundLen = RwDefinitions::SIZE_INIT_RW;
*foundId = RwDefinitions::INIT_RW_CONTROLLER;
break;
}
2021-06-21 09:50:26 +02:00
case (static_cast<uint8_t>(RwDefinitions::SET_SPEED)): {
*foundLen = RwDefinitions::SIZE_SET_SPEED_REPLY;
*foundId = RwDefinitions::SET_SPEED;
break;
}
case (static_cast<uint8_t>(RwDefinitions::GET_TEMPERATURE)): {
*foundLen = RwDefinitions::SIZE_GET_TEMPERATURE_REPLY;
*foundId = RwDefinitions::GET_TEMPERATURE;
break;
}
default: {
sif::debug << "RwHandler::scanForReply: Reply contains invalid command code" << std::endl;
return RETURN_FAILED;
break;
}
}
sizeOfReply = *foundLen;
return RETURN_OK;
}
ReturnValue_t RwHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
/** Check result code */
if (*(packet + 1) == RwDefinitions::ERROR) {
2021-06-28 14:07:37 +02:00
sif::error << "RwHandler::interpretDeviceReply: Command execution failed. Command id: "
<< id << std::endl;
2021-06-21 09:50:26 +02:00
return EXECUTION_FAILED;
}
/** Received in little endian byte order */
uint16_t replyCrc = *(packet + sizeOfReply - 1) << 8 | *(packet + sizeOfReply - 2) ;
if (CRC::crc16ccitt(packet, sizeOfReply - 2, 0xFFFF) != replyCrc) {
sif::error << "RwHandler::interpretDeviceReply: cRC error" << std::endl;
2021-06-21 09:50:26 +02:00
return CRC_ERROR;
}
switch (id) {
case (RwDefinitions::GET_LAST_RESET_STATUS): {
handleResetStatusReply(packet);
break;
}
2021-06-21 09:50:26 +02:00
case (RwDefinitions::GET_RW_STATUS): {
handleGetRwStatusReply(packet);
break;
}
2021-06-28 14:07:37 +02:00
case (RwDefinitions::CLEAR_LAST_RESET_STATUS):
case (RwDefinitions::INIT_RW_CONTROLLER):
2021-06-21 09:50:26 +02:00
case (RwDefinitions::SET_SPEED):
// no reply data expected
break;
case (RwDefinitions::GET_TEMPERATURE): {
handleTemperatureReply(packet);
break;
}
default: {
sif::debug << "RwHandler::interpretDeviceReply: Unknown device reply id" << std::endl;
return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY;
}
}
return RETURN_OK;
}
void RwHandler::setNormalDatapoolEntriesInvalid() {
}
uint32_t RwHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) {
2021-06-29 16:08:20 +02:00
return 500;
2021-06-21 09:50:26 +02:00
}
ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(RwDefinitions::TEMPERATURE_C, new PoolEntry<int32_t>( { 0 }));
2021-06-29 16:08:20 +02:00
localDataPoolMap.emplace(RwDefinitions::CURR_SPEED, new PoolEntry<int32_t>( { 0 }));
localDataPoolMap.emplace(RwDefinitions::REFERENCE_SPEED, new PoolEntry<int32_t>( { 0 }));
localDataPoolMap.emplace(RwDefinitions::STATE, new PoolEntry<uint8_t>( { 0 }));
localDataPoolMap.emplace(RwDefinitions::CLC_MODE, new PoolEntry<uint8_t>( { 0 }));
localDataPoolMap.emplace(RwDefinitions::LAST_RESET_STATUS, new PoolEntry<uint8_t>( { 0 }));
localDataPoolMap.emplace(RwDefinitions::CURRRENT_RESET_STATUS, new PoolEntry<uint8_t>( { 0 }));
2021-06-21 09:50:26 +02:00
return RETURN_OK;
}
2021-06-29 16:08:20 +02:00
void RwHandler::prepareResetMcuCommand() {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::RESET_MCU);
rawPacket = commandBuffer;
rawPacketLen = 1;
}
void RwHandler::prepareGetLastResetStatusCommand() {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::GET_LAST_RESET_STATUS);
uint16_t crc = CRC::crc16ccitt(commandBuffer, 1, 0xFFFF);
commandBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
commandBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
rawPacket = commandBuffer;
rawPacketLen = 3;
}
void RwHandler::prepareClearResetStatusCommand() {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::CLEAR_LAST_RESET_STATUS);
uint16_t crc = CRC::crc16ccitt(commandBuffer, 1, 0xFFFF);
commandBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
commandBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
rawPacket = commandBuffer;
rawPacketLen = 3;
}
2021-06-21 09:50:26 +02:00
void RwHandler::prepareGetStatusCmd(const uint8_t * commandData, size_t commandDataLen) {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::GET_RW_STATUS);
uint16_t crc = CRC::crc16ccitt(commandBuffer, 1, 0xFFFF);
commandBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
commandBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
rawPacket = commandBuffer;
rawPacketLen = 3;
}
ReturnValue_t RwHandler::checkSpeedAndRampTime(const uint8_t* commandData, size_t commandDataLen) {
int32_t speed = *commandData << 24 | *(commandData + 1) << 16 | *(commandData + 2) << 8
| *(commandData + 3);
2021-06-29 09:50:50 +02:00
if ((speed < -65000 || speed > 65000 || (speed > -1000 && speed < 1000)) && (speed != 0)) {
2021-06-21 09:50:26 +02:00
sif::error << "RwHandler::checkSpeedAndRampTime: Command has invalid speed" << std::endl;
return INVALID_SPEED;
}
2021-06-25 15:25:54 +02:00
uint16_t rampTime = *(commandData + 4) << 8 | *(commandData + 5);
2021-06-21 09:50:26 +02:00
if (rampTime < 10 || rampTime > 10000) {
sif::error << "RwHandler::checkSpeedAndRampTime: Command has invalid ramp time"
<< std::endl;
return INVALID_RAMP_TIME;
}
return RETURN_OK;
}
void RwHandler::prepareInitRwCommand() {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::INIT_RW_CONTROLLER);
2021-06-21 09:50:26 +02:00
uint16_t crc = CRC::crc16ccitt(commandBuffer, 1, 0xFFFF);
commandBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
commandBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
rawPacket = commandBuffer;
rawPacketLen = 3;
}
void RwHandler::prepareGetTemperatureCmd() {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::GET_TEMPERATURE);
2021-06-25 16:00:32 +02:00
uint16_t crc = CRC::crc16ccitt(commandBuffer, 1, 0xFFFF);
commandBuffer[1] = static_cast<uint8_t>(crc & 0xFF);
commandBuffer[2] = static_cast<uint8_t>(crc >> 8 & 0xFF);
rawPacket = commandBuffer;
rawPacketLen = 3;
}
2021-06-21 09:50:26 +02:00
void RwHandler::prepareSetSpeedCmd(const uint8_t * commandData, size_t commandDataLen) {
commandBuffer[0] = static_cast<uint8_t>(RwDefinitions::SET_SPEED);
/** Speed (0.1 RPM) */
commandBuffer[1] = *(commandData + 3);
commandBuffer[2] = *(commandData + 2);
commandBuffer[3] = *(commandData + 1);
commandBuffer[4] = *commandData;
/** Ramp time (ms) */
2021-06-25 15:25:54 +02:00
commandBuffer[5] = *(commandData + 5);
commandBuffer[6] = *(commandData + 4);
2021-06-21 09:50:26 +02:00
uint16_t crc = CRC::crc16ccitt(commandBuffer, 7, 0xFFFF);
commandBuffer[7] = static_cast<uint8_t>(crc & 0xFF);
commandBuffer[8] = static_cast<uint8_t>(crc >> 8 & 0xFF);
rawPacket = commandBuffer;
rawPacketLen = 9;
}
void RwHandler::handleResetStatusReply(const uint8_t* packet) {
2021-06-29 16:08:20 +02:00
PoolReadGuard rg(&lastResetStatusSet);
uint8_t offset = 2;
2021-06-29 16:08:20 +02:00
uint8_t resetStatus = *(packet + offset);
if (resetStatus != RwDefinitions::CLEARED) {
internalState = InternalState::CLEAR_RESET_STATUS;
lastResetStatusSet.lastResetStatus = resetStatus;
}
lastResetStatusSet.currentResetStatus = resetStatus;
#if OBSW_VERBOSE_LEVEL >= 1 && RW_DEBUG == 1
sif::info << "RwHandler::handleResetStatusReply: Last reset status: "
<< static_cast<unsigned int>(lastResetStatusSet.lastResetStatus.value) << std::endl;
2021-06-29 16:08:20 +02:00
sif::info << "RwHandler::handleResetStatusReply: Current reset status: "
<< static_cast<unsigned int>(lastResetStatusSet.currentResetStatus.value) << std::endl;
#endif
}
2021-06-21 09:50:26 +02:00
void RwHandler::handleGetRwStatusReply(const uint8_t* packet) {
2021-06-29 16:08:20 +02:00
PoolReadGuard rg(&statusSet);
uint8_t offset = 2;
statusSet.currSpeed = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
2021-06-25 15:25:54 +02:00
| *(packet + offset + 1) << 8 | *(packet + offset);
2021-06-21 09:50:26 +02:00
offset += 4;
statusSet.referenceSpeed = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
2021-06-25 15:25:54 +02:00
| *(packet + offset + 1) << 8 | *(packet + offset);
2021-06-21 09:50:26 +02:00
offset += 4;
statusSet.state = *(packet + offset);
offset += 1;
statusSet.clcMode = *(packet + offset);
2021-06-29 16:08:20 +02:00
if (statusSet.state == RwDefinitions::ERROR) {
/**
* This requires the commanding of the init reaction wheel controller command to recover
* form error state which must be handled by the FDIR instance.
*/
triggerEvent(ERROR_STATE);
sif::error << "RwHandler::handleGetRwStatusReply: Reaction wheel in error state"
<< std::endl;
}
2021-06-21 09:50:26 +02:00
#if OBSW_VERBOSE_LEVEL >= 1 && RW_DEBUG == 1
sif::info << "RwHandler::handleGetRwStatusReply: Current speed is: " << statusSet.currSpeed
<< " * 0.1 RPM" << std::endl;
sif::info << "RwHandler::handleGetRwStatusReply: Reference speed is: "
<< statusSet.referenceSpeed << " * 0.1 RPM" << std::endl;
sif::info << "RwHandler::handleGetRwStatusReply: State is: "
<< (unsigned int) statusSet.state.value << std::endl;
sif::info << "RwHandler::handleGetRwStatusReply: clc mode is: "
<< (unsigned int) statusSet.clcMode.value << std::endl;
2021-06-21 09:50:26 +02:00
#endif
}
void RwHandler::handleTemperatureReply(const uint8_t* packet) {
2021-06-29 16:08:20 +02:00
PoolReadGuard rg(&temperatureSet);
uint8_t offset = 2;
temperatureSet.temperatureCelcius = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16
2021-06-25 15:25:54 +02:00
| *(packet + offset + 1) << 8 | *(packet + offset);
2021-06-21 09:50:26 +02:00
#if OBSW_VERBOSE_LEVEL >= 1 && RW_DEBUG == 1
sif::info << "RwHandler::handleTemperatureReply: Temperature: "
<< temperatureSet.temperatureCelcius << " °C" << std::endl;
#endif
}