diff --git a/README.md b/README.md index 0ddf459c..20097b10 100644 --- a/README.md +++ b/README.md @@ -434,7 +434,7 @@ cmp ident List parameter table: x values: 1,2 or 4 ```` -param table x +param list x ```` Table 4 lists HK parameters Changing parameters diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/ObjectFactory.cpp index 7c33b2e4..e6ea8fa1 100644 --- a/bsp_q7s/ObjectFactory.cpp +++ b/bsp_q7s/ObjectFactory.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,8 @@ #include #include #include +#include +#include void Factory::setStaticFrameworkObjectIds() { PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR; @@ -87,6 +90,18 @@ void ObjectFactory::produce(){ i2cCookieTmp1075tcs2); tmp1075Handler_2->setStartUpImmediately(); + /* Thermal objects */ + GpioCookie gpioCookie = new GpioCookie; +#if TE0720 == 1 + // Configuration for MIO0 on TE0720-03-1CFA + GpioConfig_t gpioConfigForDummyHeater(std::string("gpiochip0"), 0, + std::string("Heater1"), Gpio::OUT); + gpioCookie.add(gpioIds::HEATER_1, gpioConfigForDummyHeater); +#else +#endif + LinuxLibgpioIF linuxLibgpioIF = new LinuxLibgpioIF(objects::GPIO_IF); + new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, ); + new TmTcUnixUdpBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, diff --git a/bsp_q7s/comIF/GpioComIF.cpp b/bsp_q7s/comIF/GpioComIF.cpp index 78ad9bba..e8d4d8e1 100644 --- a/bsp_q7s/comIF/GpioComIF.cpp +++ b/bsp_q7s/comIF/GpioComIF.cpp @@ -32,9 +32,12 @@ ReturnValue_t GpioComIF::initializeInterface(CookieIF * cookie) { } /* Register new GPIOs in gpioMap*/ - result = initializeAndConfigure(mapToAdd); - if (result != HasReturnvaluesIF::RETURN_OK){ - return result; + std::pair insertionResult = gpioMap.insert(mapToAdd.begin(), + mapToAdd.end()); + if (insertionResult.second() != true) { + sif::error << "GpioComIF::initializeAndConfigure: Failed to add " + << "GPIO " << gpioStr.c_st() << " to gpioMap" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; @@ -188,14 +191,14 @@ ReturnValue_t GpioComIF::openDevice(std::string deviceFile, } ReturnValue_t GpioComIF::checkForConflicts(GpioMap mapToAdd){ - gpio_t gpio; + gpioId_t gpioId; GpioMapIter mapToAddIter = mapToAdd.begin(); for(; mapToAddIter != mapToAdd.end(); mapToAddIter++){ gpio = mapToAddIter.first(); - if(gpioMapIter.find(gpio) != mapToAdd.end()){ + if(gpioMapIter.find(gpioId) != mapToAdd.end()){ /* An entry for this GPIO already exists. Check if configuration * of direction is equivalent */ - if (mapToAddIter.second() != gpioMapIter.second()){ + if (mapToAddIter.second.direction != gpioMapIter.second.direction){ sif::error << "GpioComIF::checkForConflicts: Detected conflict " << "for GPIO " << mapToAddIter.first() << std::endl; return HasReturnvaluesIF::RETURN_OK; diff --git a/bsp_q7s/comIF/cookies/GpioCookie.h b/bsp_q7s/comIF/cookies/GpioCookie.h deleted file mode 100644 index 22c99b76..00000000 --- a/bsp_q7s/comIF/cookies/GpioCookie.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ -#define SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ - -#include -#include - -namespace Gpio { - enum Direction { - IN = 0, - OUT = 1 - }; -} - -using gpio_t = uint32_t; -using direction_t = bool; -using GpioMap = std::unordered_map; -using GpioMapIter = GpioMap::iterator; - -/** - * @brief Cookie for the GpioComIF. Allows the GpioComIF to determine which - * GPIOs to initialize and whether they should be configured as in- or - * output. - * @details One GpioCookie can hold multiple GPIO configurations. To add a new - * GPIO configuration to a GpioCookie use the GpioCookie::addGpio - * function. - * - * @author J. Meier - */ -class GpioCookie: public CookieIF { -public: - - GpioCookie(); - - virtual ~GpioCookie(); - - void addGpio(gpioMap newEntry); - /** - * @brief Get map with register GPIOs. - */ - GpioMap getGpioMap() const; - -private: - - GpioMap gpioMap; - GpioMapIter gpioMapIter; -}; - -#endif diff --git a/bsp_q7s/gpio/GpioIF.cpp b/bsp_q7s/gpio/GpioIF.cpp new file mode 100644 index 00000000..9f20aa55 --- /dev/null +++ b/bsp_q7s/gpio/GpioIF.cpp @@ -0,0 +1,18 @@ +/* + * GpioIF.cpp + * + * Created on: 16.01.2021 + * Author: jakob + */ + +#include "GpioIF.h" + +GpioIF::GpioIF() { + // TODO Auto-generated constructor stub + +} + +GpioIF::~GpioIF() { + // TODO Auto-generated destructor stub +} + diff --git a/bsp_q7s/gpio/GpioIF.h b/bsp_q7s/gpio/GpioIF.h new file mode 100644 index 00000000..3d3733c3 --- /dev/null +++ b/bsp_q7s/gpio/GpioIF.h @@ -0,0 +1,43 @@ +#ifndef BSP_Q7S_GPIO_GPIOIF_H_ +#define BSP_Q7S_GPIO_GPIOIF_H_ + +#include +#include + +typedef uint16_t gpioId_t; + +/** + * @brief This class defines the interface for objects requiring the control + * over GPIOs. + * @author J. Meier + */ +class GpioIF : public HasReturnvaluesIF{ +public: + GpioIF(); + virtual ~GpioIF(); + + /** + * @brief Called by the GPIO using object. + * @param cookie Cookie specifying informations of the GPIOs required + * by a object. + */ + virtual ReturnValue_t initialize(CookieIF * cookie) = 0; + + /** + * @brief By implementing this function a child must provide the + * functionality to pull a certain GPIO to high logic level. + * + * @param gpioId A unique number which specifies the GPIO to drive. + */ + virtual ReturnValue_t pullHigh(gpioId_t gpioId) = 0; + + /** + * @brief By implementing this function a child must provide the + * functionality to pull a certain GPIO to low logic level. + * + * @param gpioId A unique number which specifies the GPIO to drive. + */ + virtual ReturnValue_t pullLow(gpioId_t gpioId) = 0; +}; + +#endif /* BSP_Q7S_GPIO_GPIOIF_H_ */ diff --git a/bsp_q7s/gpio/LinuxLibgpioIF.cpp b/bsp_q7s/gpio/LinuxLibgpioIF.cpp new file mode 100644 index 00000000..5070c5e1 --- /dev/null +++ b/bsp_q7s/gpio/LinuxLibgpioIF.cpp @@ -0,0 +1,134 @@ +#include +#include +#include + +LinuxLibgpioIF::LinuxLibgpioIF(object_id_t objectId) : SystemObject(objectId) { +} + +LinuxLibgpioIF::~LinuxLibgpioIF() { +} + +ReturnValue_t LinuxLibgpioIF::initialize(CookieIF * cookie){ + ReturnValue_t result; + GpioMap mapToAdd; + GpioMapIter mapToAddIter; + + if(cookie == nullptr) { + return NULLPOINTER; + } + GpioCookie* GpioCookie = dynamic_cast(cookie); + if(GpioCookie == nullptr) { + sif::error << "LinuxLibgpioIF: Invalid Gpio Cookie!" + << std::endl; + return NULLPOINTER; + } + + mapToAdd = GpioCookie->getGpioMap(); + + result = checkForConflicts(mapToAdd); + if (result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + /* Register new GPIOs in gpioMap*/ + result = initializeAndConfigure(mapToAdd); + if (result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + /* Register new GPIOs in gpioMap*/ + std::pair insertionResult = gpioMap.insert(mapToAdd.begin(), + mapToAdd.end()); + if (insertionResult.second() != true) { + sif::error << "LinuxLibgpioIF::initialize: Failed to add " + << "GPIO with ID " << mapToAddIter.first << " to gpioMap" + << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId){ + return driveGpio(gpioId, 1); +} + +ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId){ + return driveGpio(gpioId, 0); +} + +ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, + unsigned int logiclevel) { + GpioMapIter gpioMapIter = gpioMap.find(gpioId); + char *chipname; + unsigned int lineNum; + struct gpiod_chip *chip; + struct gpiod_line *line; + int result; + Gpio::Direction direction; + + /* Verify if GPIO has been configured as output */ + direction = gpioMapIter.second.direction; + if (direction != Gpio::OUT) { + sif::error << "LinuxLibgpioIF::pullHigh: GPIO with ID " << gpioId + << "not configured as output" << std::endl; + return CONFIGURATION_FAILURE; + } + + chipname = gpioMapIter.second.chipname; + chip = gpiod_chip_open_by_name(chipname); + if (!chip) { + sif::error << "LinuxLibgpioIF::pullHigh: Failed to open chip " + << chipname << ". Gpio ID: " << gpioId << std::endl; + return OPEN_CHIP_FAILURE; + } + + lineNum = gpioMapIter.second.lineNum; + line = gpiod_chip_get_line(chip, lineNum); + if (!line) { + sif::error << "LinuxLibgpioIF::pullHigh: Failed to open line. Gpio ID " + << gpioId << std::endl; + gpiod_chip_close(chip); + return OPEN_LINE_FAILURE; + } + + result = gpiod_line_request_output(line, CONSUMER, 0); + if (result < 0) { + sif::error << "LinuxLibgpioIF::pullHigh: Failed to request line " + << line << " from GPIO instance with ID: " << gpioId + << std::endl; + gpiod_line_release(line); + return REQUEST_LINE_FAILURE; + } + + result = gpiod_line_set_value(line, logiclevel); + if (result < 0) { + sif::error << "LinuxLibgpioIF::pullHigh: Failed to pull GPIO with ID " + << gpioId << "to low" << std::endl; + gpiod_line_release(line); + return PULLING_HIGH_FAILURE; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t LinuxLibgpioIF::checkForConflicts(GpioMap mapToAdd){ + gpioId_t gpioId; + GpioMapIter mapToAddIter = mapToAdd.begin(); + for(; mapToAddIter != mapToAdd.end(); mapToAddIter++){ + gpio = mapToAddIter.first(); + if(gpioMapIter.find(gpioId) != mapToAdd.end()){ + /* An entry for this GPIO already exists. Check if configuration + * of direction is equivalent */ + if (mapToAddIter.second.direction != gpioMapIter.second.direction){ + sif::error << "LinuxLibgpioIF::checkForConflicts: Detected conflict " + << "for GPIO " << mapToAddIter.first() << std::endl; + return HasReturnvaluesIF::RETURN_OK; + } + /* Remove element from map to add because a entry for this GPIO + * already exists */ + mapToAdd.erase(mapToAddIter); + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/bsp_q7s/gpio/LinuxLibgpioIF.h b/bsp_q7s/gpio/LinuxLibgpioIF.h new file mode 100644 index 00000000..37ef4c61 --- /dev/null +++ b/bsp_q7s/gpio/LinuxLibgpioIF.h @@ -0,0 +1,58 @@ +#ifndef BSP_Q7S_GPIO_LINUXLIBGPIOIF_H_ +#define BSP_Q7S_GPIO_LINUXLIBGPIOIF_H_ + +#include +#include + +/** + * @brief This class implements the GpioIF for a linux based system. The + * implementation is based on the libgpiod lib which requires linux 4.8 + * or higher. + * @note The Petalinux SDK from Xilinx supports libgpiod since Petalinux + * 2019.1. + */ +class LinuxLibgpioIF: public GpioIF, public SystemObject { +public: + + static const ReturnValue_t CONFIGURATION_FAILURE = MAKE_RETURN_CODE(0x1); + static const ReturnValue_t OPEN_CHIP_FAILURE = MAKE_RETURN_CODE(0x2); + static const ReturnValue_t OPEN_LINE_FAILURE = MAKE_RETURN_CODE(0x3); + static const ReturnValue_t REQUEST_LINE_FAILURE = MAKE_RETURN_CODE(0x4); + static const ReturnValue_t PULLING_HIGH_FAILURE = MAKE_RETURN_CODE(0x5); + + LinuxLibgpioIF(object_id_t objectId); + virtual ~LinuxLibgpioIF(); + + ReturnValue_t initialize(CookieIF * cookie) override; + ReturnValue_t pullHigh(gpioId_t gpioId) override; + ReturnValue_t pullLow(gpioId_t gpioId) override; + +private: + + static const uint8_t INTERFACE_ID = CLASS_ID::LINUX_LIBGPIO_IF; + + /*Holds the information and configuration of all used GPIOs */ + GpioMap gpioMap; + + /** + * @brief This functions drives line of a GPIO specified by the GPIO ID. + * + * @param gpioId The GPIO ID of the GPIO to drive. + * @param logiclevel The logic level to set. O or 1. + */ + ReturnValue_t driveGpio(gpioId_t gpioId, + unsigned int logiclevel); + + /** + * @brief This function checks if GPIOs are already registered and whether + * there exists a conflict in the GPIO configuration. E.g. the + * direction. + * + * @param mapToAdd The GPIOs which shall be added to the gpioMap. + * + * @return RETURN_OK if successful, otherwise RETURN_FAILED + */ + ReturnValue_t checkForConflicts(GpioMap mapToAdd); +}; + +#endif /* BSP_Q7S_GPIO_LINUXLIBGPIOIF_H_ */ diff --git a/bsp_q7s/comIF/cookies/GpioCookie.cpp b/bsp_q7s/gpio/cookies/GpioCookie.cpp similarity index 77% rename from bsp_q7s/comIF/cookies/GpioCookie.cpp rename to bsp_q7s/gpio/cookies/GpioCookie.cpp index 68d37007..60120c58 100644 --- a/bsp_q7s/comIF/cookies/GpioCookie.cpp +++ b/bsp_q7s/gpio/cookies/GpioCookie.cpp @@ -1,12 +1,12 @@ -#include +#include GpioCookie::GpioCookie() { } -void GpioCookie::addGpio(gpioMap newEntry){ +void GpioCookie::addGpio(GpioMap newEntry){ gpioMapIter = gpioMap.find(newEntry); if(gpioMapIter == gpioMap.end()) { - std::pair status = i2cDeviceMap.emplace(newEntry); + std::pair status = gpioMap.emplace(newEntry); if (status.second == false) { sif::error << "GpioCookie::addGpio: Failed to add GPIO " << newEntry.first << "to GPIO map" << std::endl; diff --git a/bsp_q7s/gpio/cookies/GpioCookie.h b/bsp_q7s/gpio/cookies/GpioCookie.h new file mode 100644 index 00000000..8d3c97da --- /dev/null +++ b/bsp_q7s/gpio/cookies/GpioCookie.h @@ -0,0 +1,68 @@ +#ifndef SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ +#define SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ + +#include +#include +#include + +namespace Gpio { + enum Direction { + IN = 0, + OUT = 1 + }; +} + +/** + * @brief Struct containing information about the GPIO to use. This is + * required by the libgpiod to access and drive a GPIO. + * @param chipname String of the chipname specifying the group which contains + * the GPIO to access. E.g. gpiochip0. To detect names of + * GPIO groups run gpiodetect on the linux command line. + * @param lineNum The offset of the GPIO within the GPIO group. + * @param consumer Name of the consumer currently accessing the GPIO. + * @param direction Specifies whether the GPIO should be used as in- or output. + */ +typedef struct GpioConfig { + GpioConfig(std::string chipname_, int lineNum_, std::string consumer_, + Gpio::Direction direction_) : + chipname(chipname_), lineNum(lineNum_), consumer(consumer_), direction( + directio_) { + } + std::string chipname; + int lineNum; + std::string consumer; + Gpio::Direction direction; +} GpioConfig_t; +using GpioMap = std::unordered_map; +using GpioMapIter = GpioMap::iterator; + +/** + * @brief Cookie for the GpioIF. Allows the GpioIF to determine which + * GPIOs to initialize and whether they should be configured as in- or + * output. + * @details One GpioCookie can hold multiple GPIO configurations. To add a new + * GPIO configuration to a GpioCookie use the GpioCookie::addGpio + * function. + * + * @author J. Meier + */ +class GpioCookie: public CookieIF { +public: + + GpioCookie(); + + virtual ~GpioCookie(); + + void addGpio(GpioMap newEntry); + /** + * @brief Get map with registered GPIOs. + */ + GpioMap getGpioMap() const; + +private: + + GpioMap gpioMap; + GpioMapIter gpioMapIter; +}; + +#endif diff --git a/fsfwconfig/OBSWConfig.h b/fsfwconfig/OBSWConfig.h index 4ceaf459..bc534929 100644 --- a/fsfwconfig/OBSWConfig.h +++ b/fsfwconfig/OBSWConfig.h @@ -12,6 +12,8 @@ // debugging. #define OBSW_ENHANCED_PRINTOUT 1 +#define TE0720 1 + #include "OBSWVersion.h" #ifdef __cplusplus diff --git a/fsfwconfig/devices/gpioIds.h b/fsfwconfig/devices/gpioIds.h new file mode 100644 index 00000000..3270ff62 --- /dev/null +++ b/fsfwconfig/devices/gpioIds.h @@ -0,0 +1,15 @@ +#ifndef FSFWCONFIG_DEVICES_GPIOIDS_H_ +#define FSFWCONFIG_DEVICES_GPIOIDS_H_ + +#include + +namespace gpioIds { + enum gpioId_t { + HEATER_1 + }; +} + + + + +#endif /* FSFWCONFIG_DEVICES_GPIOIDS_H_ */ diff --git a/fsfwconfig/devices/powerSwitcherList.cpp b/fsfwconfig/devices/powerSwitcherList.cpp index a7603185..7439c6de 100644 --- a/fsfwconfig/devices/powerSwitcherList.cpp +++ b/fsfwconfig/devices/powerSwitcherList.cpp @@ -1,9 +1,3 @@ -/** - * @file switcherList.cpp - * - * @date 28.11.2019 - */ - #include diff --git a/fsfwconfig/devices/powerSwitcherList.h b/fsfwconfig/devices/powerSwitcherList.h index 98f7af8d..0c0442a2 100644 --- a/fsfwconfig/devices/powerSwitcherList.h +++ b/fsfwconfig/devices/powerSwitcherList.h @@ -1,19 +1,14 @@ -/** - * @file switcherList.h - * - * @date 28.11.2019 - */ - #ifndef FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ #define FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ -namespace switches { +namespace pcduSwitches { /* Switches are uint8_t datatype and go from 0 to 255 */ enum switcherList { PCDU, GPS0, GPS1, - DUMMY = 129 + TCS_BOARD_8V_HEATER_IN, + DUMMY = 129, }; } diff --git a/fsfwconfig/objects/systemObjectList.h b/fsfwconfig/objects/systemObjectList.h index f44e74ac..559d0543 100644 --- a/fsfwconfig/objects/systemObjectList.h +++ b/fsfwconfig/objects/systemObjectList.h @@ -22,7 +22,6 @@ namespace objects { TM_FUNNEL = 0x52000002, /* Test Task */ - TEST_TASK = 0x42694269, DUMMY_INTERFACE = 0xCAFECAFE, DUMMY_HANDLER = 0x4400AFFE, @@ -33,13 +32,19 @@ namespace objects { CSP_COM_IF = 0x49000002, I2C_COM_IF = 0x49000003, + /* 0x47 ('G') for Gpio Interfaces */ + GPIO_IF = 0x470000001, + /* 0x44 ('D') for device handlers */ P60DOCK_HANDLER = 0x44000001, PDU1_HANDLER = 0x44000002, PDU2_HANDLER = 0x44000003, ACU_HANDLER = 0x44000004, TMP1075_HANDLER_1 = 0x44000005, - TMP1075_HANDLER_2 = 0x44000006 + TMP1075_HANDLER_2 = 0x44000006, + + /* 0x54 ('T') for thermal objects */ + HEATER_HANDLER = 0x54000001 }; } diff --git a/fsfwconfig/returnvalues/classIds.h b/fsfwconfig/returnvalues/classIds.h index 6d68d954..55bff25c 100644 --- a/fsfwconfig/returnvalues/classIds.h +++ b/fsfwconfig/returnvalues/classIds.h @@ -12,7 +12,8 @@ namespace CLASS_ID { enum { MISSION_CLASS_ID_START = FW_CLASS_ID_COUNT, MGM_LIS3MDL, - MGM_RM3100 + MGM_RM3100, + LINUX_LIBGPIO_IF }; } diff --git a/mission/devices/GomspaceDeviceHandler.h b/mission/devices/GomspaceDeviceHandler.h index d8ac4e25..c6f1866a 100644 --- a/mission/devices/GomspaceDeviceHandler.h +++ b/mission/devices/GomspaceDeviceHandler.h @@ -37,7 +37,8 @@ public: protected: void doStartUp() override; void doShutDown() override; - ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) + override; ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override; void fillCommandAndReplyMap() override; ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, diff --git a/mission/devices/HeaterHandler.cpp b/mission/devices/HeaterHandler.cpp new file mode 100644 index 00000000..c080d63b --- /dev/null +++ b/mission/devices/HeaterHandler.cpp @@ -0,0 +1,214 @@ +#include + +HeaterHandler::HeaterHandler(object_id_t setObjectId, +object_id_t gpioDriverId, CookieIF * gpioCookie, object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch) : +SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE), +gpioDriverId(gpioDriver), gpioCookie(gpioCookie), mainLineSwitcherObjectId(mainLineSwitcherObjectId), mainLineSwitch(mainLineSwitch), +healthHelper(this,setObjectId), modeHelper(this), parameterHelper(this), +actionHelper(this, nullptr), hkManager(this, nullptr), +childTransitionFailure(RETURN_OK), fdirInstance(fdirInstance), +hkSwitcher(this), defaultFDIRUsed(fdirInstance == nullptr), +switchOffWasReported(false), childTransitionDelay(5000), +transitionSourceMode(_MODE_POWER_DOWN), +transitionSourceSubMode(SUBMODE_NONE) { + commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, + MessageQueueMessage::MAX_MESSAGE_SIZE); + powerSwitcher = objectManager->get( + mainLineSwitcherObjectId); +} + +HeaterHandler::~HeaterHandler() { +} + +ReturnValue_t performOperation(uint8_t operationCode) { + + if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) { + readCommandQueue(); + handlePendingCommand(); + doStateMachine(); + + checkSwitchState(); + decrementDeviceReplyMap(); + fdirInstance->checkForFailures(); + hkSwitcher.performOperation(); + performOperationHook(); + return RETURN_OK; + } +} + +ReturnValue_t DeviceHandlerBase::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + + gpioInterface = objectManager->get(gpioDriverId); + if (gpioInterface == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "HeaterHandler::initialize: Invalid Gpio interface." + << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + result = gpioInterface->initializeInterface(gpioCookie); + if (result != RETURN_OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "HeaterHandler::initialize: Failed to initialize Gpio " + << "interface"<< std::endl; +#endif + return result; + } + + IPCStore = objectManager->get(objects::IPC_STORE); + if (IPCStore == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "HeaterHandler::initialize: IPC store not set up in " + "factory." << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + if(powerSwitcherId != objects::NO_OBJECT) { + powerSwitcher = objectManager->get(powerSwitcherId); + if (powerSwitcher == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "HeaterHandler::initialize: Power switcher " + << "object ID set but no valid object found." << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + + result = healthHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + + result = modeHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + result = actionHelper.initialize(commandQueue); + if (result != RETURN_OK) { + return result; + } + + fillCommandAndReplyMap(); + + return RETURN_OK; +} + +void DeviceHandlerBase::readCommandQueue() { + + if (dontCheckQueue()) { + return; + } + + CommandMessage command; + ReturnValue_t result = commandQueue->receiveMessage(&command); + if (result != RETURN_OK) { + return; + } + + result = modeHelper.handleModeCommand(&command); + if (result == RETURN_OK) { + return; + } + + result = actionHelper.handleActionMessage(&command); + if (result == RETURN_OK) { + return; + } +} + +ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { + ReturnValue_t result = acceptExternalDeviceCommands(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + heaterCommandMap::iterator iter = HeaterCommandMap.find(actionId); + if (iter == heaterCommandMap.end()) { + result = COMMAND_NOT_SUPPORTED; + } else { + if (commandedBy == commandQueue){ + heaterCommand(*(data), *(data + 1), NO_COMMANDER); + commandPending = true; + } + else { + heaterCommand(*(data), *(data + 1), commandedBy); + commandPending = true; + } + result = RETURN_OK; + } + return result; +} + +ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() { + if (mode != MODE_ON) { + return WRONG_MODE_FOR_COMMAND; + } + return RETURN_OK; +} + +void HeaterHandler::sendSwitchCommand(uint8_t switchNr, + ReturnValue_t onOff) const { + + ReturnValue_t result; + store_address_t address; + HeaterCommand_t command; + + switch(onOff) { + case PowerSwitchIF::SWITCH_ON: + command(SWITCH_ON, switchNr); + case PowerSwitchIF::SWITCH_OFF: + command(SWITCH_OFF, switchNr); + default: + sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request" + << std::endl; + } + + result = IPCStore->addData(&address, &command, sizeof(command)); + if (result == RETURN_OK) { + CommandMessage message; + ActionMessage::setCommand(&message, + HeaterHandler::SWITCH_HEATER, address); + /* Send heater command to own command queue */ + result = commandQueue->sendMessage(commandQueue, &message, 0); + if (result != RETURN_OK) { + debug << "HeaterHandler::sendSwitchCommand: Failed to send switch" + << "message" << std::endl; + } + } +} + +void HeaterHandler::handlePendingCommand(){ + ReturnValue_t result; + + if (!commandPending) { + return; + } + switch(heaterCommand.action) { + case SET_SWITCH_ON: + result = gpioInterface->pullHigh(heaterCommand.heaterSwitchNr); + if (result != RETURN_OK) { + triggerEvent() + } + if (heaterCommand.replyQueue != NO_COMMANDER) { + actionHelper.finish(heaterCommand.replyQueue, heaterCommand.action, + result); + } + commandPending = false; + break; + case SET_SWITCH_OFF: + result = gpioInterface->pullLow(heaterCommand.heaterSwitchNr); + if (heaterCommand.replyQueue != NO_COMMANDER) { + actionHelper.finish(heaterCommand.replyQueue, heaterCommand.action, + result); + } + commandPending = false; + break; + } +} + diff --git a/mission/devices/HeaterHandler.h b/mission/devices/HeaterHandler.h new file mode 100644 index 00000000..ab9aebdc --- /dev/null +++ b/mission/devices/HeaterHandler.h @@ -0,0 +1,132 @@ +#ifndef MISSION_DEVICES_HEATERHANDLER_H_ +#define MISSION_DEVICES_HEATERHANDLER_H_ + +#include +#include +#include +#include +#include +#include + +/** + * @brief This class intends the control of heaters. + * + * @author J. Meier + */ +class HeaterHandler: public ExecutableObjectIF, + public PowerSwitchIF, + public SystemObject, + public HasActionsIF, + public HasModesIF, + public HasReturnvaluesIF { +public: + + /** Command not in heaterCommandMap */ + static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); + /** Heater mode is MODE_OFF */ + static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5); + + + /** Device command IDs */ + static const DeviceCommandId_t SWITCH_HEATER; + + virtual ReturnValue_t performOperation(uint8_t operationCode = 0); + + void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override; + virtual void sendFuseOnCommand(uint8_t fuseNr) override; + /** + * @brief This function will be called from the Heater object to check + * the current switch state. + */ + virtual ReturnValue_t getSwitchState( uint8_t switchNr ) override; + virtual ReturnValue_t getFuseState( uint8_t fuseNr ) override; + virtual uint32_t getSwitchDelayMs(void) override; + ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, size_t size) + override; + +private: + + static const MessageQueueId_t NO_COMMANDER = 0; + + ReturnValue_t buildCommandFromCommand( + DeviceCommandId_t deviceCommand, const uint8_t *commandData, + size_t commandDataLen); + ReturnValue_t acceptExternalDeviceCommands(); + + /** + * @brief This function runs commands waiting for execution. + */ + void handlePendingCommand(); + + /** + * @brief Struct holding information about a heater command to execute. + * + * @param action The action to perform. + * @param heaterSwitchNr The number of a switch which correlates with the + * GPIO to drive. + * @param replyQueue The queue of the commander to which status replies + * will be sent. + */ + typedef struct HeaterCommand { + HeaterCommand(uint8_t action_, uint8_t heaterSwitchNr, + MessageQueueId_t replyQueue_) { + action = action_; + heaterSwitchNr = heaterSwitchNr_; + replyQueue = replyQueue_; + } + uint8_t action; + uint8_t heaterSwitchNr; + MessageQueueId_t replyQueue; + } HeaterCommand_t; + + + enum SwitchAction { + SET_SWITCH_ON, + SET_SWITCH_OFF + }; + + /** This HeaterCommand instance holds the next heater command to execute */ + HeaterCommand_t heaterCommand; + + /** + * This variable is set when the command stored in heaterCommand shall be + * executed. + */ + bool commandPending; + + /** Size of command queue */ + size_t cmdQueueSize = 20; + + /** + * Current mode of the HeaterHandler. Should only be changed with setMode(). + */ + Mode_t mode; + /** + * Current submode of the HeaterHandler. Should only be change with + * setMode(). + */ + Submode_t submode; + + /** + * The object ID of the GPIO driver which enables and disables the + * heaters. + */ + object_id_t gpioDriverId; + + GpioIF* gpioInterface; + + /** Queue to receive messages from other objects. */ + MessageQueueIF* commandQueue = nullptr; + + /** + * Power switcher object which controls the 8V main line of the heater + * logic on the TCS board. + */ + PowerSwitchIF *powerSwitcher; + + HeaterHandler(); + virtual ~HeaterHandler(); +}; + +#endif /* MISSION_DEVICES_HEATERHANDLER_H_ */ diff --git a/mission/devices/PCDUHandler.cpp b/mission/devices/PCDUHandler.cpp new file mode 100644 index 00000000..63dd931c --- /dev/null +++ b/mission/devices/PCDUHandler.cpp @@ -0,0 +1,18 @@ +/* + * PCDUHandler.cpp + * + * Created on: 21.01.2021 + * Author: jakob + */ + +#include "PCDUHandler.h" + +PCDUHandler::PCDUHandler() { + // TODO Auto-generated constructor stub + +} + +PCDUHandler::~PCDUHandler() { + // TODO Auto-generated destructor stub +} + diff --git a/mission/devices/PCDUHandler.h b/mission/devices/PCDUHandler.h new file mode 100644 index 00000000..29739e9b --- /dev/null +++ b/mission/devices/PCDUHandler.h @@ -0,0 +1,20 @@ +/* + * PCDUHandler.h + * + * Created on: 21.01.2021 + * Author: jakob + */ + +#ifndef MISSION_DEVICES_PCDUHANDLER_H_ +#define MISSION_DEVICES_PCDUHANDLER_H_ + +/** + * @brief + */ +class PCDUHandler: public PowerSwitchIF { +public: + PCDUHandler(); + virtual ~PCDUHandler(); +}; + +#endif /* MISSION_DEVICES_PCDUHANDLER_H_ */ diff --git a/mission/devices/PDU2Handler.cpp b/mission/devices/PDU2Handler.cpp new file mode 100644 index 00000000..9d5e3d50 --- /dev/null +++ b/mission/devices/PDU2Handler.cpp @@ -0,0 +1,18 @@ +/* + * PDU2Handler.cpp + * + * Created on: 23.01.2021 + * Author: jakob + */ + +#include "PDU2Handler.h" + +PDU2Handler::PDU2Handler() { + // TODO Auto-generated constructor stub + +} + +PDU2Handler::~PDU2Handler() { + // TODO Auto-generated destructor stub +} + diff --git a/mission/devices/PDU2Handler.h b/mission/devices/PDU2Handler.h new file mode 100644 index 00000000..4d18000c --- /dev/null +++ b/mission/devices/PDU2Handler.h @@ -0,0 +1,26 @@ +#ifndef MISSION_DEVICES_PDU2HANDLER_H_ +#define MISSION_DEVICES_PDU2HANDLER_H_ + +#include "GomspaceDeviceHandler.h" + +/** + * @brief This is the device handler for the PDU2. + * + * @details The PDU2 controls the + * power supply of the following devices: + * Xiphos Q7S, 8V, channel 0 + * Reaction wheels 5V, channel 2 + * TCS Board heater input, 8V, channel 3 + * SUS, 3,3V, channel 4 + * Deployment mechanism, 8V, channel 5 + * P/L PCDU, 15,9V, channel 1 and channel 6 + * ACS Board (Gyro, MGMs, GPS), 3,3V channel 7 + * Payload Camera, 8V, channel 8 + */ +class PDU2Handler: public GomspaceDeviceHandler { +public: + PDU2Handler(); + virtual ~PDU2Handler(); +}; + +#endif /* MISSION_DEVICES_PDU2HANDLER_H_ */ diff --git a/mission/devices/devicedefinitions/GomSpacePackets.h b/mission/devices/devicedefinitions/GomSpacePackets.h index 24bb67e7..b086ef5b 100644 --- a/mission/devices/devicedefinitions/GomSpacePackets.h +++ b/mission/devices/devicedefinitions/GomSpacePackets.h @@ -178,7 +178,8 @@ private: * device*/ SerializeElement action = 0x00; // get param SerializeElement tableId; - SerializeElement addresslength; // size of address + /* Size of address. Set to 0 to get full table */ + SerializeElement addresslength; SerializeElement checksum; SerializeElement seq; SerializeElement total;