diff --git a/CMakeLists.txt b/CMakeLists.txt index a1410bdb..05ca6671 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ set(FSFW_PATH fsfw) set(MISSION_PATH mission) set(CSPLIB_PATH libcsp) -set(WARNING_SHADOW_LOCAL FALSE) +set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF) # Analyse different OS and architecture/target options, determine BSP_PATH, # display information about compiler etc. @@ -165,11 +165,13 @@ endif() add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}" - COMMAND echo "Target OSAL: ${OS_FSFW}" - COMMAND echo "Target Build Type: ${CMAKE_BUILD_TYPE}" - COMMAND echo "${TARGET_STRING}" + #COMMAND echo "Build directory: ${CMAKE_BINARY_DIR}" + #COMMAND echo "Target OSAL: ${OS_FSFW}" + #COMMAND echo "Target Build Type: ${CMAKE_BUILD_TYPE}" + #COMMAND echo "${TARGET_STRING}" COMMAND ${CMAKE_SIZE} ${TARGET_NAME}${FILE_SUFFIX} + COMMENT "Build directory: ${CMAKE_BINARY_DIR}\nTarget OSAL: ${OS_FSFW}\n" + "Target Build Type: ${CMAKE_BUILD_TYPE}\n${TARGET_STRING}" ) include (${CMAKE_SCRIPT_PATH}/BuildType.cmake) diff --git a/bsp_hosted/fsfwconfig/FSFWConfig.h b/bsp_hosted/fsfwconfig/FSFWConfig.h index 261e3d6d..e3def8fe 100644 --- a/bsp_hosted/fsfwconfig/FSFWConfig.h +++ b/bsp_hosted/fsfwconfig/FSFWConfig.h @@ -7,19 +7,18 @@ //! Used to determine whether C++ ostreams are used which can increase //! the binary size significantly. If this is disabled, //! the C stdio functions can be used alternatively -#define FSFW_CPP_OSTREAM_ENABLED 1 +#define FSFW_CPP_OSTREAM_ENABLED 1 -//! More FSFW related printouts. -//! Be careful, this also turns off most diagnostic prinouts! -#define FSFW_ENHANCED_PRINTOUT 0 +//! More FSFW related printouts depending on level. Useful for development. +#define FSFW_VERBOSE_LEVEL 1 //! Can be used to completely disable printouts, even the C stdio ones. -#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_ENHANCED_PRINTOUT == 0 - #define FSFW_DISABLE_PRINTOUT 0 +#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0 + #define FSFW_DISABLE_PRINTOUT 0 #endif -//! Can be used to enable additional debugging printouts for developing the FSFW -#define FSFW_PRINT_VERBOSITY_LEVEL 0 +//! Can be used to disable the ANSI color sequences for C stdio. +#define FSFW_COLORED_OUTPUT 1 //! Can be used to disable the ANSI color sequences for C stdio. #define FSFW_COLORED_OUTPUT 1 diff --git a/bsp_q7s/CMakeLists.txt b/bsp_q7s/CMakeLists.txt index 004a2fcd..806feca9 100644 --- a/bsp_q7s/CMakeLists.txt +++ b/bsp_q7s/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(${TARGET_NAME} PUBLIC add_subdirectory(boardconfig) add_subdirectory(comIF) +add_subdirectory(gpio) diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/ObjectFactory.cpp index e6ea8fa1..45529c33 100644 --- a/bsp_q7s/ObjectFactory.cpp +++ b/bsp_q7s/ObjectFactory.cpp @@ -13,7 +13,11 @@ #include #include -#include +#include +#include +#include +#include +#include #include #include #include @@ -58,28 +62,35 @@ void ObjectFactory::produce(){ addresses::PDU2); CspCookie* acuCspCookie = new CspCookie(ACU::MAX_REPLY_LENGTH, addresses::ACU); +#if TE0720 == 1 I2cCookie* i2cCookieTmp1075tcs1 = new I2cCookie(addresses::TMP1075_TCS_1, TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0")); I2cCookie* i2cCookieTmp1075tcs2 = new I2cCookie(addresses::TMP1075_TCS_2, TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-0")); - +#else + I2cCookie* i2cCookieTmp1075tcs1 = new I2cCookie(addresses::TMP1075_TCS_1, + TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-1")); + I2cCookie* i2cCookieTmp1075tcs2 = new I2cCookie(addresses::TMP1075_TCS_2, + TMP1075::MAX_REPLY_LENGTH, std::string("/dev/i2c-1")); +#endif /* Communication interfaces */ new CspComIF(objects::CSP_COM_IF); new I2cComIF(objects::I2C_COM_IF); /* Device Handler */ - new GomspaceDeviceHandler(objects::P60DOCK_HANDLER, objects::CSP_COM_IF, + new P60DockHandler(objects::P60DOCK_HANDLER, objects::CSP_COM_IF, p60DockCspCookie, P60Dock::MAX_CONFIGTABLE_ADDRESS, - P60Dock::MAX_HKTABLE_ADDRESS); - new GomspaceDeviceHandler(objects::PDU1_HANDLER, objects::CSP_COM_IF, + P60Dock::MAX_HKTABLE_ADDRESS, P60Dock::HK_TABLE_SIZE); + new PDU1Handler(objects::PDU1_HANDLER, objects::CSP_COM_IF, pdu1CspCookie, PDU::MAX_CONFIGTABLE_ADDRESS, - PDU::MAX_HKTABLE_ADDRESS); - new GomspaceDeviceHandler(objects::PDU2_HANDLER, objects::CSP_COM_IF, + PDU::MAX_HKTABLE_ADDRESS, PDU::HK_TABLE_SIZE); + new PDU2Handler(objects::PDU2_HANDLER, objects::CSP_COM_IF, pdu2CspCookie, PDU::MAX_CONFIGTABLE_ADDRESS, - PDU::MAX_HKTABLE_ADDRESS); - new GomspaceDeviceHandler(objects::ACU_HANDLER, objects::CSP_COM_IF, + PDU::MAX_HKTABLE_ADDRESS, PDU::HK_TABLE_SIZE); + new ACUHandler(objects::ACU_HANDLER, objects::CSP_COM_IF, acuCspCookie, ACU::MAX_CONFIGTABLE_ADDRESS, - ACU::MAX_HKTABLE_ADDRESS); + ACU::MAX_HKTABLE_ADDRESS, ACU::HK_TABLE_SIZE); + new PCDUHandler(objects::PCDU_HANDLER); /* Temperature sensors */ Tmp1075Handler* tmp1075Handler_1 = new Tmp1075Handler( objects::TMP1075_HANDLER_1, objects::I2C_COM_IF, @@ -95,13 +106,15 @@ void ObjectFactory::produce(){ #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); + std::string("Heater0"), Gpio::OUT); + gpioCookie.add(gpioIds::HEATER_0, gpioConfigForDummyHeater); #else + GpioConfig_t gpioConfigHeater0(std::string("gpiochip5"), 6, + std::string("Heater0"), Gpio::OUT); + gpioCookie.add(gpioIds::HEATER_0, gpioConfigHeater0); #endif LinuxLibgpioIF linuxLibgpioIF = new LinuxLibgpioIF(objects::GPIO_IF); - new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, ); - + new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, gpioCookie); new TmTcUnixUdpBridge(objects::UDP_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR, diff --git a/bsp_q7s/comIF/GpioComIF.cpp b/bsp_q7s/comIF/GpioComIF.cpp deleted file mode 100644 index e8d4d8e1..00000000 --- a/bsp_q7s/comIF/GpioComIF.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include -#include -#include - - -GpioComIF::GpioComIF(object_id_t objectId): SystemObject(objectId){ -} - -GpioComIF::~GpioComIF() {} - -ReturnValue_t GpioComIF::initializeInterface(CookieIF * cookie) { - - ReturnValue_t result; - GpioMap mapToAdd; - - if(cookie == nullptr) { - return NULLPOINTER; - } - GpioCookie* GpioCookie = dynamic_cast(cookie); - if(GpioCookie == nullptr) { - sif::error << "GpioComIF: 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*/ - 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; -} - -ReturnValue_t GpioComIF::sendMessage(CookieIF *cookie, - const uint8_t *sendData, size_t sendLen) { - - ReturnValue_t result; - int fd; - std::string deviceFile; - - if(sendData == nullptr) { - sif::error << "GpioComIF::sendMessage: Send Data is nullptr" - << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(sendLen == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - I2cCookie* i2cCookie = dynamic_cast(cookie); - if(i2cCookie == nullptr) { - sif::error << "GpioComIF::sendMessasge: Invalid I2C Cookie!" - << std::endl; - return NULLPOINTER; - } - - address_t i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); - if (i2cDeviceMapIter == i2cDeviceMap.end()) { - sif::error << "GpioComIF::sendMessage: i2cAddress of Cookie not " - << "registered in i2cDeviceMap" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - deviceFile = i2cCookie->getDeviceFile(); - result = openDevice(deviceFile, i2cAddress, &fd); - if (result != HasReturnvaluesIF::RETURN_OK){ - return result; - } - - if (write(fd, sendData, sendLen) != (int)sendLen) { - sif::error << "GpioComIF::sendMessage: Failed to send data to I2C " - "device with error code " << errno << ". Error description: " - << strerror(errno) << std::endl; - close(fd); - return HasReturnvaluesIF::RETURN_FAILED; - } - close(fd); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t GpioComIF::getSendSuccess(CookieIF *cookie) { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t GpioComIF::requestReceiveMessage(CookieIF *cookie, - size_t requestLen) { - - ReturnValue_t result; - int fd; - std::string deviceFile; - - if (requestLen == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - I2cCookie* i2cCookie = dynamic_cast(cookie); - if(i2cCookie == nullptr) { - sif::error << "GpioComIF::requestReceiveMessage: Invalid I2C Cookie!" - << std::endl; - i2cDeviceMapIter->second.replyLen = 0; - return NULLPOINTER; - } - - address_t i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); - if (i2cDeviceMapIter == i2cDeviceMap.end()) { - sif::error << "GpioComIF::requestReceiveMessage: i2cAddress of Cookie not " - << "registered in i2cDeviceMap" << std::endl; - i2cDeviceMapIter->second.replyLen = 0; - return HasReturnvaluesIF::RETURN_FAILED; - } - - deviceFile = i2cCookie->getDeviceFile(); - result = openDevice(deviceFile, i2cAddress, &fd); - if (result != HasReturnvaluesIF::RETURN_OK){ - i2cDeviceMapIter->second.replyLen = 0; - return result; - } - - uint8_t* replyBuffer = i2cDeviceMapIter->second.replyBuffer.data(); - - if (read(fd, replyBuffer, requestLen) != (int)requestLen) { - sif::error << "GpioComIF::requestReceiveMessage: Reading from I2C " - << "device failed with error code " << errno <<". Description" - << " of error: " << strerror(errno) << std::endl; - close(fd); - i2cDeviceMapIter->second.replyLen = 0; - return HasReturnvaluesIF::RETURN_FAILED; - } - - i2cDeviceMapIter->second.replyLen = requestLen; - - close(fd); - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t GpioComIF::readReceivedMessage(CookieIF *cookie, - uint8_t **buffer, size_t* size) { - I2cCookie* i2cCookie = dynamic_cast(cookie); - if(i2cCookie == nullptr) { - sif::error << "GpioComIF::readReceivedMessage: Invalid I2C Cookie!" - << std::endl; - return NULLPOINTER; - } - - address_t i2cAddress = i2cCookie->getAddress(); - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); - if (i2cDeviceMapIter == i2cDeviceMap.end()) { - sif::error << "GpioComIF::readReceivedMessage: i2cAddress of Cookie not " - << "found in i2cDeviceMap" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - *buffer = i2cDeviceMapIter->second.replyBuffer.data(); - *size = i2cDeviceMapIter->second.replyLen; - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t GpioComIF::openDevice(std::string deviceFile, - address_t i2cAddress, int* fileDescriptor) { - *fileDescriptor = open(deviceFile.c_str(), O_RDWR); - if (*fileDescriptor < 0) { - sif::error << "GpioComIF: Opening i2c device failed with error code " - << errno << ". Error description: " << strerror(errno) - << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - if (ioctl(*fileDescriptor, I2C_SLAVE, i2cAddress) < 0) { - sif::error << "GpioComIF: Specifying target device failed with error " - << "code " << errno << ". Error description " - << strerror(errno) << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t GpioComIF::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 << "GpioComIF::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; -} - -ReturnValue_t GpioComIF::initializeAndConfigure(GpioMap mapToAdd){ - - int exportfd; - int directionfd; - std::string gpioStr; - GpioMapIter mapToAddItr; - - mapToAddItr = mapToAdd.begin(); - /* Perform initialization for all GPIOs in map */ - for(; mapToAddItr != mapToAdd.end(); mapToAddItr++){ - /* The GPIO has to be exported to be able to see it in sysfs */ - exportfd = open("/sys/class/gpio/export", O_WRONLY); - if (exportfd < 0) - { - sif::error << "GpioComIF::initializeAndConfigure: Cannot open GPIO " - << mapToAddItr.first() << " to export it" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - gpioStr = std::to_string(mapToAddItr.first()); - write(exportfd, gpioStr.c_str(), gpioStr.length() + 1); - close(exportfd); - - /* Set direction of the GPIO */ - std::string directionPath = "/sys/class/gpio/" + gpioStr + - "/direction"; - directionfd = open(directionPath.c_str(), O_RDWR); - if (directionfd < 0) - { - sif::error << "Cannot open " << directionPath.c_str() << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - if (mapToAdd.second() == Gpio::IN) { - write(directionfd, "in", 3); - } - else if (mapToAdd.second() == Gpio::OUT) { - write(directionfd, "out", 4); - } - else { - sif::error << "GpioComIF::initializeAndConfigure: Invalid direction" - << " specified" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - close(directionfd); - - /* Add GPIO to GpioMap of GpioComIF */ - std::pair insertionResult = gpioMap.insert(mapToAddItr); - 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; -} diff --git a/bsp_q7s/comIF/GpioComIF.h b/bsp_q7s/comIF/GpioComIF.h deleted file mode 100644 index f90a82d0..00000000 --- a/bsp_q7s/comIF/GpioComIF.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef BSP_Q7S_COMIF_I2s COMIF_H_ -#define BSP_Q7S_COMIF_I2COMIF_H_ - -#include -#include -#include - -/** - * @brief This is the communication interface to drive GPIOs by using the - * the linux sysfs. - * - * @author J. Meier - */ -class GpioComIF: public DeviceCommunicationIF, public SystemObject { -public: - GpioComIF(object_id_t objectId); - - virtual ~GpioComIF(); - - ReturnValue_t initializeInterface(CookieIF * cookie) override; - ReturnValue_t sendMessage(CookieIF *cookie,const uint8_t *sendData, - size_t sendLen) override; - ReturnValue_t getSendSuccess(CookieIF *cookie) override; - ReturnValue_t requestReceiveMessage(CookieIF *cookie, - size_t requestLen) override; - ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer, - size_t *size) override; - -private: - - /* All GPIOs will be stored in this map after successful initialization */ - GpioMap gpioMap; - GpioMapIter gpioMapIter; - - /** - * @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); - - /** - * @brief This function initializes all GPIOs specified in the mapToAdd. - * - * @param Map with the GPIOs to initialize. - * - * @return RETURN_OK if successful, otherwise RETURN_FAILED - */ - ReturnValue_t GpioComIF::initializeAndConfigure(GpioMap mapToAdd); - -}; - -#endif /* BSP_Q7S_COMIF_I2COMIF_H_ */ diff --git a/bsp_q7s/gpio/CMakeLists.txt b/bsp_q7s/gpio/CMakeLists.txt new file mode 100644 index 00000000..e35dd300 --- /dev/null +++ b/bsp_q7s/gpio/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(${TARGET_NAME} PUBLIC + cookies/GpioCookie.cpp + LinuxLibgpioIF.cpp +) + + diff --git a/bsp_q7s/gpio/GpioIF.cpp b/bsp_q7s/gpio/GpioIF.cpp deleted file mode 100644 index 9f20aa55..00000000 --- a/bsp_q7s/gpio/GpioIF.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 index 3d3733c3..313351fb 100644 --- a/bsp_q7s/gpio/GpioIF.h +++ b/bsp_q7s/gpio/GpioIF.h @@ -13,7 +13,7 @@ typedef uint16_t gpioId_t; */ class GpioIF : public HasReturnvaluesIF{ public: - GpioIF(); + virtual ~GpioIF(); /** diff --git a/bsp_q7s/gpio/LinuxLibgpioIF.h b/bsp_q7s/gpio/LinuxLibgpioIF.h index 37ef4c61..27a68858 100644 --- a/bsp_q7s/gpio/LinuxLibgpioIF.h +++ b/bsp_q7s/gpio/LinuxLibgpioIF.h @@ -3,6 +3,7 @@ #include #include +#include /** * @brief This class implements the GpioIF for a linux based system. The diff --git a/bsp_q7s/gpio/cookies/GpioCookie.cpp b/bsp_q7s/gpio/cookies/GpioCookie.cpp index 60120c58..d71bc682 100644 --- a/bsp_q7s/gpio/cookies/GpioCookie.cpp +++ b/bsp_q7s/gpio/cookies/GpioCookie.cpp @@ -10,7 +10,6 @@ void GpioCookie::addGpio(GpioMap newEntry){ if (status.second == false) { sif::error << "GpioCookie::addGpio: Failed to add GPIO " << newEntry.first << "to GPIO map" << std::endl; - return HasReturnvaluesIF::RETURN_OK; } } else { diff --git a/bsp_q7s/gpio/cookies/GpioCookie.h b/bsp_q7s/gpio/cookies/GpioCookie.h index 8d3c97da..1a99a676 100644 --- a/bsp_q7s/gpio/cookies/GpioCookie.h +++ b/bsp_q7s/gpio/cookies/GpioCookie.h @@ -1,8 +1,9 @@ -#ifndef SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ -#define SAM9G20_COMIF_COOKIES_I2C_COOKIE_H_ +#ifndef SAM9G20_COMIF_COOKIES_GPIO_COOKIE_H_ +#define SAM9G20_COMIF_COOKIES_GPIO_COOKIE_H_ #include #include +#include #include namespace Gpio { diff --git a/bsp_rpi/CMakeLists.txt b/bsp_rpi/CMakeLists.txt index 7885ca28..281994bf 100644 --- a/bsp_rpi/CMakeLists.txt +++ b/bsp_rpi/CMakeLists.txt @@ -7,6 +7,11 @@ target_sources(${TARGET_NAME} PUBLIC add_subdirectory(boardconfig) add_subdirectory(boardtest) +# wiringPi is deprecated unfortunately.. +#target_link_libraries(${TARGET_NAME} PRIVATE +# wiringPi +#) + diff --git a/bsp_rpi/InitMission.cpp b/bsp_rpi/InitMission.cpp index 76918716..197abcc6 100644 --- a/bsp_rpi/InitMission.cpp +++ b/bsp_rpi/InitMission.cpp @@ -14,18 +14,10 @@ #include -// This is configured for linux without \cr -#ifdef LINUX ServiceInterfaceStream sif::debug("DEBUG"); ServiceInterfaceStream sif::info("INFO"); ServiceInterfaceStream sif::warning("WARNING"); -ServiceInterfaceStream sif::error("ERROR", false, false, true); -#else -ServiceInterfaceStream sif::debug("DEBUG", true); -ServiceInterfaceStream sif::info("INFO", true); -ServiceInterfaceStream sif::warning("WARNING", true); -ServiceInterfaceStream sif::error("ERROR", true, false, true); -#endif +ServiceInterfaceStream sif::error("ERROR"); ObjectManagerIF *objectManager = nullptr; @@ -47,11 +39,11 @@ void InitMission::initTasks(){ 0.100, nullptr); ReturnValue_t result = TmTcDistributor->addComponent( objects::CCSDS_PACKET_DISTRIBUTOR); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } result = TmTcDistributor->addComponent(objects::PUS_PACKET_DISTRIBUTOR); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } result = TmTcDistributor->addComponent(objects::TM_FUNNEL); @@ -97,11 +89,11 @@ void InitMission::initTasks(){ PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.200, nullptr); result = PusHighPrio->addComponent(objects::PUS_SERVICE_2_DEVICE_ACCESS); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } result = PusHighPrio->addComponent(objects::PUS_SERVICE_9_TIME_MGMT); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } @@ -110,11 +102,11 @@ void InitMission::initTasks(){ PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, nullptr); result = PusMedPrio->addComponent(objects::PUS_SERVICE_8_FUNCTION_MGMT); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } result = PusMedPrio->addComponent(objects::PUS_SERVICE_200_MODE_MGMT); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } @@ -122,7 +114,7 @@ void InitMission::initTasks(){ createPeriodicTask("PUSB", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.6, nullptr); result = PusLowPrio->addComponent(objects::PUS_SERVICE_17_TEST); - if(result!=HasReturnvaluesIF::RETURN_OK){ + if(result != HasReturnvaluesIF::RETURN_OK){ sif::error << "Object add component failed" << std::endl; } @@ -139,6 +131,14 @@ void InitMission::initTasks(){ #endif + PeriodicTaskIF* SpiTestTask = TaskFactory::instance()-> + createPeriodicTask("SPI_TEST", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, + 2.0, nullptr); + result = SpiTestTask->addComponent(objects::SPI_TEST); + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "Object add SPI test failed" << std::endl; + } + //Main thread sleep sif::info << "Starting tasks.." << std::endl; TmTcDistributor->startTask(); @@ -151,6 +151,8 @@ void InitMission::initTasks(){ PusMedPrio->startTask(); PusLowPrio->startTask(); + SpiTestTask->startTask(); + #if OBSW_ADD_TEST_CODE == 1 TestTimeslotTask->startTask(); #endif diff --git a/bsp_rpi/ObjectFactory.cpp b/bsp_rpi/ObjectFactory.cpp index 4300fbeb..c90db492 100644 --- a/bsp_rpi/ObjectFactory.cpp +++ b/bsp_rpi/ObjectFactory.cpp @@ -1,5 +1,6 @@ -#include #include "ObjectFactory.h" +#include +#include #include #include @@ -42,4 +43,6 @@ void ObjectFactory::produce(){ objects::CCSDS_PACKET_DISTRIBUTOR, objects::TM_STORE, objects::TC_STORE); new TcUnixUdpPollingTask(objects::UDP_POLLING_TASK, objects::UDP_BRIDGE); + + new SpiTest(objects::SPI_TEST); } diff --git a/bsp_rpi/boardtest/CMakeLists.txt b/bsp_rpi/boardtest/CMakeLists.txt index 768fc52f..1e373efb 100644 --- a/bsp_rpi/boardtest/CMakeLists.txt +++ b/bsp_rpi/boardtest/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(${TARGET_NAME} PRIVATE SpiTest.cpp + RPiGPIO.cpp ) diff --git a/bsp_rpi/boardtest/RPiGPIO.cpp b/bsp_rpi/boardtest/RPiGPIO.cpp new file mode 100644 index 00000000..7ffb024c --- /dev/null +++ b/bsp_rpi/boardtest/RPiGPIO.cpp @@ -0,0 +1,123 @@ +#include "RPiGPIO.h" + +#include +#include +#include +#include +#include + + +int RPiGPIO::enablePin(int pin) { + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/export", O_WRONLY); + if (fd == -1) { + sif::error << "Failed to open export of pin " << pin << " for writing!" << std::endl; + return -1; + } + + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return 0; +} + +int RPiGPIO::disablePin(int pin) { + char buffer[BUFFER_MAX]; + ssize_t bytes_written; + int fd; + + fd = open("/sys/class/gpio/unexport", O_WRONLY); + if (fd == -1) { + sif::error << "Failed to open unexport of pin " << pin << " for writing!" << std::endl; + return -1; + } + + bytes_written = snprintf(buffer, BUFFER_MAX, "%d", pin); + write(fd, buffer, bytes_written); + close(fd); + return(0); +} + +int RPiGPIO::pinDirection(int pin, Directions dir) { + + char path[DIRECTION_MAX]; + + snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin); + int fd = open(path, O_WRONLY); + if (fd == -1) { + sif::error << "Failed to open gpio " << pin << " direction for writing!" << std::endl; + return -1; + } + + int result = 0; + if(dir == Directions::IN) { + result = write(fd, "in", IN_WRITE_SIZE); + } + else { + result = write(fd, "out", OUT_WRITE_SIZE); + } + + if (result != 0) { + sif::error << "Failed to set direction!" << std::endl; + return -2; + } + + close(fd); + return 0; +} + +int RPiGPIO::readPin(int pin) { + char path[VALUE_MAX]; + char value_str[3]; + + snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); + int fd = open(path, O_RDONLY); + if (fd == -1) { + sif::error << "RPiGPIO::readPin: Failed to open GPIO pin " << pin << "!" << std::endl; + return -1; + } + + if (read(fd, value_str, 3) == -1) { + sif::error << "Failed to read value!" << std::endl; + return -1; + } + + close(fd); + char* endPtr = nullptr; + + return strtol(value_str, &endPtr, 10); +} + +int RPiGPIO::writePin(int pin, States state) { + + char path[VALUE_MAX]; + int fd; + + snprintf(path, VALUE_MAX, "/sys/class/gpio/gpio%d/value", pin); + fd = open(path, O_WRONLY); + if (fd == -1) { + sif::error << "RPiGPIO::writePin: Failed to open GPIO pin " << pin << "!" << std::endl; + return -1; + } + + int result = 0; + if(state == States::LOW) { + result = write(fd, "0", 1); + } + else { + result = write(fd, "1", 1); + } + + + if (result != 0) { + sif::error << "Failed to write pin " << pin << " value to " << static_cast(state) + << "!" << std::endl; + return -1; + } + + close(fd); + return 0; +} diff --git a/bsp_rpi/boardtest/RPiGPIO.h b/bsp_rpi/boardtest/RPiGPIO.h new file mode 100644 index 00000000..400a37d8 --- /dev/null +++ b/bsp_rpi/boardtest/RPiGPIO.h @@ -0,0 +1,41 @@ +#ifndef BSP_RPI_BOARDTEST_RPIGPIO_H_ +#define BSP_RPI_BOARDTEST_RPIGPIO_H_ + +#include + +/** + * @brief Really simple C++ GPIO wrapper for the Raspberry Pi, using the sysfs interface. + * Use BCM pins notation (https://pinout.xyz/#) + * + */ +class RPiGPIO { +public: + enum Directions { + IN = 0, + OUT = 1 + }; + + enum States { + LOW = 0, + HIGH = 1 + }; + + static int enablePin(int pin); + static int disablePin(int pin); + static int pinDirection(int pin, Directions dir); + static int readPin(int pin); + static int writePin(int pin, States state); + +private: + + + static constexpr uint8_t BUFFER_MAX = 3; + static constexpr uint8_t DIRECTION_MAX = 35; + static constexpr uint8_t VALUE_MAX = 30; + + static constexpr uint8_t IN_WRITE_SIZE = 3; + static constexpr uint8_t OUT_WRITE_SIZE = 4; +}; + + +#endif /* BSP_RPI_BOARDTEST_RPIGPIO_H_ */ diff --git a/bsp_rpi/boardtest/SpiTest.cpp b/bsp_rpi/boardtest/SpiTest.cpp index 91939714..a78d0171 100644 --- a/bsp_rpi/boardtest/SpiTest.cpp +++ b/bsp_rpi/boardtest/SpiTest.cpp @@ -1,13 +1,31 @@ #include "SpiTest.h" -#include +#include #include #include -#include + + SpiTest::SpiTest(object_id_t objectId): SystemObject(objectId) { - wiringPiSetupGpio(); + sif::info << "Setting up Raspberry Pi WiringPi library." << std::endl; +// wiringPiSetupGpio(); + +// pinMode(SS_MGM_0_LIS3, OUTPUT); +// pinMode(SS_MGM_1_RM, OUTPUT); +// pinMode(SS_GYRO_0_ADIS, OUTPUT); +// pinMode(SS_GYRO_1_L3G, OUTPUT); +// pinMode(SS_GYRO_2_L3G, OUTPUT); +// pinMode(SS_MGM_2_LIS3, OUTPUT); +// pinMode(SS_MGM_3_RM, OUTPUT); +// +// digitalWrite(SS_MGM_0_LIS3, HIGH); +// digitalWrite(SS_MGM_1_RM, HIGH); +// digitalWrite(SS_GYRO_0_ADIS, HIGH); +// digitalWrite(SS_GYRO_1_L3G, HIGH); +// digitalWrite(SS_GYRO_2_L3G, HIGH); +// digitalWrite(SS_MGM_2_LIS3, HIGH); +// digitalWrite(SS_MGM_3_RM, HIGH); int spiFd = open(spiDeviceName.c_str(), O_RDWR); if (spiFd < 0){ @@ -40,4 +58,4 @@ ReturnValue_t SpiTest::initialize() { //transferHandle.speed_hz = 976000; //transferHandle.len = 2; return HasReturnvaluesIF::RETURN_OK; -} \ No newline at end of file +} diff --git a/bsp_rpi/boardtest/SpiTest.h b/bsp_rpi/boardtest/SpiTest.h index 9bdb8f25..b4f37fe2 100644 --- a/bsp_rpi/boardtest/SpiTest.h +++ b/bsp_rpi/boardtest/SpiTest.h @@ -6,13 +6,27 @@ #include #include -class SpiTest: public ExecutableObjectIF, SystemObject { +class SpiTest: + public SystemObject, + public ExecutableObjectIF { public: SpiTest(object_id_t objectId); ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t initialize() override; private: + // These chip selects (BCM number) will be pulled high if not used + // ACS board specific. + enum SpiChipSelects { + SS_MGM_0_LIS3 = 0, //!< MGM 0, LIS3MDLTR, U6, A side + SS_MGM_1_RM = 1, //!< MGM 1, RM3100, U7, A side + SS_GYRO_0_ADIS = 2, //!< Gyro 0, ADIS16485, U3, A side + SS_GYRO_1_L3G = 3, //!< Gyro 1, L3GD20H, U4, A side + SS_GYRO_2_L3G = 4, //!< Gyro 2, L3GD20h, U5, B side + SS_MGM_2_LIS3 = 17, //!< MGM 2, LIS3MDLTR, U8, B side + SS_MGM_3_RM = 27, //!< MGM 3, RM3100, U9, B side + }; + const std::string spiDeviceName = "/dev/spidev0.0"; int spiFd = 0; diff --git a/cmake/HardwareOsPostConfig.cmake b/cmake/HardwareOsPostConfig.cmake index c3dc3f93..73a8d8b1 100644 --- a/cmake/HardwareOsPostConfig.cmake +++ b/cmake/HardwareOsPostConfig.cmake @@ -55,8 +55,8 @@ target_compile_options(${TARGET_NAME} PRIVATE add_custom_command( TARGET ${TARGET_NAME} POST_BUILD - COMMAND echo Generating binary file ${CMAKE_PROJECT_NAME}.bin.. COMMAND ${CMAKE_OBJCOPY} -O binary ${TARGET_NAME} ${TARGET_NAME}.bin + COMMENT "Generating binary file ${CMAKE_PROJECT_NAME}.bin.." ) endfunction() \ No newline at end of file diff --git a/cmake/PreProjectConfig.cmake b/cmake/PreProjectConfig.cmake index ce18d89d..f54da048 100644 --- a/cmake/PreProjectConfig.cmake +++ b/cmake/PreProjectConfig.cmake @@ -19,15 +19,15 @@ if(${OS_FSFW} STREQUAL linux AND TGT_BSP) ) elseif (${TGT_BSP} MATCHES "arm/raspberrypi") if(NOT DEFINED ENV{RASPBIAN_ROOTFS}) - if(NOT RASPBIAN_ROOTFS) + if(NOT DEFINED RASPBIAN_ROOTFS) + message(WARNING "No RASPBIAN_ROOTFS environmental or CMake variable set!") set(ENV{RASPBIAN_ROOTFS} "$ENV{HOME}/raspberrypi/rootfs") else() set(ENV{RASPBIAN_ROOTFS} "${RASPBIAN_ROOTFS}") endif() else() message(STATUS - "RASPBIAN_ROOTFS from environmental variables used: " - "$ENV{RASPBIAN_ROOTFS}" + "RASPBIAN_ROOTFS from environmental variables used: $ENV{RASPBIAN_ROOTFS}" ) endif() @@ -36,12 +36,8 @@ if(${OS_FSFW} STREQUAL linux AND TGT_BSP) message(STATUS "No RASPBERRY_VERSION specified, setting to 4") set(RASPBERRY_VERSION "4" CACHE STRING "Raspberry Pi version") else() - message(STATUS - "Setting RASPBERRY_VERSION to ${RASPBERRY_VERSION}" - ) - set(RASPBERRY_VERSION - ${RASPBERRY_VERSION} CACHE STRING "Raspberry Pi version" - ) + message(STATUS "Setting RASPBERRY_VERSION to ${RASPBERRY_VERSION}") + set(RASPBERRY_VERSION ${RASPBERRY_VERSION} CACHE STRING "Raspberry Pi version") set(ENV{RASPBERRY_VERSION} ${RASPBERRY_VERSION}) endif() else() diff --git a/fsfw b/fsfw index bd5cc7ae..41c0436e 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit bd5cc7ae3ea53040cc832b5d756846d21613d91a +Subproject commit 41c0436e29f7a75f737f75e963dc2119a64a3921 diff --git a/fsfwconfig/FSFWConfig.h b/fsfwconfig/FSFWConfig.h index 261e3d6d..e3def8fe 100644 --- a/fsfwconfig/FSFWConfig.h +++ b/fsfwconfig/FSFWConfig.h @@ -7,19 +7,18 @@ //! Used to determine whether C++ ostreams are used which can increase //! the binary size significantly. If this is disabled, //! the C stdio functions can be used alternatively -#define FSFW_CPP_OSTREAM_ENABLED 1 +#define FSFW_CPP_OSTREAM_ENABLED 1 -//! More FSFW related printouts. -//! Be careful, this also turns off most diagnostic prinouts! -#define FSFW_ENHANCED_PRINTOUT 0 +//! More FSFW related printouts depending on level. Useful for development. +#define FSFW_VERBOSE_LEVEL 1 //! Can be used to completely disable printouts, even the C stdio ones. -#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_ENHANCED_PRINTOUT == 0 - #define FSFW_DISABLE_PRINTOUT 0 +#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_VERBOSE_LEVEL == 0 + #define FSFW_DISABLE_PRINTOUT 0 #endif -//! Can be used to enable additional debugging printouts for developing the FSFW -#define FSFW_PRINT_VERBOSITY_LEVEL 0 +//! Can be used to disable the ANSI color sequences for C stdio. +#define FSFW_COLORED_OUTPUT 1 //! Can be used to disable the ANSI color sequences for C stdio. #define FSFW_COLORED_OUTPUT 1 diff --git a/fsfwconfig/OBSWConfig.h b/fsfwconfig/OBSWConfig.h index bc534929..0682a0c3 100644 --- a/fsfwconfig/OBSWConfig.h +++ b/fsfwconfig/OBSWConfig.h @@ -12,7 +12,7 @@ // debugging. #define OBSW_ENHANCED_PRINTOUT 1 -#define TE0720 1 +#define TE0720 0 #include "OBSWVersion.h" diff --git a/fsfwconfig/devices/gpioIds.h b/fsfwconfig/devices/gpioIds.h index 3270ff62..d2a7a1ec 100644 --- a/fsfwconfig/devices/gpioIds.h +++ b/fsfwconfig/devices/gpioIds.h @@ -5,7 +5,7 @@ namespace gpioIds { enum gpioId_t { - HEATER_1 + HEATER_0 }; } diff --git a/fsfwconfig/devices/heaterSwitcherList.h b/fsfwconfig/devices/heaterSwitcherList.h new file mode 100644 index 00000000..c673b1d8 --- /dev/null +++ b/fsfwconfig/devices/heaterSwitcherList.h @@ -0,0 +1,13 @@ +#ifndef FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_ +#define FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_ + +namespace heaterSwitches { + enum switcherList { + PAYLOAD_CAMERA, + NUMBER_OF_SWITCHES + }; +} + + + +#endif /* FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_ */ diff --git a/fsfwconfig/devices/powerSwitcherList.cpp b/fsfwconfig/devices/powerSwitcherList.cpp deleted file mode 100644 index 7439c6de..00000000 --- a/fsfwconfig/devices/powerSwitcherList.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include - - - diff --git a/fsfwconfig/events/subsystemIdRanges.h b/fsfwconfig/events/subsystemIdRanges.h index 47e04816..e04d57fb 100644 --- a/fsfwconfig/events/subsystemIdRanges.h +++ b/fsfwconfig/events/subsystemIdRanges.h @@ -18,7 +18,8 @@ enum: uint8_t { PUS_SERVICE_8, PUS_SERVICE_23, MGM_LIS3MDL, - MGM_RM3100 + MGM_RM3100, + PCDU_HANDLER }; } diff --git a/fsfwconfig/objects/systemObjectList.h b/fsfwconfig/objects/systemObjectList.h index 559d0543..8bb027f8 100644 --- a/fsfwconfig/objects/systemObjectList.h +++ b/fsfwconfig/objects/systemObjectList.h @@ -2,10 +2,15 @@ #define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ #include +#include // The objects will be instantiated in the ID order namespace objects { enum sourceObjects: uint32_t { + /* 0x53 reserved for FSFW */ + FW_ADDRESS_START = PUS_SERVICE_1_VERIFICATION, + FW_ADDRESS_END = TIME_STAMPER, + /* First Byte 0x50-0x52 reserved for PUS Services **/ CCSDS_PACKET_DISTRIBUTOR = 0x50000100, PUS_PACKET_DISTRIBUTOR = 0x50000200, @@ -21,19 +26,13 @@ namespace objects { TM_FUNNEL = 0x52000002, - /* Test Task */ - TEST_TASK = 0x42694269, - DUMMY_INTERFACE = 0xCAFECAFE, - DUMMY_HANDLER = 0x4400AFFE, - P60DOCK_TEST_TASK = 0x00005060, - /* 0x49 ('I') for Communication Interfaces **/ ARDUINO_COM_IF = 0x49000001, CSP_COM_IF = 0x49000002, I2C_COM_IF = 0x49000003, /* 0x47 ('G') for Gpio Interfaces */ - GPIO_IF = 0x470000001, + GPIO_IF = 0x47000001, /* 0x44 ('D') for device handlers */ P60DOCK_HANDLER = 0x44000001, @@ -43,8 +42,18 @@ namespace objects { TMP1075_HANDLER_1 = 0x44000005, TMP1075_HANDLER_2 = 0x44000006, + /* Custom device handler */ + PCDU_HANDLER = 0x45000001, + /* 0x54 ('T') for thermal objects */ - HEATER_HANDLER = 0x54000001 + HEATER_HANDLER = 0x54000001, + + /* 0x54 ('T') for test handlers */ + TEST_TASK = 0x54694269, + SPI_TEST = 0x54000010, + DUMMY_INTERFACE = 0x5400CAFE, + DUMMY_HANDLER = 0x5400AFFE, + P60DOCK_TEST_TASK = 0x00005060 }; } diff --git a/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp b/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp index d228b103..089c0ed4 100644 --- a/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp +++ b/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp @@ -10,26 +10,24 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) /* Length of a communication cycle */ uint32_t length = thisSequence->getPeriodMs(); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, - length * 0, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::TMP1075_HANDLER_2, - length * 0, DeviceHandlerIF::PERFORM_OPERATION); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, - length * 0.2, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::TMP1075_HANDLER_2, - length * 0.2, DeviceHandlerIF::SEND_WRITE); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, - length * 0.4, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::TMP1075_HANDLER_2, - length * 0.4, DeviceHandlerIF::GET_WRITE); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, - length * 0.6, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::TMP1075_HANDLER_2, - length * 0.6, DeviceHandlerIF::SEND_READ); - thisSequence->addSlot(objects::TMP1075_HANDLER_1, - length * 0.8, DeviceHandlerIF::GET_READ); - thisSequence->addSlot(objects::TMP1075_HANDLER_2, - length * 0.8, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::HEATER_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + + thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.2, DeviceHandlerIF::SEND_WRITE); + + thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.4, DeviceHandlerIF::GET_WRITE); + + thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.6, DeviceHandlerIF::SEND_READ); + + thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0.8, DeviceHandlerIF::GET_READ); + thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0.8, DeviceHandlerIF::GET_READ); if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { return HasReturnvaluesIF::RETURN_OK; diff --git a/fsfwconfig/returnvalues/classIds.h b/fsfwconfig/returnvalues/classIds.h index 55bff25c..e259b46f 100644 --- a/fsfwconfig/returnvalues/classIds.h +++ b/fsfwconfig/returnvalues/classIds.h @@ -13,7 +13,8 @@ enum { MISSION_CLASS_ID_START = FW_CLASS_ID_COUNT, MGM_LIS3MDL, MGM_RM3100, - LINUX_LIBGPIO_IF + LINUX_LIBGPIO_IF, + PCDU_HANDLER }; } diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject index e0ac2c75..7d08be5e 100644 --- a/misc/eclipse/.cproject +++ b/misc/eclipse/.cproject @@ -795,69 +795,51 @@ - + - - + - - - - - - - + + + + make + -j16 + clean + true + true + true + + + make + -j16 + hardclean + true + true + true + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/mission/devices/ACUHandler.cpp b/mission/devices/ACUHandler.cpp new file mode 100644 index 00000000..638c3f9b --- /dev/null +++ b/mission/devices/ACUHandler.cpp @@ -0,0 +1,14 @@ +#include "ACUHandler.h" + +ACUHandler::ACUHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, + uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, uint16 hkTableSize) : + GomspaceDeviceHandler(objectId, comIF, comCookie, maxConfigTableAddress, maxHkTableAddress, + hkTableSize) { +} + +ACUHandler::~ACUHandler() { +} + +void ACUHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) { + +} diff --git a/mission/devices/ACUHandler.h b/mission/devices/ACUHandler.h new file mode 100644 index 00000000..a6f7d046 --- /dev/null +++ b/mission/devices/ACUHandler.h @@ -0,0 +1,24 @@ +#ifndef MISSION_DEVICES_ACUHANDLER_H_ +#define MISSION_DEVICES_ACUHANDLER_H_ + +#include "GomspaceDeviceHandler.h" +#include + +/** + * @brief Handler for the ACU of Gomspace. Monitors and controls the battery charging via + * the solar pannels. + */ +class ACUHandler: public GomspaceDeviceHandler { +public: + ACUHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, + uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, uint16_t hkTableSize); + virtual ~ACUHandler(); +protected: + + virtual void letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) override; + +private: + +}; + +#endif /* MISSION_DEVICES_ACUHANDLER_H_ */ diff --git a/mission/devices/CMakeLists.txt b/mission/devices/CMakeLists.txt index a96be24f..9a2920d5 100644 --- a/mission/devices/CMakeLists.txt +++ b/mission/devices/CMakeLists.txt @@ -5,6 +5,12 @@ target_sources(${TARGET_NAME} PUBLIC MGMHandlerRM3100.cpp GomspaceDeviceHandler.cpp Tmp1075Handler.cpp + PCDUHandler.cpp + P60DockHandler.cpp + PDU1Handler.cpp + PDU2Handler.cpp + ACUHandler.cpp + HeaterHandler.cpp ) diff --git a/mission/devices/GPSHandler.cpp b/mission/devices/GPSHandler.cpp index fb549eb7..e53ce347 100644 --- a/mission/devices/GPSHandler.cpp +++ b/mission/devices/GPSHandler.cpp @@ -44,7 +44,7 @@ uint32_t GPSHandler::getTransitionDelayMs(Mode_t from, Mode_t to) { } ReturnValue_t GPSHandler::initializeLocalDataPool( - LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { return HasReturnvaluesIF::RETURN_OK; } diff --git a/mission/devices/GPSHandler.h b/mission/devices/GPSHandler.h index 52ac25be..01a13591 100644 --- a/mission/devices/GPSHandler.h +++ b/mission/devices/GPSHandler.h @@ -29,7 +29,7 @@ protected: void fillCommandAndReplyMap() override; void modeChanged() override; uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; - ReturnValue_t initializeLocalDataPool(LocalDataPool &localDataPoolMap, + ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; private: diff --git a/mission/devices/GomspaceDeviceHandler.cpp b/mission/devices/GomspaceDeviceHandler.cpp index 5db2ed19..2529100a 100644 --- a/mission/devices/GomspaceDeviceHandler.cpp +++ b/mission/devices/GomspaceDeviceHandler.cpp @@ -2,14 +2,14 @@ #include GomspaceDeviceHandler::GomspaceDeviceHandler(object_id_t objectId, object_id_t comIF, - CookieIF * comCookie, uint16_t maxConfigTableAddress, - uint16_t maxHkTableAddress) : - DeviceHandlerBase(objectId, comIF, comCookie), maxConfigTableAddress( - maxConfigTableAddress), maxHkTableAddress(maxHkTableAddress) { - mode = MODE_NORMAL; - if (comCookie == NULL) { - sif::error << "GomspaceDeviceHandler invalid com cookie" << std::endl; - } + CookieIF * comCookie, uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, + uint16_t hkTableSize) : + DeviceHandlerBase(objectId, comIF, comCookie), maxConfigTableAddress(maxConfigTableAddress), maxHkTableAddress( + maxHkTableAddress), hkTableSize(hkTableSize) { + mode = MODE_NORMAL; + if (comCookie == NULL) { + sif::error << "GomspaceDeviceHandler invalid com cookie" << std::endl; + } } GomspaceDeviceHandler::~GomspaceDeviceHandler() { @@ -38,38 +38,41 @@ ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand( size_t commandDataLen) { ReturnValue_t result; switch(deviceCommand) { - case(PING): { + case(GOMSPACE::PING): { result = generatePingCommand(commandData, commandDataLen); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } break; } - case(REBOOT): { + case(GOMSPACE::REBOOT): { generateRebootCommand(); break; } - case(PARAM_SET):{ + case(GOMSPACE::PARAM_SET):{ result = generateSetParamCommand(commandData, commandDataLen); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } break; } - case(PARAM_GET):{ + case(GOMSPACE::PARAM_GET):{ result = generateGetParamCommand(commandData, commandDataLen); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } break; } - case(GNDWDT_RESET): { + case(GOMSPACE::GNDWDT_RESET): { result = generateResetWatchdogCmd(); if(result != HasReturnvaluesIF::RETURN_OK){ return result; } break; } + case(GOMSPACE::REQUEST_HK_TABLE): { + generateRequestFullHkTableCmd(hkTableSize); + } default: return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } @@ -77,31 +80,38 @@ ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand( } void GomspaceDeviceHandler::fillCommandAndReplyMap(){ - this->insertInCommandAndReplyMap(PING, 3); - this->insertInCommandMap(REBOOT); - this->insertInCommandAndReplyMap(PARAM_SET, 3); - this->insertInCommandAndReplyMap(PARAM_GET, 3); - this->insertInCommandMap(GNDWDT_RESET); + this->insertInCommandAndReplyMap(GOMSPACE::PING, 3); + this->insertInCommandMap(GOMSPACE::REBOOT); + this->insertInCommandAndReplyMap(GOMSPACE::PARAM_SET, 3); + this->insertInCommandAndReplyMap(GOMSPACE::PARAM_GET, 3); + this->insertInCommandAndReplyMap(GOMSPACE::REQUEST_HK_TABLE, 3); + this->insertInCommandMap(GOMSPACE::GNDWDT_RESET); } ReturnValue_t GomspaceDeviceHandler::scanForReply(const uint8_t *start, size_t remainingSize, DeviceCommandId_t *foundId, size_t *foundLen) { switch(rememberCommandId) { - case(PING): - *foundId = PING; + case(GOMSPACE::PING): + *foundId = GOMSPACE::PING; *foundLen = PING_REPLY_SIZE; - rememberCommandId = NONE; + rememberCommandId = GOMSPACE::NONE; break; - case(PARAM_GET): { - *foundId = PARAM_GET; - *foundLen = rememberRequestedSize + CspGetParamReply::GS_HDR_LENGTH; - rememberCommandId = NONE; + case(GOMSPACE::PARAM_GET): { + *foundId = GOMSPACE::PARAM_GET; + *foundLen = rememberRequestedSize + GOMSPACE::GS_HDR_LENGTH; + rememberCommandId = GOMSPACE::NONE; break; } - case(PARAM_SET): { - *foundId = PARAM_SET; + case(GOMSPACE::PARAM_SET): { + *foundId = GOMSPACE::PARAM_SET; *foundLen = rememberRequestedSize; - rememberCommandId = NONE; + rememberCommandId = GOMSPACE::NONE; + break; + } + case(GOMSPACE::REQUEST_HK_TABLE): { + *foundId = GOMSPACE::REQUEST_HK_TABLE; + *foundLen = rememberRequestedSize + GOMSPACE::GS_HDR_LENGTH; + rememberCommandId = GOMSPACE::NONE; break; } default: @@ -113,12 +123,12 @@ ReturnValue_t GomspaceDeviceHandler::scanForReply(const uint8_t *start, ReturnValue_t GomspaceDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) { switch(id) { - case(PING): { + case(GOMSPACE::PING): { SerializeElement replyTime = *packet; handleDeviceTM(&replyTime, id, true); break; } - case(PARAM_GET): { + case(GOMSPACE::PARAM_GET): { // -2 to subtract address size from gomspace parameter reply packet uint16_t payloadLength = (*(packet + 2) << 8 | *(packet + 3)) - 2; if(payloadLength > sizeof(uint32_t)){ @@ -129,7 +139,7 @@ ReturnValue_t GomspaceDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, uint8_t tempPayloadBuffer[payloadLength]; /* Extract information from received data */ CspGetParamReply cspGetParamReply(tempPayloadBuffer, payloadLength); - size_t size = CspGetParamReply::GS_HDR_LENGTH + payloadLength; + size_t size = GOMSPACE::GS_HDR_LENGTH + payloadLength; ReturnValue_t result = cspGetParamReply.deSerialize(&packet, &size, SerializeIF::Endianness::BIG); if(result != HasReturnvaluesIF::RETURN_OK){ @@ -146,7 +156,7 @@ ReturnValue_t GomspaceDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, handleDeviceTM(¶mReply, id, true); break; } - case(PARAM_SET): { + case(GOMSPACE::PARAM_SET): { /* When setting a parameter, the p60dock sends back the state of the * operation */ if(*packet != PARAM_SET_OK){ @@ -154,6 +164,10 @@ ReturnValue_t GomspaceDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, } break; } + case(GOMSPACE::REQUEST_HK_TABLE): { + letChildHandleHkReply(id, packet); + break; + } default: break; } @@ -211,7 +225,7 @@ ReturnValue_t GomspaceDeviceHandler::generateSetParamCommand( rawPacket = cspPacket; rawPacketLen = cspPacketLen; rememberRequestedSize = querySize; - rememberCommandId = PARAM_SET; + rememberCommandId = GOMSPACE::PARAM_SET; return HasReturnvaluesIF::RETURN_OK; } @@ -256,7 +270,7 @@ ReturnValue_t GomspaceDeviceHandler::generateGetParamCommand( << "size" << std::endl; return INVALID_PARAM_SIZE; } - uint16_t querySize = parameterSize + CspGetParamCommand::GS_HDR_LENGTH; + uint16_t querySize = parameterSize + GOMSPACE::GS_HDR_LENGTH; /* Generate the CSP command to send to the P60 Dock */ CspGetParamCommand getParamCmd(querySize, tableId, length, @@ -277,7 +291,7 @@ ReturnValue_t GomspaceDeviceHandler::generateGetParamCommand( rawPacket = cspPacket; rawPacketLen = cspPacketLen; rememberRequestedSize = querySize; - rememberCommandId = PARAM_GET; + rememberCommandId = GOMSPACE::PARAM_GET; return HasReturnvaluesIF::RETURN_OK; } @@ -301,7 +315,7 @@ ReturnValue_t GomspaceDeviceHandler::generatePingCommand( } rawPacket = cspPacket; rawPacketLen = cspPacketLen; - rememberCommandId = PING; + rememberCommandId = GOMSPACE::PING; return HasReturnvaluesIF::RETURN_OK; } @@ -330,10 +344,32 @@ ReturnValue_t GomspaceDeviceHandler::generateResetWatchdogCmd(){ rawPacketLen = cspPacketLen; rememberRequestedSize = 0; // No bytes will be queried with the ground // watchdog command. - rememberCommandId = GNDWDT_RESET; + rememberCommandId = GOMSPACE::GNDWDT_RESET; return HasReturnvaluesIF::RETURN_OK; } +ReturnValue_t GomspaceDeviceHandler::generateRequestFullHkTableCmd(uint16_t hkTableSize) { + + uint16_t querySize = hkTableSize + GOMSPACE::GS_HDR_LENGTH; + uint8_t tableId = HK_TABLE_ID; + RequestFullTableCommand requestFullTableCommand(querySize, tableId); + + size_t cspPacketLen = 0; + uint8_t* buffer = cspPacket; + ReturnValue_t result = requestFullTableCommand.serialize(&buffer, + &cspPacketLen, sizeof(cspPacket), SerializeIF::Endianness::BIG); + if(result != HasReturnvaluesIF::RETURN_OK){ + sif::error << "GomspaceDeviceHandler::generateRequestFullHkTableCmd Failed to serialize " + "full table request command " << std::endl; + return result; + } + rawPacket = cspPacket; + rawPacketLen = cspPacketLen; + rememberRequestedSize = querySize; + rememberCommandId = GOMSPACE::REQUEST_HK_TABLE; + return RETURN_OK; +} + uint32_t GomspaceDeviceHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 0; diff --git a/mission/devices/GomspaceDeviceHandler.h b/mission/devices/GomspaceDeviceHandler.h index c6f1866a..2ea8af4a 100644 --- a/mission/devices/GomspaceDeviceHandler.h +++ b/mission/devices/GomspaceDeviceHandler.h @@ -2,6 +2,7 @@ #define MISSION_DEVICES_GOMSPACEDEVICEHANDLER_H_ #include +#include /** * @brief This is the device handler class for all gomspace devices. @@ -19,6 +20,7 @@ public: static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE2); static const ReturnValue_t INVALID_PARAM_SIZE = MAKE_RETURN_CODE(0xE3); static const ReturnValue_t INVALID_PAYLOAD_SIZE = MAKE_RETURN_CODE(0xE4); + static const ReturnValue_t UNKNOWN_REPLY_ID = MAKE_RETURN_CODE(0xE5); /** * @brief Constructor @@ -30,11 +32,28 @@ public: * device. */ GomspaceDeviceHandler(object_id_t objectId, object_id_t comIF, - CookieIF * comCookie, uint16_t maxConfigTableAddress, - uint16_t maxHkTableAddress); + CookieIF * comCookie, uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, + uint16_t hkTableSize); virtual ~GomspaceDeviceHandler(); protected: + + static const uint8_t MAX_PACKET_LEN = 36; + static const uint8_t PARAM_SET_OK = 1; + static const uint8_t PING_REPLY_SIZE = 2; + static const uint8_t CONFIG_TABLE_ID = 1; + static const uint8_t HK_TABLE_ID = 4; + + uint8_t rememberRequestedSize = 0; + uint8_t rememberCommandId = GOMSPACE::NONE; + uint8_t cspPacket[MAX_PACKET_LEN]; + + uint16_t maxConfigTableAddress; + uint16_t maxHkTableAddress; + + /** The size of the housekeeping table (table id 4) */ + uint16_t hkTableSize; + void doStartUp() override; void doShutDown() override; virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) @@ -49,29 +68,22 @@ protected: const uint8_t *packet) override; void setNormalDatapoolEntriesInvalid() override; uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + /** + * @brief The command to generate a request to receive the full housekeeping table is device + * specific. Thus the child has to build this command. + */ + virtual ReturnValue_t generateRequestFullHkTableCmd(uint16_t hkTableSize); + + /** + * @brief Because housekeeping tables are device specific the handling of the reply is + * given to the child class. + * @param id The id of the command which initiates the full table request. + * @param packet Pointer to the reply containing the hk table. + */ + virtual void letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) = 0; private: - static const uint8_t MAX_PACKET_LEN = 36; - static const uint8_t PARAM_SET_OK = 1; - static const uint8_t PING_REPLY_SIZE = 2; - static const uint8_t CONFIG_TABLE_ID = 1; - static const uint8_t HK_TABLE_ID = 4; - /* Device commands are derived from the rparam.h of the gomspace lib */ - static const DeviceCommandId_t PING = 0x1; //!< [EXPORT] : [COMMAND] - static const DeviceCommandId_t NONE = 0x2; // Set when no command is pending - static const DeviceCommandId_t REBOOT = 0x4; //!< [EXPORT] : [COMMAND] - static const DeviceCommandId_t GNDWDT_RESET = 0x9; //!< [EXPORT] : [COMMAND] - static const DeviceCommandId_t PARAM_GET = 0x00; //!< [EXPORT] : [COMMAND] - static const DeviceCommandId_t PARAM_SET = 0xFF; //!< [EXPORT] : [COMMAND] - - uint8_t rememberRequestedSize = 0; - uint8_t rememberCommandId = NONE; - uint8_t cspPacket[MAX_PACKET_LEN]; - - uint16_t maxConfigTableAddress; - uint16_t maxHkTableAddress; - /** * @brief Function to generate the command to set a parameter. Command * will be sent to the ComIF over the rawPacket buffer. diff --git a/mission/devices/GyroL3GD20Handler.cpp b/mission/devices/GyroL3GD20Handler.cpp index 38016531..28cbdbed 100644 --- a/mission/devices/GyroL3GD20Handler.cpp +++ b/mission/devices/GyroL3GD20Handler.cpp @@ -1,4 +1,5 @@ #include +#include GyroHandler::GyroHandler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie): @@ -171,14 +172,13 @@ ReturnValue_t GyroHandler::interpretDeviceReply(DeviceCommandId_t id, int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX]; float temperature = 25.0 + temperaturOffset; - result = dataset.read(); - if(result == HasReturnvaluesIF::RETURN_OK) { + PoolReadHelper readSet(&dataset); + if(readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) { dataset.angVelocX = angVelocX; dataset.angVelocY = angVelocY; dataset.angVelocZ = angVelocZ; dataset.temperature = temperature; dataset.setValidity(true, true); - result = dataset.commit(); } break; } @@ -194,7 +194,7 @@ uint32_t GyroHandler::getTransitionDelayMs(Mode_t from, Mode_t to) { } ReturnValue_t GyroHandler::initializeLocalDataPool( - LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localDataPoolMap.emplace(L3GD20H::ANG_VELOC_X, new PoolEntry({0.0})); localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, diff --git a/mission/devices/GyroL3GD20Handler.h b/mission/devices/GyroL3GD20Handler.h index 5905b26a..20396315 100644 --- a/mission/devices/GyroL3GD20Handler.h +++ b/mission/devices/GyroL3GD20Handler.h @@ -37,7 +37,7 @@ protected: void fillCommandAndReplyMap() override; void modeChanged() override; uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; - ReturnValue_t initializeLocalDataPool(LocalDataPool &localDataPoolMap, + ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; private: diff --git a/mission/devices/HeaterHandler.cpp b/mission/devices/HeaterHandler.cpp index c080d63b..e09568ea 100644 --- a/mission/devices/HeaterHandler.cpp +++ b/mission/devices/HeaterHandler.cpp @@ -1,121 +1,101 @@ #include +#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(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), actionHelper(this, nullptr) { + commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, + MessageQueueMessage::MAX_MESSAGE_SIZE); } HeaterHandler::~HeaterHandler() { } -ReturnValue_t performOperation(uint8_t operationCode) { +ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) { if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) { readCommandQueue(); - handlePendingCommand(); - doStateMachine(); - - checkSwitchState(); - decrementDeviceReplyMap(); - fdirInstance->checkForFailures(); - hkSwitcher.performOperation(); - performOperationHook(); + handleActiveCommands(); return RETURN_OK; } + } -ReturnValue_t DeviceHandlerBase::initialize() { +ReturnValue_t HeaterHandler::initialize() { ReturnValue_t result = SystemObject::initialize(); if (result != RETURN_OK) { - return result; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + result = initializeHeaterMap(); + if (result != RETURN_OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; } gpioInterface = objectManager->get(gpioDriverId); if (gpioInterface == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "HeaterHandler::initialize: Invalid Gpio interface." - << std::endl; -#endif + sif::error << "HeaterHandler::initialize: Invalid Gpio interface." << std::endl; 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; + sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; } 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 + sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl; 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 + if(mainLineSwitcherObjectId != objects::NO_OBJECT) { + mainLineSwitcher = objectManager->get(mainLineSwitcherObjectId); + if (mainLineSwitcher == nullptr) { + sif::error << "HeaterHandler::initialize: Main line switcher failed to fetch object" + << "from object ID." << std::endl; 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; + return ObjectManagerIF::CHILD_INIT_FAILED; } - fillCommandAndReplyMap(); - return RETURN_OK; } -void DeviceHandlerBase::readCommandQueue() { - - if (dontCheckQueue()) { - return; +ReturnValue_t HeaterHandler::initializeHeaterMap(){ + heaterMapIter = heaterMap.begin(); + HeaterCommandInfo_t heaterCommandInfo; + for(int switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { + std::pair status = heaterMap.emplace(switchNr, heaterCommandInfo); + if (status.second == false) { + sif::error << "HeaterHandler::initializeHeaterMap: Failed to initialize heater map" + << std::endl; + return RETURN_FAILED; + } } + return RETURN_OK; +} +void HeaterHandler::setInitialSwitchStates() { + for (int switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { + switchStates[switchNr] = OFF; + } +} + +void HeaterHandler::readCommandQueue() { 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; @@ -124,56 +104,51 @@ void DeviceHandlerBase::readCommandQueue() { 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()) { + if (actionId != SWITCH_ON && actionId != SWITCH_OFF) { result = COMMAND_NOT_SUPPORTED; } else { - if (commandedBy == commandQueue){ - heaterCommand(*(data), *(data + 1), NO_COMMANDER); - commandPending = true; + heaterMapIter = heaterMap.find(*data); + if (heaterMapIter != heaterMap.end()) { + heaterMapIter.second.action = *(data + 1); + heaterMapIter.second.active = true; } else { - heaterCommand(*(data), *(data + 1), commandedBy); - commandPending = true; + sif::error << "HeaterHandler::executeAction: Invalid switchNr" << std::endl; + return INVALID_SWITCH_NR; } 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; + store_address_t storeAddress; + uint8_t commandData[2]; switch(onOff) { case PowerSwitchIF::SWITCH_ON: - command(SWITCH_ON, switchNr); + commandData[0] = switchNr; + commandData[1] = SET_SWITCH_ON; case PowerSwitchIF::SWITCH_OFF: - command(SWITCH_OFF, switchNr); + commandData[0] = switchNr; + commandData[1] = SET_SWITCH_OFF; default: sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request" << std::endl; } - result = IPCStore->addData(&address, &command, sizeof(command)); + result = IPCStore->addData(&storeAddress, commandData, sizeof(commandData)); if (result == RETURN_OK) { CommandMessage message; ActionMessage::setCommand(&message, - HeaterHandler::SWITCH_HEATER, address); + HeaterHandler::SWITCH_HEATER, storeAddress); /* Send heater command to own command queue */ result = commandQueue->sendMessage(commandQueue, &message, 0); if (result != RETURN_OK) { @@ -183,32 +158,79 @@ void HeaterHandler::sendSwitchCommand(uint8_t switchNr, } } -void HeaterHandler::handlePendingCommand(){ +void HeaterHandler::handleActiveCommands(){ ReturnValue_t result; - if (!commandPending) { - return; - } - switch(heaterCommand.action) { - case SET_SWITCH_ON: - result = gpioInterface->pullHigh(heaterCommand.heaterSwitchNr); - if (result != RETURN_OK) { - triggerEvent() + heaterMapIter = heaterMap.begin(); + for (; heaterMapIter != mapToAdd.end(); heaterMapIter++) { + if (heaterMapIter.second.active) { + switch(heaterMapIter.second.action) { + case SET_SWITCH_ON: + int switchNr = heaterMapIter.first(); + /* Check state of main line switch */ + if (mainLineSwitcher->getSwitchState(pcduSwitches::TCS_BOARD_8V_HEATER_IN) + == SWITCH_ON) { + if (!checkSwitchState(switchNr)) { + gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr); + result = gpioInterface->pullHigh(gpioId); + if (result != RETURN_OK) { + triggerEvent(GPIO_PULL_HIGH_FAILED, result); + } + } + else { + triggerEvent(SWITCH_ALREADY_ON, switchNr); + } + /* There is no need to send action finish replies if the sender was the + * HeaterHandler itself. */ + if (heaterMapIter.second.replyQueue != commandQueue) { + actionHelper.finish(heaterMapIter.second.replyQueue, + heaterMapIter.second.action, result); + } + heaterMapIter.second.active = false; + } + else { + mainLineSwitcher->sendSwitchCommand(pcduSwitches::TCS_BOARD_8V_HEATER_IN); + } + break; + case SET_SWITCH_OFF: + int switchNr = heaterMapIter.first(); + if (checkSwitchState(switchNr)) { + gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr); + result = gpioInterface->pullLow(gpioId); + triggerEvent(GPIO_PULL_LOW_FAILED, result); + } + else { + triggerEvent(SWITCH_ALREADY_OFF, switchNr); + } + if (heaterCommand.replyQueue != NO_COMMANDER) { + actionHelper.finish(heaterMapIter.second.replyQueue, + heaterMapIter.second.action, result); + } + break; + default: + sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded" + << std::endl; + break; + } } - 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; } } +bool HeaterHandler::checkSwitchState(int switchNr) { + return switchStates[switchNr]; +} + +gpioId_t HeaterHandler::getGpioIdFromSwitchNr(switchNr) { + gpioId_t gpioId = 0xFFFF; + switch(switchNr) { + case heaterSwitches::PAYLOAD_CAMERA: + gpioId = gpioIds::HEATER_0; + break; + default: + sif::error << "HeaterHandler::getGpioIdFromSwitchNr: Unknown heater switch number" + << std::endl; + break; + } + return gpioId; +} + diff --git a/mission/devices/HeaterHandler.h b/mission/devices/HeaterHandler.h index ab9aebdc..30cd12b8 100644 --- a/mission/devices/HeaterHandler.h +++ b/mission/devices/HeaterHandler.h @@ -7,6 +7,7 @@ #include #include #include +#include /** * @brief This class intends the control of heaters. @@ -21,15 +22,14 @@ class HeaterHandler: public ExecutableObjectIF, 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; + HeaterHandler(object_id_t setObjectId, object_id_t gpioDriverId, CookieIF * gpioCookie, + object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch); + + virtual ~HeaterHandler(); + virtual ReturnValue_t performOperation(uint8_t operationCode = 0); void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override; @@ -47,67 +47,82 @@ public: private: - static const MessageQueueId_t NO_COMMANDER = 0; + static const uint8_t INTERFACE_ID = CLASS_ID::PCDU_HANDLER; + + static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); + static const ReturnValue_t INIT_FAILED = MAKE_RETURN_CODE(0xA2); + static const ReturnValue_t INVALID_SWITCH_NR = MAKE_RETURN_CODE(0xA3); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_HANDLER; + static const Event GPIO_PULL_HIGH_FAILED = MAKE_EVENT(0, severity::LOW); + static const Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW); + static const Event SWITCH_ALREADY_ON = MAKE_EVENT(2, severity::LOW); + static const Event SWITCH_ALREADY_OFF = MAKE_EVENT(3, severity::LOW); ReturnValue_t buildCommandFromCommand( DeviceCommandId_t deviceCommand, const uint8_t *commandData, size_t commandDataLen); - ReturnValue_t acceptExternalDeviceCommands(); + /** + * @brief Returns the state of a switch (ON - true, or OFF - false). + * @param switchNr The number of the switch to check. + */ + bool checkSwitchState(int switchNr); + + /** + * @brief Returns the ID of the GPIO related to a heater identified by the switch number + * which is defined in the heaterSwitches list. + */ + gpioId_t getGpioIdFromSwitchNr(switchNr); /** * @brief This function runs commands waiting for execution. */ - void handlePendingCommand(); + void handleActiveCommands(); + + ReturnValue_t initializeHeaterMap(); + + /** + * @brief Sets all switches to OFF. + */ + void setInitialSwitchStates(); + + enum SwitchState : bool { + ON = true, + OFF = false + }; + /** * @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. + * @param active True if command is waiting for execution, otherwise false. */ - typedef struct HeaterCommand { - HeaterCommand(uint8_t action_, uint8_t heaterSwitchNr, - MessageQueueId_t replyQueue_) { - action = action_; - heaterSwitchNr = heaterSwitchNr_; - replyQueue = replyQueue_; - } + typedef struct HeaterCommandInfo { uint8_t action; - uint8_t heaterSwitchNr; MessageQueueId_t replyQueue; - } HeaterCommand_t; - + bool active = false; + } HeaterCommandInfo_t; enum SwitchAction { SET_SWITCH_ON, SET_SWITCH_OFF }; - /** This HeaterCommand instance holds the next heater command to execute */ - HeaterCommand_t heaterCommand; + using switchNr_t = int; + using HeaterMap = std::unordered_map; + using HeaterMapIter = HeaterMap::iterator; - /** - * This variable is set when the command stored in heaterCommand shall be - * executed. - */ - bool commandPending; + HeateerMap heaterMap; + HeaterMapIter heaterMapIter; + + bool switchStates[heaterSwitches::NUMBER_OF_SWITCHES]; /** 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. @@ -119,14 +134,20 @@ private: /** Queue to receive messages from other objects. */ MessageQueueIF* commandQueue = nullptr; + object_id_t mainLineSwitcherObjectId; + + /** Switch number of the heater power supply switch */ + uint8_t mainLineSwitch; + /** * Power switcher object which controls the 8V main line of the heater * logic on the TCS board. */ - PowerSwitchIF *powerSwitcher; + PowerSwitchIF *mainLineSwitcher = nullptr; - HeaterHandler(); - virtual ~HeaterHandler(); + ActionHelper actionHelper; + + StorageManagerIF *IPCStore = nullptr; }; #endif /* MISSION_DEVICES_HEATERHANDLER_H_ */ diff --git a/mission/devices/MGMHandlerLIS3MDL.cpp b/mission/devices/MGMHandlerLIS3MDL.cpp index 58740d7d..2445620d 100644 --- a/mission/devices/MGMHandlerLIS3MDL.cpp +++ b/mission/devices/MGMHandlerLIS3MDL.cpp @@ -423,7 +423,7 @@ void MGMHandlerLIS3MDL::modeChanged(void) { } ReturnValue_t MGMHandlerLIS3MDL::initializeLocalDataPool( - LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_X, new PoolEntry({0.0})); localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Y, diff --git a/mission/devices/MGMHandlerLIS3MDL.h b/mission/devices/MGMHandlerLIS3MDL.h index 414731db..4a62ba31 100644 --- a/mission/devices/MGMHandlerLIS3MDL.h +++ b/mission/devices/MGMHandlerLIS3MDL.h @@ -52,7 +52,7 @@ protected: const uint8_t *packet) override; void fillCommandAndReplyMap() override; void modeChanged(void) override; - ReturnValue_t initializeLocalDataPool(LocalDataPool &localDataPoolMap, + ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; private: diff --git a/mission/devices/MGMHandlerRM3100.cpp b/mission/devices/MGMHandlerRM3100.cpp index 0fda5fba..62db06a7 100644 --- a/mission/devices/MGMHandlerRM3100.cpp +++ b/mission/devices/MGMHandlerRM3100.cpp @@ -304,7 +304,7 @@ void MGMHandlerRM3100::modeChanged(void) { } ReturnValue_t MGMHandlerRM3100::initializeLocalDataPool( - LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_X, new PoolEntry({0.0})); localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Y, diff --git a/mission/devices/MGMHandlerRM3100.h b/mission/devices/MGMHandlerRM3100.h index d735ca45..4af6b627 100644 --- a/mission/devices/MGMHandlerRM3100.h +++ b/mission/devices/MGMHandlerRM3100.h @@ -55,7 +55,7 @@ protected: void fillCommandAndReplyMap() override; void modeChanged(void) override; uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; - ReturnValue_t initializeLocalDataPool(LocalDataPool &localDataPoolMap, + ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; private: diff --git a/mission/devices/P60DockHandler.cpp b/mission/devices/P60DockHandler.cpp new file mode 100644 index 00000000..771a6533 --- /dev/null +++ b/mission/devices/P60DockHandler.cpp @@ -0,0 +1,14 @@ +#include "P60DockHandler.h" + +P60DockHandler::P60DockHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, + uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, uint16_t hkTableSize) : + GomspaceDeviceHandler(objectId, comIF, comCookie, maxConfigTableAddress, maxHkTableAddress, + hkTableSize) { +} + +P60DockHandler::~P60DockHandler() { +} + +void P60DockHandler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) { + +} diff --git a/mission/devices/P60DockHandler.h b/mission/devices/P60DockHandler.h new file mode 100644 index 00000000..f23a365d --- /dev/null +++ b/mission/devices/P60DockHandler.h @@ -0,0 +1,21 @@ +#ifndef MISSION_DEVICES_P60DOCKHANDLER_H_ +#define MISSION_DEVICES_P60DOCKHANDLER_H_ + +#include "GomspaceDeviceHandler.h" + + +/** + * @brief Device handler for the P60Dock. The P60Dock serves as carrier for the ACU, PDU1 and + * PDU2. Via the P60Dock each of these modules can be turned on and off individually. + */ +class P60DockHandler: public GomspaceDeviceHandler { +public: + P60DockHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, + uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, uint16_t hkTableSize); + virtual ~P60DockHandler(); + +protected: + virtual void letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) override; +}; + +#endif /* MISSION_DEVICES_P60DOCKHANDLER_H_ */ diff --git a/mission/devices/PCDUHandler.cpp b/mission/devices/PCDUHandler.cpp index 63dd931c..1d68b776 100644 --- a/mission/devices/PCDUHandler.cpp +++ b/mission/devices/PCDUHandler.cpp @@ -1,18 +1,289 @@ -/* - * PCDUHandler.cpp - * - * Created on: 21.01.2021 - * Author: jakob - */ - #include "PCDUHandler.h" +#include +#include +#include +#include +#include -PCDUHandler::PCDUHandler() { - // TODO Auto-generated constructor stub +PCDUHandler::PCDUHandler(object_id_t setObjectId, size_t cmdQueueSize) : + SystemObject(setObjectId), poolManager(this, nullptr), pdu2HkTableDataset(this), cmdQueueSize( + cmdQueueSize) { + commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, + MessageQueueMessage::MAX_MESSAGE_SIZE); } PCDUHandler::~PCDUHandler() { - // TODO Auto-generated destructor stub } +ReturnValue_t PCDUHandler::performOperation(uint8_t counter) { + + if (counter == DeviceHandlerIF::PERFORM_OPERATION) { + readCommandQueue(); + return RETURN_OK; + } + + return RETURN_OK; +} + +ReturnValue_t PCDUHandler::initialize() { + + ReturnValue_t result; + + IPCStore = objectManager->get(objects::IPC_STORE); + if (IPCStore == nullptr) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + + result = poolManager.initialize(commandQueue); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + HasLocalDataPoolIF* pdu2Handler = objectManager->get(objects::PDU2_HANDLER); + if(pdu2Handler == nullptr) { + sif::warning << "PCDUHandler::initialize: Invalid pdu2Handler" << std::endl; + return RETURN_FAILED; + } + result = pdu2Handler->getSubscriptionInterface()->subscribeForSetUpdateMessages( + PDU2::HK_TABLE_DATA_SET_ID, this->getObjectId(), commandQueue->getId(), true); + if (result != RETURN_OK) { + sif::error << "PCDUHandler::initialize: Failed to subscribe for set update messages from " + << "PDU2Handler" << std::endl; + } + + return RETURN_OK; +} + +void PCDUHandler::readCommandQueue() { + ReturnValue_t result; + CommandMessage command; + result = poolManager.handleHousekeepingMessage(&command); + if (result == RETURN_OK) { + return; + } +} + +MessageQueueId_t PCDUHandler::getCommandQueue() const { + return commandQueue->getId(); +} + +void PCDUHandler::handleChangedDataset(sid_t sid, store_address_t storeId) { + + ReturnValue_t result; + + if (sid == sid_t(objects::PCDU_HANDLER, PDU2::HK_TABLE_DATA_SET_ID)) { + HousekeepingPacketUpdate packetUpdate(reinterpret_cast(&timeStamp), + sizeof(timeStamp), &pdu2HkTableDataset); + const uint8_t** packet_ptr; + size_t size; + result = IPCStore->getData(storeId, packet_ptr, &size); + if (result != RETURN_OK) { + sif::error << "PCDUHandler::handleChangedDataset: Failed to get data from IPCStore." + << std::endl; + //TODO: Is it necessary to trigger an Event here? + result = IPCStore->deleteData(storeId); + if (result != RETURN_OK) { + sif::error << "PCDUHandler::handleChangedDataset: Failed to delete data in IPCStore" + << std::endl; + } + } + result = packetUpdate.deSerialize(packet_ptr, &size, SerializeIF::Endianness::BIG); + if (result != RETURN_OK) { + sif::error << "PCDUHandler::handleChangedDataset: Failed to deserialize packet in " + << "pdu2HkTableDataset" << std::endl; + } + } + else { + sif::error << "PCDUHandler::handleChangedDataset: Invalid sid" << std::endl; + } +} + +LocalDataPoolManager* PCDUHandler::getHkManagerHandle() { + return &poolManager; +} + +void PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const { + + ReturnValue_t result; + uint16_t memoryAddress; + size_t parameterValueSize = sizeof(uint8_t); + uint8_t parameterValue; + GomspaceDeviceHandler* pdu; + + switch (switchNr) { + case pcduSwitches::TCS_BOARD_8V_HEATER_IN: + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_HEATER_IN; + pdu = objectManager->get(objects::PDU2_HANDLER); + break; + default: + sif::error << "PCDUHandler::sendSwitchCommand: Invalid switch number " << std::endl; + return; + } + + switch (onOff) { + case PowerSwitchIF::SWITCH_ON: + parameterValue = 1; + break; + case PowerSwitchIF::SWITCH_OFF: + parameterValue = 0; + break; + default: + sif::error << "PCDUHandler::sendSwitchCommand: Invalid state commanded" << std::endl; + return; + } + + size_t serializedLength = 0; + uint8_t command[4]; + uint8_t* commandPtr = command; + size_t maxSize = sizeof(command); + GomspaceSetParamMessage setParamMessage(memoryAddress, ¶meterValue, parameterValueSize); + setParamMessage.serialize(&commandPtr, &serializedLength, maxSize, + SerializeIF::Endianness::BIG); + + store_address_t storeAddress; + result = IPCStore->addData(&storeAddress, command,sizeof(command)); + + CommandMessage message; + ActionMessage::setCommand(&message, GOMSPACE::PARAM_SET, storeAddress); + + result = commandQueue->sendMessage(pdu->getCommandQueue(), &message, 0); + if (result != RETURN_OK) { + sif::debug << "PCDUHandler::sendSwitchCommand: Failed to send message to PDU Handler" + << std::endl; + } +} + +void PCDUHandler::sendFuseOnCommand(uint8_t fuseNr) const { + +} + +ReturnValue_t PCDUHandler::getSwitchState( uint8_t switchNr ) const { + switch (switchNr) { + case pcduSwitches::TCS_BOARD_8V_HEATER_IN: + if (pdu2HkTableDataset.outEnabledTCSBoardHeaterIn == 1) { + return PowerSwitchIF::SWITCH_ON; + } + else { + return PowerSwitchIF::SWITCH_OFF; + } + default: + sif::error << "PCDUHandler::getSwitchState: Invalid switchNr" << std::endl; + return RETURN_FAILED; + } +} + +ReturnValue_t PCDUHandler::getFuseState( uint8_t fuseNr ) const { + return RETURN_OK; +} + +uint32_t PCDUHandler::getSwitchDelayMs(void) const { + return 0; +} + +object_id_t PCDUHandler::getObjectId() const { + return SystemObject::getObjectId(); +} + +ReturnValue_t PCDUHandler::initializeLocalDataPool( + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_Q7S, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_RW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_SUS_REDUNDANT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_DEPLOYMENT_MECHANISM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_ACS_BOARD_SIDE_B, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_PAYLOAD_CAMERA, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_Q7S, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_RW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_SUS_REDUNDANT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_DEPLOYMENT_MECHANISM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_ACS_BOARD_SIDE_B, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_PAYLOAD_CAMERA, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_VCC, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VBAT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_TEMPERATURE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CONV_EN, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_Q7S, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_RW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_SUS_REDUNDANT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_ACS_BOARD_SIDE_B, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_PAYLOAD_CAMERA, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_BOOTCAUSE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_BOOTCNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_UPTIME, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_RESETCAUSE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_BATT_MODE, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_DEVICE_0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_7, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_DEVICE_0_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_1_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_2_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_3_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_4_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_5_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_6_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_7_STATUS, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_GND, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_I2C, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_CAN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_CSP, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_GND_LEFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_I2C_LEFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CAN_LEFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CSP_LEFT, new PoolEntry( { 0 })); + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t PCDUHandler::initializeAfterTaskCreation() { + + if(executingTask != nullptr) { + pstIntervalMs = executingTask->getPeriodMs(); + } + this->poolManager.initializeAfterTaskCreation(); + + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PCDUHandler::getPeriodicOperationFrequency() const { + return pstIntervalMs; +} + +void PCDUHandler::setTaskIF(PeriodicTaskIF* task){ + executingTask = task; +} + +LocalPoolDataSetBase* PCDUHandler::getDataSetHandle(sid_t sid) { + switch (sid) { + case pdu2HkTableDataset.getSid(): + return &pdu2HkTableDataset; + default: + sif::error << "PCDUHandler::getDataSetHandle: Invalid sid" << std::endl; + return nullptr; + break; + } +} diff --git a/mission/devices/PCDUHandler.h b/mission/devices/PCDUHandler.h index 29739e9b..7bb4c8a1 100644 --- a/mission/devices/PCDUHandler.h +++ b/mission/devices/PCDUHandler.h @@ -1,20 +1,83 @@ -/* - * PCDUHandler.h - * - * Created on: 21.01.2021 - * Author: jakob - */ - #ifndef MISSION_DEVICES_PCDUHANDLER_H_ #define MISSION_DEVICES_PCDUHANDLER_H_ +#include +#include +#include +#include +#include +#include +#include +#include + /** - * @brief + * @brief The PCDUHandler provides a compact interface to handle all devices related to the + * control of power. This is necessary because the fsfw manages all power related + * functionalities via one power object. This includes for example the switch on and off + * of devices. */ -class PCDUHandler: public PowerSwitchIF { +class PCDUHandler: public PowerSwitchIF, + public HasLocalDataPoolIF, + public SystemObject, + public ExecutableObjectIF { public: - PCDUHandler(); + + PCDUHandler(object_id_t setObjectId, size_t cmdQueueSize = 20); virtual ~PCDUHandler(); + + virtual ReturnValue_t initialize() override; + virtual ReturnValue_t performOperation(uint8_t counter) override; + virtual void handleChangedDataset(sid_t sid, store_address_t storeId = + storeId::INVALID_STORE_ADDRESS); + + virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const override; + virtual void sendFuseOnCommand(uint8_t fuseNr) const override; + virtual ReturnValue_t getSwitchState( uint8_t switchNr ) const override; + virtual ReturnValue_t getFuseState( uint8_t fuseNr ) const override; + virtual uint32_t getSwitchDelayMs(void) const override; + virtual object_id_t getObjectId() const override; + virtual LocalDataPoolManager* getHkManagerHandle() override; + + virtual MessageQueueId_t getCommandQueue() const override; + virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + virtual uint32_t getPeriodicOperationFrequency() const override; + virtual ReturnValue_t initializeAfterTaskCreation() override; + virtual void setTaskIF(PeriodicTaskIF* task_); + +private: + + uint32_t pstIntervalMs = 0; + + /** + * The dataset holding the hk table of PDU2. This dataset is a copy of the PDU2 HK dataset + * of the PDU2Handler. Each time the PDU2Handler updates his HK dataset, a copy is sent + * to this object via a HousekeepingMessage. + */ + PDU2::PDU2HkTableDataset pdu2HkTableDataset; + /** The timeStamp of the current pdu2HkTableDataset */ + CCSDSTime::CDS_short timeStamp; + + /** + * Pointer to the IPCStore. + * This caches the pointer received from the objectManager in the constructor. + */ + StorageManagerIF *IPCStore = nullptr; + + /** + * Message queue to communicate with other objetcs. Used for example to receive + * local pool messages from ACU, PDU1 and PDU2. + */ + MessageQueueIF* commandQueue = nullptr; + + size_t cmdQueueSize; + + /** Housekeeping manager. Handles updates of local pool variables. */ + LocalDataPoolManager poolManager; + + PeriodicTaskIF* executingTask = nullptr; + + void readCommandQueue(); }; #endif /* MISSION_DEVICES_PCDUHANDLER_H_ */ diff --git a/mission/devices/PDU1Handler.cpp b/mission/devices/PDU1Handler.cpp new file mode 100644 index 00000000..1df70acc --- /dev/null +++ b/mission/devices/PDU1Handler.cpp @@ -0,0 +1,25 @@ +#include "PDU1Handler.h" + +PDU1Handler::PDU1Handler(object_id_t objectId, object_id_t comIF, + CookieIF * comCookie, uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, + uint16_t hkTableSize) : GomspaceDeviceHandler(objectId, comIF, + comCookie, maxConfigTableAddress, maxHkTableAddress, hkTableSize) { +} + +PDU1Handler::~PDU1Handler() { +} + +ReturnValue_t PDU1Handler::buildNormalDeviceCommand( + DeviceCommandId_t * id) { + *id = GOMSPACE::REQUEST_HK_TABLE; + return buildCommandFromCommand(*id, NULL, 0); +} + +void PDU1Handler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) { + const uint8_t* payloadPtr = packet + GOMSPACE::GS_HDR_LENGTH; + size_t size = (size_t)hkTableSize; + hkTableDataset.deSerialize(&payloadPtr, &size, SerializeIF::Endianness::BIG); + FullTableReply fullTableReply(id, HK_TABLE_ID, hkTableDataset); + handleDeviceTM(&fullTableReply, id, true); +} + diff --git a/mission/devices/PDU1Handler.h b/mission/devices/PDU1Handler.h new file mode 100644 index 00000000..ccbd0c2c --- /dev/null +++ b/mission/devices/PDU1Handler.h @@ -0,0 +1,40 @@ +#ifndef MISSION_DEVICES_PDU1Handler_H_ +#define MISSION_DEVICES_PDU1Handler_H_ + +#include "GomspaceDeviceHandler.h" +#include + +/** + * @brief This is the device handler for the PDU1. + * + * @details The PDU1 controls the + * power supply of the following devices: + * TCS Board, 3.3V, channel 0 + * Syrlinks, 12V, channel 1 + * Star Tracker, 5V, channel 2 + * MGT, 5V, channel 3 + * SUS 1-6 Nominal, 3.3V, channel 4 + * Solar cell experiment, 5V, channel 5 + * PLOC, 12V, channel 6 + * ACS 3.3V for Side A group, channel 7 + * Unoccupied, 5V, channel 8 + */ +class PDU1Handler: public GomspaceDeviceHandler { +public: + PDU1Handler(object_id_t objectId, object_id_t comIF, + CookieIF * comCookie, uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, + uint16_t hkTableSize); + virtual ~PDU1Handler(); +protected: + /** + * @brief In MODE_NORMAL, a command will be built periodically by this function. + */ + virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + virtual void letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) override; + +private: + /** Dataset for the housekeeping table of the PDU1 */ + PDU1::PDU1HkTableDataset hkTableDataset; +}; + +#endif /* MISSION_DEVICES_PDU1Handler_H_ */ diff --git a/mission/devices/PDU2Handler.cpp b/mission/devices/PDU2Handler.cpp index 9d5e3d50..2da40d28 100644 --- a/mission/devices/PDU2Handler.cpp +++ b/mission/devices/PDU2Handler.cpp @@ -1,18 +1,99 @@ -/* - * PDU2Handler.cpp - * - * Created on: 23.01.2021 - * Author: jakob - */ - #include "PDU2Handler.h" +#include -PDU2Handler::PDU2Handler() { - // TODO Auto-generated constructor stub - +PDU2Handler::PDU2Handler(object_id_t objectId, object_id_t comIF, + CookieIF * comCookie, uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, + uint16_t hkTableSize) : GomspaceDeviceHandler(objectId, comIF, + comCookie, maxConfigTableAddress, maxHkTableAddress, hkTableSize), hkTableDataset(this) { } PDU2Handler::~PDU2Handler() { - // TODO Auto-generated destructor stub } +ReturnValue_t PDU2Handler::buildNormalDeviceCommand( + DeviceCommandId_t * id) { + *id = GOMSPACE::REQUEST_HK_TABLE; + return buildCommandFromCommand(*id, NULL, 0); +} + +void PDU2Handler::letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) { + const uint8_t* payloadPtr = packet + GOMSPACE::GS_HDR_LENGTH; + size_t size = (size_t)hkTableSize; + hkTableDataset.deSerialize(&payloadPtr, &size, SerializeIF::Endianness::BIG); + FullTableReply fullTableReply(id, HK_TABLE_ID, &hkTableDataset); + handleDeviceTM(&fullTableReply, id, true); +} + +ReturnValue_t PDU2Handler::initializeLocalDataPool( + localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_Q7S, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_RW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_SUS_REDUNDANT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_DEPLOYMENT_MECHANISM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_ACS_BOARD_SIDE_B, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CURRENT_OUT_PAYLOAD_CAMERA, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_Q7S, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_RW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_SUS_REDUNDANT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_DEPLOYMENT_MECHANISM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_ACS_BOARD_SIDE_B, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VOLTAGE_OUT_PAYLOAD_CAMERA, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_VCC, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_VBAT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_TEMPERATURE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_CONV_EN, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_Q7S, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_RW, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_SUS_REDUNDANT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_ACS_BOARD_SIDE_B, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_OUT_EN_PAYLOAD_CAMERA, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_BOOTCAUSE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_BOOTCNT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_UPTIME, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_RESETCAUSE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_BATT_MODE, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_DEVICE_0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_1, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_2, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_3, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_4, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_5, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_6, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_7, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_DEVICE_0_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_1_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_2_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_3_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_4_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_5_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_6_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_DEVICE_7_STATUS, new PoolEntry( { 0 })); + + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_GND, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_I2C, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_CAN, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CNT_CSP, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_GND_LEFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_I2C_LEFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CAN_LEFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(PDU::PDU2_WDT_CSP_LEFT, new PoolEntry( { 0 })); + + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/mission/devices/PDU2Handler.h b/mission/devices/PDU2Handler.h index 4d18000c..ec7b6f9b 100644 --- a/mission/devices/PDU2Handler.h +++ b/mission/devices/PDU2Handler.h @@ -2,6 +2,7 @@ #define MISSION_DEVICES_PDU2HANDLER_H_ #include "GomspaceDeviceHandler.h" +#include /** * @brief This is the device handler for the PDU2. @@ -11,16 +12,31 @@ * Xiphos Q7S, 8V, channel 0 * Reaction wheels 5V, channel 2 * TCS Board heater input, 8V, channel 3 - * SUS, 3,3V, channel 4 + * SUS 8-12 Redundant, 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 + * P/L PCDU, Battery voltage (Vnominal = 14.8V), 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(); + PDU2Handler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie, + uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress, uint16_t hkTableSize); virtual ~PDU2Handler(); + + virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + +protected: + /** + * @brief As soon as the device is in MODE_NORMAL, this function is executed periodically. + */ + virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id) override; + virtual void letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) override; + +private: + /** Dataset for the housekeeping table of the PDU2 */ + PDU2::PDU2HkTableDataset hkTableDataset; }; #endif /* MISSION_DEVICES_PDU2HANDLER_H_ */ diff --git a/mission/devices/Tmp1075Handler.cpp b/mission/devices/Tmp1075Handler.cpp index 7d3c2ac3..e4eb1692 100644 --- a/mission/devices/Tmp1075Handler.cpp +++ b/mission/devices/Tmp1075Handler.cpp @@ -137,10 +137,9 @@ uint32_t Tmp1075Handler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo){ return 500; } -ReturnValue_t Tmp1075Handler::initializeLocalDataPool( - LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075_1, - new PoolEntry({0.0})); - return HasReturnvaluesIF::RETURN_OK; +ReturnValue_t Tmp1075Handler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) { + localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075_1, new PoolEntry( { 0.0 })); + return HasReturnvaluesIF::RETURN_OK; } diff --git a/mission/devices/Tmp1075Handler.h b/mission/devices/Tmp1075Handler.h index ff73fa5f..190ac47f 100644 --- a/mission/devices/Tmp1075Handler.h +++ b/mission/devices/Tmp1075Handler.h @@ -36,8 +36,8 @@ protected: const uint8_t *packet) override; void setNormalDatapoolEntriesInvalid() override; uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; - ReturnValue_t initializeLocalDataPool(LocalDataPool &localDataPoolMap, - LocalDataPoolManager &poolManager) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; private: diff --git a/mission/devices/devicedefinitions/GomSpacePackets.h b/mission/devices/devicedefinitions/GomSpacePackets.h index b086ef5b..7c4d0cf7 100644 --- a/mission/devices/devicedefinitions/GomSpacePackets.h +++ b/mission/devices/devicedefinitions/GomSpacePackets.h @@ -5,16 +5,7 @@ #include #include #include - -namespace GOMSPACE{ - static const uint16_t IGNORE_CHECKSUM = 0xbb0; - /* CSP port to ping gomspace devices. */ - static const uint8_t PING_PORT = 1; - static const uint8_t REBOOT_PORT = 4; - /* CSP port of gomspace devices to request or set parameters */ - static const uint8_t PARAM_PORT = 7; - static const uint8_t P60_PORT_GNDWDT_RESET = 9; -} +#include /** @@ -92,8 +83,6 @@ private: class CspSetParamCommand : public SerialLinkedListAdapter { public: - static const uint8_t GS_HDR_LENGTH = 12; - CspSetParamCommand(uint16_t querySize_, uint16_t payloadlength_, uint16_t checksum_, uint16_t seq_, uint16_t total_, uint16_t addr_, const uint8_t* parameter_, uint8_t parameterCount_) : @@ -178,7 +167,6 @@ private: * device*/ SerializeElement action = 0x00; // get param SerializeElement tableId; - /* Size of address. Set to 0 to get full table */ SerializeElement addresslength; SerializeElement checksum; SerializeElement seq; @@ -187,14 +175,55 @@ private: }; +/** + * @brief This class can be used to generate a get param command for the + * gomspace devices which will be sent to the device communication + * interface object. + * + * @note cspPort and querySize only serve as information for the CspComIF + * and will not be transmitted physically to the target device. + */ +class RequestFullTableCommand : public SerialLinkedListAdapter { +public: + + RequestFullTableCommand(uint16_t querySize_, uint8_t tableId) : + querySize(querySize_), tableId(tableId_) { + setLinks(); + } + +private: + RequestFullTableCommand(const RequestFullTableCommand &command); + void setLinks() { + setStart(&cspPort); + cspPort.setNext(&querySize); + querySize.setNext(&action); + action.setNext(&tableId); + tableId.setNext(&addresslength); + addresslength.setNext(&checksum); + checksum.setNext(&seq); + seq.setNext(&total); + } + SerializeElement cspPort = GOMSPACE::PARAM_PORT; + /** Size of bytes to query (size of csp header + size of table) */ + SerializeElement querySize; + /* Following information will also be physically transmitted to the target + * device*/ + SerializeElement action = 0x00; // get param + SerializeElement tableId; + /* Size of address. Set to 0 to get full table */ + SerializeElement addresslength = 0; + SerializeElement checksum = GOMSPACE::IGNORE_CHECKSUM; + SerializeElement seq = 0; + SerializeElement total = 0; +}; + + /** * @brief This class can be used to deserialize replies from gomspace devices * and extract the relevant data. */ class CspGetParamReply : public SerialLinkedListAdapter { public: - /* The size of the header of a gomspace CSP packet. */ - static const uint8_t GS_HDR_LENGTH = 12; /** * @brief Constructor * @@ -285,6 +314,38 @@ private: SerializeElement> payload; }; + +/** + * @brief This class generates the reply containing data from a full table request. + */ +class FullTableReply : public SerialLinkedListAdapter { +public: + /** + * @brief Constructor + * + * @param action_ The command which triggers the full table request. + * @param tableId_ The id of the requested table. + * @param tableDataset_ Pointer to the dataset holding the table data. + */ + FullTableReply(uint8_t action_, uint8_t tableId_, LocalPoolDataSetBase* tableDataset_) : + action(action_), tableId(tableId_), tableDataset(*tableDataset_) { + setLinks(); + } + +private: + FullTableReply(const FullTableReply &reply); + void setLinks() { + setStart(&action); + action.setNext(&tableId); + tableId.setNext(&tableLength); + tableLength.setNext(&tableDataset); + } + SerializeElement action; + SerializeElement tableId; + SerializeElement tableDataset; +}; + + /** * @brief This class helps to unpack information from an action message * to set a parameter in gomspace devices. The action message can be @@ -322,6 +383,46 @@ private: }; +/** + * @brief This class generates a message which can be sent to the GomspaceDeviceHandler to + * command a parameter change. + * + * @details Structure of set parameter command: + * | memory address | size of parameter value | parameter value | + */ +class GomspaceSetParamMessage : public SerialLinkedListAdapter { +public: + + /* The size of the largest parameter */ + static const uint32_t MAX_SIZE = 4; + + /** + * @brief Constructor + * + * @param memoryAddress The address of the parameter to change in the configuration table. + * @param parameterValue Pointer to the parameter value to set. + * @param parameterSize The size of the parameter. + * + */ + GomspaceSetParamMessage(uint16_t memoryAddress, uint8_t* parameterValue, uint8_t parameterSize) : + memoryAddress(memoryAddress) { + const uint8_t** buffer; + *buffer = parameterValue; + parameterInfo.deserialize(buffer, parameterSize, SerializeIF::Endianness::BIG); + setLinks(); + } + +private: + GomspaceSetParamMessage(const FullTableReply &reply); + void setLinks() { + setStart(&memoryAddress); + memoryAddress.setNext(¶meter); + } + SerializeElement memoryAddress; + SerializeElement> parameterValueInfo; +}; + + /** * @brief This class helps to unpack information from an action message * to get a parameter from gomspace devices. The action message can be diff --git a/mission/devices/devicedefinitions/GomspaceDefinitions.h b/mission/devices/devicedefinitions/GomspaceDefinitions.h index a0c0cacd..2986c5ae 100644 --- a/mission/devices/devicedefinitions/GomspaceDefinitions.h +++ b/mission/devices/devicedefinitions/GomspaceDefinitions.h @@ -9,8 +9,34 @@ #ifndef MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_ #define MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_ +#include +#include +#include +#include -namespace P60Dock{ +namespace GOMSPACE{ + static const uint16_t IGNORE_CHECKSUM = 0xbb0; + /** The size of the header of a gomspace CSP packet. */ + static const uint8_t GS_HDR_LENGTH = 12; + /** CSP port to ping gomspace devices. */ + static const uint8_t PING_PORT = 1; + static const uint8_t REBOOT_PORT = 4; + /** CSP port of gomspace devices to request or set parameters */ + static const uint8_t PARAM_PORT = 7; + static const uint8_t P60_PORT_GNDWDT_RESET = 9; + + /* Device commands are derived from the rparam.h of the gomspace lib */ + static const DeviceCommandId_t PING = 0x1; //!< [EXPORT] : [COMMAND] + static const DeviceCommandId_t NONE = 0x2; // Set when no command is pending + static const DeviceCommandId_t REBOOT = 0x4; //!< [EXPORT] : [COMMAND] + static const DeviceCommandId_t GNDWDT_RESET = 0x9; //!< [EXPORT] : [COMMAND] + static const DeviceCommandId_t PARAM_GET = 0x00; //!< [EXPORT] : [COMMAND] + static const DeviceCommandId_t PARAM_SET = 0xFF; //!< [EXPORT] : [COMMAND] + static const DeviceCommandId_t REQUEST_HK_TABLE = 0x10; //!< [EXPORT] : [COMMAND] +} + + +namespace P60Dock { /* The maximum size of a reply from the P60 dock. Maximum size is reached * when retrieving the full parameter configuration table. 412 bytes of * payload data and 12 bytes of CSP header data. */ @@ -18,22 +44,509 @@ namespace P60Dock{ static const uint16_t MAX_CONFIGTABLE_ADDRESS = 408; static const uint16_t MAX_HKTABLE_ADDRESS = 187; + static const uint16_t HK_TABLE_SIZE = 188; } +/** + * @brief Constants common for both PDU1 and PDU2. + */ namespace PDU{ /* When retrieving full configuration parameter table */ static const uint16_t MAX_REPLY_LENGTH = 318; static const uint16_t MAX_CONFIGTABLE_ADDRESS = 316; static const uint16_t MAX_HKTABLE_ADDRESS = 140; + static const uint16_t HK_TABLE_SIZE = 145; + static const uint8_t HK_TABLE_ENTRIES = 60; + + enum PDUPoolIds: lp_id_t { + PDU1_CURRENT_OUT_TCS_BOARD_3V3, + PDU1_CURRENT_OUT_SYRLINKS, + PDU1_CURRENT_OUT_STAR_TRACKER, + PDU1_CURRENT_OUT_MGT, + PDU1_CURRENT_OUT_SUS_NOMINAL, + PDU1_CURRENT_OUT_SOLAR_CELL_EXP, + PDU1_CURRENT_OUT_PLOC, + PDU1_CURRENT_OUT_ACS_BOARD_SIDE_A, + PDU1_CURRENT_OUT_CHANNEL8, + PDU1_VOLTAGE_OUT_TCS_BOARD_3V3, + PDU1_VOLTAGE_OUT_SYRLINKS, + PDU1_VOLTAGE_OUT_STAR_TRACKER, + PDU1_VOLTAGE_OUT_MGT, + PDU1_VOLTAGE_OUT_SUS_NOMINAL, + PDU1_VOLTAGE_OUT_SOLAR_CELL_EXP, + PDU1_VOLTAGE_OUT_PLOC, + PDU1_VOLTAGE_OUT_ACS_BOARD_SIDE_A, + PDU1_VOLTAGE_OUT_CHANNEL8, + PDU1_VCC, + PDU1_VBAT, + PDU1_TEMPERATURE, + PDU1_CONV_EN, + PDU1_OUT_EN_TCS_BOARD_3V3, + PDU1_OUT_EN_SYRLINKS, + PDU1_OUT_EN_STAR_TRACKER, + PDU1_OUT_EN_MGT, + PDU1_OUT_EN_SUS_NOMINAL, + PDU1_OUT_EN_SOLAR_CELL_EXP, + PDU1_OUT_EN_PLOC, + PDU1_OUT_EN_ACS_BOARD_SIDE_A, + PDU1_OUT_EN_CHANNEL8, + PDU1_BOOTCAUSE, + PDU1_BOOTCNT, + PDU1_UPTIME, + PDU1_RESETCAUSE, + PDU1_BATT_MODE, + PDU1_LATCHUP, + PDU1_DEVICE_0, + PDU1_DEVICE_1, + PDU1_DEVICE_2, + PDU1_DEVICE_3, + PDU1_DEVICE_4, + PDU1_DEVICE_5, + PDU1_DEVICE_6, + PDU1_DEVICE_7, + PDU1_DEVICE_0_STATUS, + PDU1_DEVICE_1_STATUS, + PDU1_DEVICE_2_STATUS, + PDU1_DEVICE_3_STATUS, + PDU1_DEVICE_4_STATUS, + PDU1_DEVICE_5_STATUS, + PDU1_DEVICE_6_STATUS, + PDU1_DEVICE_7_STATUS, + PDU1_WDT_CNT_GND, + PDU1_WDT_CNT_I2C, + PDU1_WDT_CNT_CAN, + PDU1_WDT_CNT_CSP, + PDU1_WDT_GND_LEFT, + PDU1_WDT_I2C_LEFT, + PDU1_WDT_CAN_LEFT, + PDU1_WDT_CSP_LEFT, + + PDU2_CURRENT_OUT_Q7S, + PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH1, + PDU2_CURRENT_OUT_RW, + PDU2_CURRENT_OUT_TCS_BOARD_HEATER_IN, + PDU2_CURRENT_OUT_SUS_REDUNDANT, + PDU2_CURRENT_OUT_DEPLOYMENT_MECHANISM, + PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH6, + PDU2_CURRENT_OUT_ACS_BOARD_SIDE_B, + PDU2_CURRENT_OUT_PAYLOAD_CAMERA, + PDU2_VOLTAGE_OUT_Q7S, + PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH1, + PDU2_VOLTAGE_OUT_RW, + PDU2_VOLTAGE_OUT_TCS_BOARD_HEATER_IN, + PDU2_VOLTAGE_OUT_SUS_REDUNDANT, + PDU2_VOLTAGE_OUT_DEPLOYMENT_MECHANISM, + PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH6, + PDU2_VOLTAGE_OUT_ACS_BOARD_SIDE_B, + PDU2_VOLTAGE_OUT_PAYLOAD_CAMERA, + PDU2_VCC, + PDU2_VBAT, + PDU2_TEMPERATURE, + PDU2_CONV_EN, + PDU2_OUT_EN_Q7S, + PDU2_OUT_EN_PAYLOAD_PCDU_CH1, + PDU2_OUT_EN_RW, + PDU2_OUT_EN_TCS_BOARD_HEATER_IN, + PDU2_OUT_EN_SUS_REDUNDANT, + PDU2_OUT_EN_DEPLOYMENT_MECHANISM, + PDU2_OUT_EN_PAYLOAD_PCDU_CH6, + PDU2_OUT_EN_ACS_BOARD_SIDE_B, + PDU2_OUT_EN_PAYLOAD_CAMERA, + PDU2_BOOTCAUSE, + PDU2_BOOTCNT, + PDU2_UPTIME, + PDU2_RESETCAUSE, + PDU2_BATT_MODE, + PDU2_LATCHUP, + PDU2_DEVICE_0, + PDU2_DEVICE_1, + PDU2_DEVICE_2, + PDU2_DEVICE_3, + PDU2_DEVICE_4, + PDU2_DEVICE_5, + PDU2_DEVICE_6, + PDU2_DEVICE_7, + PDU2_DEVICE_0_STATUS, + PDU2_DEVICE_1_STATUS, + PDU2_DEVICE_2_STATUS, + PDU2_DEVICE_3_STATUS, + PDU2_DEVICE_4_STATUS, + PDU2_DEVICE_5_STATUS, + PDU2_DEVICE_6_STATUS, + PDU2_DEVICE_7_STATUS, + PDU2_WDT_CNT_GND, + PDU2_WDT_CNT_I2C, + PDU2_WDT_CNT_CAN, + PDU2_WDT_CNT_CSP, + PDU2_WDT_GND_LEFT, + PDU2_WDT_I2C_LEFT, + PDU2_WDT_CAN_LEFT, + PDU2_WDT_CSP_LEFT + }; } -namespace ACU{ - /* When receiving full houskeeping (telemetry) table */ +namespace PDU1 { + static const uint32_t HK_TABLE_DATA_SET_ID = 0x1; // hk table has table id 4 + /** + * Addresses within configuration table to enable or disable output channels. Refer also to + * gs-man-nanopower-p60-pdu-200.pdf on page 16. + */ + static const uint16_t CONFIG_ADDRESS_OUT_EN_TCS_BOARD_3V3 = 0x48; + static const uint16_t CONFIG_ADDRESS_OUT_EN_SYRLINKS = 0x49; + static const uint16_t CONFIG_ADDRESS_OUT_EN_STAR_TRACKER = 0x50; + static const uint16_t CONFIG_ADDRESS_OUT_EN_MGT = 0x51; + static const uint16_t CONFIG_ADDRESS_OUT_EN_SUS_NOMINAL = 0x52; + static const uint16_t CONFIG_ADDRESS_OUT_EN_SOLAR_CELL_EXP = 0x53; + static const uint16_t CONFIG_ADDRESS_OUT_EN_PLOC = 0x54; + static const uint16_t CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_A = 0x55; + static const uint16_t CONFIG_ADDRESS_OUT_EN_CHANNEL8 = 0x56; + + /** + * @brief This class defines a dataset for the hk table of the PDU1. + */ + class PDU1HkTableDataset : + public StaticLocalDataSet { + public: + + PDU1HkTableDataset(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, PDU1::HK_TABLE_DATA_SET_ID) { + } + + PDU1HkTableDataset(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, PDU1::HK_TABLE_DATA_SET_ID)) { + } + + /** Measured output currents */ + lp_var_t currentOutTCSBoard3V3 = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_TCS_BOARD_3V3, this); + lp_var_t currentOutSyrlinks = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_SYRLINKS, this); + lp_var_t currentOutStarTracker = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_STAR_TRACKER, this); + lp_var_t currentOutMGT = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_MGT, this); + lp_var_t currentOutSUSNominal = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_SUS_NOMINAL, this); + lp_var_t currentOutSolarCellExp = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_SOLAR_CELL_EXP, this); + lp_var_t currentOutPLOC = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_PLOC, this); + lp_var_t currentOutACSBoardSideA = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_ACS_BOARD_SIDE_A, this); + lp_var_t currentOutChannel8 = lp_var_t(sid.objectId, + PDU::PDU1_CURRENT_OUT_CHANNEL8, this); + /** Measured voltage of output channels */ + lp_var_t voltageOutTCSBoard3V3 = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_TCS_BOARD_3V3, this); + lp_var_t voltageOutSyrlinks = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_SYRLINKS, this); + lp_var_t voltageOutStarTracker = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_STAR_TRACKER, this); + lp_var_t voltageOutMGT = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_MGT, this); + lp_var_t voltageOutSUSNominal = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_SUS_NOMINAL, this); + lp_var_t voltageOutSolarCellExp = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_SOLAR_CELL_EXP, this); + lp_var_t voltageOutPLOC = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_PLOC, this); + lp_var_t voltageOutACSBoardSideA = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_ACS_BOARD_SIDE_A, this); + lp_var_t voltageOutChannel8 = lp_var_t(sid.objectId, + PDU::PDU1_VOLTAGE_OUT_CHANNEL8, this); + /** Measured VCC */ + lp_var_t vcc = lp_var_t(sid.objectId, + PDU::PDU1_VCC, this); + /** Measured VBAT */ + lp_var_t vbat = lp_var_t(sid.objectId, + PDU::PDU1_VBAT, this); + lp_var_t temperature = lp_var_t(sid.objectId, + PDU::PDU1_TEMPERATURE, this); + /** Output converter enable status */ + lp_var_t converterEnable = lp_var_t(sid.objectId, + PDU::PDU1_CONV_EN, this); + /** Output channels enable status */ + lp_var_t outEnabledTCSBoard3V3 = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_TCS_BOARD_3V3, this); + lp_var_t outEnabledSyrlinks = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_SYRLINKS, this); + lp_var_t outEnabledStarTracker = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_STAR_TRACKER, this); + lp_var_t outEnabledMGT = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_MGT, this); + lp_var_t outEnabledSUSNominal = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_SUS_NOMINAL, this); + lp_var_t outEnabledSolarCellExp = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_SOLAR_CELL_EXP, this); + lp_var_t outEnabledPLOC = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_PLOC, this); + lp_var_t outEnabledAcsBoardSideA = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_ACS_BOARD_SIDE_A, this); + lp_var_t outEnabledChannel8 = lp_var_t(sid.objectId, + PDU::PDU1_OUT_EN_CHANNEL8, this); + lp_var_t bootcause = lp_var_t(sid.objectId, + PDU::PDU1_BOOTCAUSE, this); + /** Number of reboots */ + lp_var_t bootcount = lp_var_t(sid.objectId, + PDU::PDU1_BOOTCNT, this); + /** Uptime in seconds */ + lp_var_t uptime = lp_var_t(sid.objectId, + PDU::PDU1_UPTIME, this); + lp_var_t resetcause = lp_var_t(sid.objectId, + PDU::PDU1_RESETCAUSE, this); + /** Battery mode: 1 = Critical, 2 = Safe, 3 = Normal, 4 = Full */ + lp_var_t battMode = lp_var_t(sid.objectId, + PDU::PDU1_BATT_MODE, this); + /** + * There are 8 devices on the PDU. FRAM, ADCs, temperature sensor etc. Each device is + * identified by an ID. Refer also to gs-man-nanopower-p60-pdu-200-1.pdf on pages 17 and 18. + */ + lp_var_t device0 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_0, this); + lp_var_t device1 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_1, this); + lp_var_t device2 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_2, this); + lp_var_t device3 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_3, this); + lp_var_t device4 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_4, this); + lp_var_t device5 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_5, this); + lp_var_t device6 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_6, this); + lp_var_t device7 = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_7, this); + /** The status of each device. 0 = None, 1 = Ok, 2 = Error, 3 = Not found */ + lp_var_t device0Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_0_STATUS, this); + lp_var_t device1Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_1_STATUS, this); + lp_var_t device2Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_2_STATUS, this); + lp_var_t device3Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_3_STATUS, this); + lp_var_t device4Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_4_STATUS, this); + lp_var_t device5Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_5_STATUS, this); + lp_var_t device6Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_6_STATUS, this); + lp_var_t device7Status = lp_var_t(sid.objectId, + PDU::PDU1_DEVICE_7_STATUS, this); + /** Number of reboots triggered by the ground watchdog */ + lp_var_t gndWdtReboots = lp_var_t(sid.objectId, + PDU::PDU1_WDT_CNT_GND, this); + /** Number of reboots triggered through the I2C watchdog. Not relevant for EIVE. */ + lp_var_t i2cWdtReboots = lp_var_t(sid.objectId, + PDU::PDU1_WDT_CNT_I2C, this); + /** Number of reboots triggered through the CAN watchdog */ + lp_var_t canWdtReboots = lp_var_t(sid.objectId, + PDU::PDU1_WDT_CNT_CAN, this); + /** Number of reboots triggered through the CSP watchdog */ + lp_var_t cspWdtReboots = lp_var_t(sid.objectId, + PDU::PDU1_WDT_CNT_CSP, this); + /** Ground watchdog remaining seconds before rebooting */ + lp_var_t groundWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU1_WDT_GND_LEFT, this); + /** I2C watchdog remaining seconds before rebooting. Not relevant for EIVE. */ + lp_var_t i2cWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU1_WDT_I2C_LEFT, this); + /** CAN watchdog remaining seconds before rebooting. */ + lp_var_t canWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU1_WDT_CAN_LEFT, this); + /** CSP watchdog remaining seconds before rebooting. */ + lp_var_t cspWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU1_WDT_CSP_LEFT, this); + }; +} + + +namespace PDU2 { + static const uint32_t HK_TABLE_DATA_SET_ID = 0x2; + /** + * Addresses within configuration table to enable or disable output channels. Refer also to + * gs-man-nanopower-p60-pdu-200.pdf on page 16. + */ + static const uint16_t CONFIG_ADDRESS_OUT_EN_Q7S = 0x48; + static const uint16_t CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH1 = 0x49; + static const uint16_t CONFIG_ADDRESS_OUT_EN_RW = 0x50; + static const uint16_t CONFIG_ADDRESS_OUT_EN_TCS_BOARD_HEATER_IN = 0x51; + static const uint16_t CONFIG_ADDRESS_OUT_EN_SUS_REDUNDANT = 0x52; + static const uint16_t CONFIG_ADDRESS_OUT_EN_DEPLOYMENT_MECHANISM = 0x53; + static const uint16_t CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6PLOC = 0x54; + static const uint16_t CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_B = 0x55; + static const uint16_t CONFIG_ADDRESS_OUT_EN_PAYLOAD_CAMERA = 0x56; + + /** + * @brief This class defines a dataset for the hk table of the PDU2. + */ + class PDU2HkTableDataset: + public StaticLocalDataSet { + public: + + PDU2HkTableDataset(HasLocalDataPoolIF* owner): + StaticLocalDataSet(owner, PDU2::HK_TABLE_DATA_SET_ID) { + } + + PDU2HkTableDataset(object_id_t objectId): + StaticLocalDataSet(sid_t(objectId, PDU2::HK_TABLE_DATA_SET_ID)) { + } + + /** Measured output currents */ + lp_var_t currentOutQ7S = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_Q7S, this); + lp_var_t currentOutPayloadPCDUCh1 = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH1, this); + lp_var_t currentOutReactionWheels = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_RW, this); + lp_var_t currentOutTCSBoardHeaterIn = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_TCS_BOARD_HEATER_IN, this); + lp_var_t currentOutSUSRedundant = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_SUS_REDUNDANT, this); + lp_var_t currentOutDeplMechanism = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_DEPLOYMENT_MECHANISM, this); + lp_var_t currentOutPayloadPCDUCh6 = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH6, this); + lp_var_t currentOutACSBoard = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_ACS_BOARD_SIDE_B, this); + lp_var_t currentOutPayloadCamera = lp_var_t(sid.objectId, + PDU::PDU2_CURRENT_OUT_PAYLOAD_CAMERA, this); + /** Measured voltage of output channels */ + lp_var_t voltageOutQ7S = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_Q7S, this); + lp_var_t voltageOutPayloadPCDUCh1 = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH1, this); + lp_var_t voltageOutReactionWheels = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_RW, this); + lp_var_t voltageOutTCSBoardHeaterIn = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_TCS_BOARD_HEATER_IN, this); + lp_var_t voltageOutSUS = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_SUS_REDUNDANT, this); + lp_var_t voltageOutDeplMechanism = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_DEPLOYMENT_MECHANISM, this); + lp_var_t voltageOutPayloadPCDUCh6 = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_PAYLOAD_PCDU_CH6, this); + lp_var_t voltageOutACSBoard = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_ACS_BOARD_SIDE_B, this); + lp_var_t voltageOutPayloadCamera = lp_var_t(sid.objectId, + PDU::PDU2_VOLTAGE_OUT_PAYLOAD_CAMERA, this); + /** Measured VCC */ + lp_var_t vcc = lp_var_t(sid.objectId, + PDU::PDU2_VCC, this); + /** Measured VBAT */ + lp_var_t vbat = lp_var_t(sid.objectId, + PDU::PDU2_VBAT, this); + lp_var_t temperature = lp_var_t(sid.objectId, + PDU::PDU2_TEMPERATURE, this); + /** Output converter enable status */ + lp_var_t converterEnable = lp_var_t(sid.objectId, + PDU::PDU2_CONV_EN, this); + /** Output channels enable status */ + lp_var_t outEnabledQ7S = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_Q7S, this); + lp_var_t outEnabledPlPCDUCh1 = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, this); + lp_var_t outEnabledReactionWheels = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_RW, this); + lp_var_t outEnabledTCSBoardHeaterIn = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, this); + lp_var_t outEnabledSUS = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_SUS_REDUNDANT, this); + lp_var_t outEnabledDeplMechanism = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, this); + lp_var_t outEnabledPlPCDUCh6 = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, this); + lp_var_t outEnabledAcsBoard = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_ACS_BOARD_SIDE_B, this); + lp_var_t outEnabledPayloadCamera = lp_var_t(sid.objectId, + PDU::PDU2_OUT_EN_PAYLOAD_CAMERA, this); + lp_var_t bootcause = lp_var_t(sid.objectId, + PDU::PDU2_BOOTCAUSE, this); + /** Number of reboots */ + lp_var_t bootcount = lp_var_t(sid.objectId, + PDU::PDU2_BOOTCNT, this); + /** Uptime in seconds */ + lp_var_t uptime = lp_var_t(sid.objectId, + PDU::PDU2_UPTIME, this); + lp_var_t resetcause = lp_var_t(sid.objectId, + PDU::PDU2_RESETCAUSE, this); + /** Battery mode: 1 = Critical, 2 = Safe, 3 = Normal, 4 = Full */ + lp_var_t battMode = lp_var_t(sid.objectId, + PDU::PDU2_BATT_MODE, this); + /** + * There are 8 devices on the PDU. FRAM, ADCs, temperature sensor etc. Each device is + * identified by an ID. Refer also to gs-man-nanopower-p60-pdu-200-1.pdf on pages 17 and 18. + */ + lp_var_t device0 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_0, this); + lp_var_t device1 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_1, this); + lp_var_t device2 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_2, this); + lp_var_t device3 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_3, this); + lp_var_t device4 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_4, this); + lp_var_t device5 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_5, this); + lp_var_t device6 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_6, this); + lp_var_t device7 = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_7, this); + /** The status of each device. 0 = None, 1 = Ok, 2 = Error, 3 = Not found */ + lp_var_t device0Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_0_STATUS, this); + lp_var_t device1Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_1_STATUS, this); + lp_var_t device2Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_2_STATUS, this); + lp_var_t device3Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_3_STATUS, this); + lp_var_t device4Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_4_STATUS, this); + lp_var_t device5Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_5_STATUS, this); + lp_var_t device6Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_6_STATUS, this); + lp_var_t device7Status = lp_var_t(sid.objectId, + PDU::PDU2_DEVICE_7_STATUS, this); + /** Number of reboots triggered by the ground watchdog */ + lp_var_t gndWdtReboots = lp_var_t(sid.objectId, + PDU::PDU2_WDT_CNT_GND, this); + /** Number of reboots triggered through the I2C watchdog. Not relevant for EIVE. */ + lp_var_t i2cWdtReboots = lp_var_t(sid.objectId, + PDU::PDU2_WDT_CNT_I2C, this); + /** Number of reboots triggered through the CAN watchdog */ + lp_var_t canWdtReboots = lp_var_t(sid.objectId, + PDU::PDU2_WDT_CNT_CAN, this); + /** Number of reboots triggered through the CSP watchdog */ + lp_var_t cspWdtReboots = lp_var_t(sid.objectId, + PDU::PDU2_WDT_CNT_CSP, this); + /** Ground watchdog remaining seconds before rebooting */ + lp_var_t groundWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU2_WDT_GND_LEFT, this); + /** I2C watchdog remaining seconds before rebooting. Not relevant for EIVE. */ + lp_var_t i2cWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU2_WDT_I2C_LEFT, this); + /** CAN watchdog remaining seconds before rebooting. */ + lp_var_t canWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU2_WDT_CAN_LEFT, this); + /** CSP watchdog remaining seconds before rebooting. */ + lp_var_t cspWatchdogSecondsLeft = lp_var_t(sid.objectId, + PDU::PDU2_WDT_CSP_LEFT, this); + }; +} + + +namespace ACU { + /* When receiving full housekeeping (telemetry) table */ static const uint16_t MAX_REPLY_LENGTH = 124; static const uint16_t MAX_CONFIGTABLE_ADDRESS = 26; static const uint16_t MAX_HKTABLE_ADDRESS = 120; + static const uint16_t HK_TABLE_SIZE = 125; } #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_GOMSPACEDEFINITIONS_H_ */