2021-02-27 19:46:13 +01:00
|
|
|
#include "SolarArrayDeploymentHandler.h"
|
|
|
|
|
2021-02-16 15:32:24 +01:00
|
|
|
#include <devices/gpioIds.h>
|
2022-01-18 11:41:19 +01:00
|
|
|
#include <devices/powerSwitcherList.h>
|
2021-02-23 13:38:43 +01:00
|
|
|
#include <fsfw/ipc/QueueFactory.h>
|
2021-06-08 16:45:25 +02:00
|
|
|
#include <fsfw/objectmanager/ObjectManager.h>
|
2022-01-18 11:41:19 +01:00
|
|
|
#include <fsfw_hal/common/gpio/GpioCookie.h>
|
2021-02-16 15:32:24 +01:00
|
|
|
|
|
|
|
SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_,
|
2022-01-18 11:41:19 +01:00
|
|
|
object_id_t gpioDriverId_,
|
|
|
|
CookieIF* gpioCookie_,
|
|
|
|
object_id_t mainLineSwitcherObjectId_,
|
|
|
|
uint8_t mainLineSwitch_, gpioId_t deplSA1,
|
|
|
|
gpioId_t deplSA2, uint32_t burnTimeMs)
|
|
|
|
: SystemObject(setObjectId_),
|
|
|
|
gpioDriverId(gpioDriverId_),
|
|
|
|
gpioCookie(gpioCookie_),
|
|
|
|
mainLineSwitcherObjectId(mainLineSwitcherObjectId_),
|
|
|
|
mainLineSwitch(mainLineSwitch_),
|
|
|
|
deplSA1(deplSA1),
|
|
|
|
deplSA2(deplSA2),
|
|
|
|
burnTimeMs(burnTimeMs),
|
|
|
|
actionHelper(this, nullptr) {
|
|
|
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
|
|
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
2022-01-18 11:41:19 +01:00
|
|
|
SolarArrayDeploymentHandler::~SolarArrayDeploymentHandler() {}
|
2021-02-16 15:32:24 +01:00
|
|
|
|
|
|
|
ReturnValue_t SolarArrayDeploymentHandler::performOperation(uint8_t operationCode) {
|
2022-01-18 11:41:19 +01:00
|
|
|
if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
|
|
|
|
handleStateMachine();
|
2021-02-16 15:32:24 +01:00
|
|
|
return RETURN_OK;
|
2022-01-18 11:41:19 +01:00
|
|
|
}
|
|
|
|
return RETURN_OK;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t SolarArrayDeploymentHandler::initialize() {
|
2022-01-18 11:41:19 +01:00
|
|
|
ReturnValue_t result = SystemObject::initialize();
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
gpioInterface = ObjectManager::instance()->get<GpioIF>(gpioDriverId);
|
|
|
|
if (gpioInterface == nullptr) {
|
|
|
|
sif::error << "SolarArrayDeploymentHandler::initialize: Invalid Gpio interface." << std::endl;
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = gpioInterface->addGpios(dynamic_cast<GpioCookie*>(gpioCookie));
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
sif::error << "SolarArrayDeploymentHandler::initialize: Failed to initialize Gpio interface"
|
|
|
|
<< std::endl;
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mainLineSwitcherObjectId != objects::NO_OBJECT) {
|
|
|
|
mainLineSwitcher = ObjectManager::instance()->get<PowerSwitchIF>(mainLineSwitcherObjectId);
|
|
|
|
if (mainLineSwitcher == nullptr) {
|
|
|
|
sif::error
|
|
|
|
<< "SolarArrayDeploymentHandler::initialize: Main line switcher failed to fetch object"
|
|
|
|
<< "from object ID." << std::endl;
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
2022-01-18 11:41:19 +01:00
|
|
|
}
|
2021-02-16 15:32:24 +01:00
|
|
|
|
2022-01-18 11:41:19 +01:00
|
|
|
result = actionHelper.initialize(commandQueue);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
2021-02-16 15:32:24 +01:00
|
|
|
|
2022-01-18 11:41:19 +01:00
|
|
|
return RETURN_OK;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SolarArrayDeploymentHandler::handleStateMachine() {
|
2022-01-18 11:41:19 +01:00
|
|
|
switch (stateMachine) {
|
2021-02-16 15:32:24 +01:00
|
|
|
case WAIT_ON_DELOYMENT_COMMAND:
|
2022-01-18 11:41:19 +01:00
|
|
|
readCommandQueue();
|
|
|
|
break;
|
2021-02-16 15:32:24 +01:00
|
|
|
case SWITCH_8V_ON:
|
2022-01-18 11:41:19 +01:00
|
|
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON);
|
|
|
|
mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
|
|
|
|
stateMachine = WAIT_ON_8V_SWITCH;
|
|
|
|
break;
|
2021-02-16 15:32:24 +01:00
|
|
|
case WAIT_ON_8V_SWITCH:
|
2022-01-18 11:41:19 +01:00
|
|
|
performWaitOn8VActions();
|
|
|
|
break;
|
2021-02-16 15:32:24 +01:00
|
|
|
case SWITCH_DEPL_GPIOS:
|
2022-01-18 11:41:19 +01:00
|
|
|
switchDeploymentTransistors();
|
|
|
|
break;
|
2021-02-16 15:32:24 +01:00
|
|
|
case WAIT_ON_DEPLOYMENT_FINISH:
|
2022-01-18 11:41:19 +01:00
|
|
|
handleDeploymentFinish();
|
|
|
|
break;
|
2021-02-16 15:32:24 +01:00
|
|
|
case WAIT_FOR_MAIN_SWITCH_OFF:
|
2022-01-18 11:41:19 +01:00
|
|
|
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_OFF) {
|
|
|
|
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
|
|
|
|
} else if (mainSwitchCountdown.hasTimedOut()) {
|
|
|
|
triggerEvent(MAIN_SWITCH_OFF_TIMEOUT);
|
|
|
|
sif::error << "SolarArrayDeploymentHandler::handleStateMachine: Failed to switch main"
|
|
|
|
<< " switch off" << std::endl;
|
|
|
|
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
|
|
|
|
}
|
|
|
|
break;
|
2021-02-16 15:32:24 +01:00
|
|
|
default:
|
2022-01-18 11:41:19 +01:00
|
|
|
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Invalid state" << std::endl;
|
|
|
|
break;
|
|
|
|
}
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SolarArrayDeploymentHandler::performWaitOn8VActions() {
|
2022-01-18 11:41:19 +01:00
|
|
|
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == PowerSwitchIF::SWITCH_ON) {
|
|
|
|
stateMachine = SWITCH_DEPL_GPIOS;
|
|
|
|
} else {
|
|
|
|
if (mainSwitchCountdown.hasTimedOut()) {
|
|
|
|
triggerEvent(MAIN_SWITCH_ON_TIMEOUT);
|
|
|
|
actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS,
|
|
|
|
MAIN_SWITCH_TIMEOUT_FAILURE);
|
|
|
|
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
2022-01-18 11:41:19 +01:00
|
|
|
}
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SolarArrayDeploymentHandler::switchDeploymentTransistors() {
|
2022-01-18 11:41:19 +01:00
|
|
|
ReturnValue_t result = RETURN_OK;
|
|
|
|
result = gpioInterface->pullHigh(deplSA1);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
|
|
|
|
" array deployment switch 1 high "
|
|
|
|
<< std::endl;
|
|
|
|
/* If gpio switch high failed, state machine is reset to wait for a command reinitiating
|
|
|
|
* the deployment sequence. */
|
|
|
|
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
|
|
|
|
triggerEvent(DEPL_SA1_GPIO_SWTICH_ON_FAILED);
|
|
|
|
actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, SWITCHING_DEPL_SA2_FAILED);
|
|
|
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
|
|
|
}
|
|
|
|
result = gpioInterface->pullHigh(deplSA2);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
|
|
|
|
" array deployment switch 2 high "
|
|
|
|
<< std::endl;
|
|
|
|
stateMachine = WAIT_ON_DELOYMENT_COMMAND;
|
|
|
|
triggerEvent(DEPL_SA2_GPIO_SWTICH_ON_FAILED);
|
|
|
|
actionHelper.finish(false, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, SWITCHING_DEPL_SA2_FAILED);
|
|
|
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
|
|
|
}
|
|
|
|
deploymentCountdown.setTimeout(burnTimeMs);
|
|
|
|
stateMachine = WAIT_ON_DEPLOYMENT_FINISH;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SolarArrayDeploymentHandler::handleDeploymentFinish() {
|
2022-01-18 11:41:19 +01:00
|
|
|
ReturnValue_t result = RETURN_OK;
|
|
|
|
if (deploymentCountdown.hasTimedOut()) {
|
|
|
|
actionHelper.finish(true, rememberCommanderId, DEPLOY_SOLAR_ARRAYS, RETURN_OK);
|
|
|
|
result = gpioInterface->pullLow(deplSA1);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
|
|
|
|
" array deployment switch 1 low "
|
|
|
|
<< std::endl;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
2022-01-18 11:41:19 +01:00
|
|
|
result = gpioInterface->pullLow(deplSA2);
|
2021-02-16 15:32:24 +01:00
|
|
|
if (result != RETURN_OK) {
|
2022-01-18 11:41:19 +01:00
|
|
|
sif::debug << "SolarArrayDeploymentHandler::handleStateMachine: Failed to pull solar"
|
|
|
|
" array deployment switch 2 low "
|
|
|
|
<< std::endl;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
2022-01-18 11:41:19 +01:00
|
|
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
|
|
|
mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
|
|
|
|
stateMachine = WAIT_FOR_MAIN_SWITCH_OFF;
|
|
|
|
}
|
|
|
|
}
|
2021-02-16 15:32:24 +01:00
|
|
|
|
2022-01-18 11:41:19 +01:00
|
|
|
void SolarArrayDeploymentHandler::readCommandQueue() {
|
|
|
|
CommandMessage command;
|
|
|
|
ReturnValue_t result = commandQueue->receiveMessage(&command);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = actionHelper.handleActionMessage(&command);
|
|
|
|
if (result == RETURN_OK) {
|
|
|
|
return;
|
|
|
|
}
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t SolarArrayDeploymentHandler::executeAction(ActionId_t actionId,
|
2022-01-18 11:41:19 +01:00
|
|
|
MessageQueueId_t commandedBy,
|
|
|
|
const uint8_t* data, size_t size) {
|
|
|
|
ReturnValue_t result;
|
|
|
|
if (stateMachine != WAIT_ON_DELOYMENT_COMMAND) {
|
|
|
|
sif::error << "SolarArrayDeploymentHandler::executeAction: Received command while not in"
|
|
|
|
<< "waiting-on-command-state" << std::endl;
|
|
|
|
return DEPLOYMENT_ALREADY_EXECUTING;
|
|
|
|
}
|
|
|
|
if (actionId != DEPLOY_SOLAR_ARRAYS) {
|
|
|
|
sif::error << "SolarArrayDeploymentHandler::executeAction: Received invalid command"
|
|
|
|
<< std::endl;
|
|
|
|
result = COMMAND_NOT_SUPPORTED;
|
|
|
|
} else {
|
|
|
|
stateMachine = SWITCH_8V_ON;
|
|
|
|
rememberCommanderId = commandedBy;
|
|
|
|
result = RETURN_OK;
|
|
|
|
}
|
|
|
|
return result;
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
MessageQueueId_t SolarArrayDeploymentHandler::getCommandQueue() const {
|
2022-01-18 11:41:19 +01:00
|
|
|
return commandQueue->getId();
|
2021-02-16 15:32:24 +01:00
|
|
|
}
|