diff --git a/CMakeLists.txt b/CMakeLists.txt index 22e45134..5107b573 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ set(TEST_PATH test/testtasks) set(LINUX_PATH linux) set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF) -set(ADD_LINUX_FILES FALSE) +set(ADD_LINUX_FILES TRUE) # Analyse different OS and architecture/target options, determine BSP_PATH, # display information about compiler etc. diff --git a/bsp_q7s/ObjectFactory.cpp b/bsp_q7s/ObjectFactory.cpp index aae12b34..a97118f9 100644 --- a/bsp_q7s/ObjectFactory.cpp +++ b/bsp_q7s/ObjectFactory.cpp @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -33,6 +35,8 @@ #include #include #include +#include +#include #if TEST_LIBGPIOD == 1 #include "LibgpiodTest.h" @@ -75,6 +79,7 @@ void ObjectFactory::produce(){ /* Communication interfaces */ new CspComIF(objects::CSP_COM_IF); new I2cComIF(objects::I2C_COM_IF); + new UartComIF(objects::UART_COM_IF); #if TE0720 == 0 CspCookie* p60DockCspCookie = new CspCookie(P60Dock::MAX_REPLY_LENGTH, @@ -168,6 +173,14 @@ void ObjectFactory::produce(){ new SolarArrayDeploymentHandler(objects::SOLAR_ARRAY_DEPL_HANDLER, objects::GPIO_IF, solarArrayDeplCookie, objects::PCDU_HANDLER, pcduSwitches::DEPLOYMENT_MECHANISM, gpioIds::DEPLSA1, gpioIds::DEPLSA2, 1000); + + UartCookie* syrlinksUartCookie = new UartCookie( + std::string("/dev/ttyPS1"), 38400, SYRLINKS::MAX_REPLY_SIZE); + syrlinksUartCookie->setParityEven(); + + SyrlinksHkHandler* syrlinksHkHandler = new SyrlinksHkHandler(objects::SYRLINKS_HK_HANDLER, objects::UART_COM_IF, syrlinksUartCookie); + syrlinksHkHandler->setModeNormal(); + #endif new TmTcUnixUdpBridge(objects::UDP_BRIDGE, diff --git a/fsfwconfig/objects/systemObjectList.h b/fsfwconfig/objects/systemObjectList.h index 153b3155..f05a5f6a 100644 --- a/fsfwconfig/objects/systemObjectList.h +++ b/fsfwconfig/objects/systemObjectList.h @@ -30,6 +30,7 @@ namespace objects { ARDUINO_COM_IF = 0x49000001, CSP_COM_IF = 0x49000002, I2C_COM_IF = 0x49000003, + UART_COM_IF = 0x49000004, /* 0x47 ('G') for Gpio Interfaces */ GPIO_IF = 0x47000001, @@ -41,10 +42,11 @@ namespace objects { ACU_HANDLER = 0x44000004, TMP1075_HANDLER_1 = 0x44000005, TMP1075_HANDLER_2 = 0x44000006, - /* Custom device handler */ PCDU_HANDLER = 0x44000007, + /* Custom device handler */ SOLAR_ARRAY_DEPL_HANDLER = 0x44000008, + SYRLINKS_HK_HANDLER = 0x44000009, /* 0x54 ('T') for thermal objects */ HEATER_HANDLER = 0x54000003, diff --git a/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp b/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp index d6f922dd..f098800f 100644 --- a/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp +++ b/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp @@ -20,15 +20,19 @@ ReturnValue_t pst::pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence) 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::SYRLINKS_HK_HANDLER, 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::SYRLINKS_HK_HANDLER, 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::SYRLINKS_HK_HANDLER, 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::SYRLINKS_HK_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { return HasReturnvaluesIF::RETURN_OK; diff --git a/libcsp/src/drivers/can/can_socketcan.c b/libcsp/src/drivers/can/can_socketcan.c index d6d6b9e1..94c6bdde 100644 --- a/libcsp/src/drivers/can/can_socketcan.c +++ b/libcsp/src/drivers/can/can_socketcan.c @@ -95,12 +95,6 @@ static void * socketcan_rx_thread(void * parameters) /* Strip flags */ frame.can_id &= CAN_EFF_MASK; - printf("socketcan_rx_thread: CAN bytes received: "); - /* Print received data */ - for (int i = 0; i < 8; i++) { - printf("%x, ", frame.data[i]); - } - /* Call RX callbacsp_can_rx_frameck */ csp_can_rx(&socketcan[0].interface, frame.can_id, frame.data, frame.can_dlc, NULL); } diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 9a25fdff..da75446a 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -2,4 +2,5 @@ add_subdirectory(gpio) add_subdirectory(i2c) add_subdirectory(csp) add_subdirectory(spi) +add_subdirectory(uart) diff --git a/linux/i2c/I2cComIF.cpp b/linux/i2c/I2cComIF.cpp index 2f1d710a..5b11f231 100644 --- a/linux/i2c/I2cComIF.cpp +++ b/linux/i2c/I2cComIF.cpp @@ -40,7 +40,7 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF * cookie) { sif::error << "I2cComIF::initializeInterface: Failed to insert " << "device with address " << i2cAddress << "to I2C device " << "map" << std::endl; - return HasReturnvaluesIF::RETURN_OK; + return HasReturnvaluesIF::RETURN_FAILED; } } else { @@ -48,11 +48,6 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF * cookie) { << "already in use" << std::endl; } - i2cDeviceMapIter = i2cDeviceMap.find(i2cAddress); - if(i2cDeviceMapIter == i2cDeviceMap.end()) { - sif::error << "Failure" << std::endl; - } - return HasReturnvaluesIF::RETURN_OK; } diff --git a/linux/i2c/I2cCookie.h b/linux/i2c/I2cCookie.h index f03d6290..483ed19c 100644 --- a/linux/i2c/I2cCookie.h +++ b/linux/i2c/I2cCookie.h @@ -15,8 +15,9 @@ public: /** * @brief Constructor for the I2C cookie. * @param i2cAddress_ The i2c address of the target device. - * @param maxReplyLen The maximum expected length of a reply from the + * @param maxReplyLen_ The maximum expected length of a reply from the * target device. + * @param devicFile_ The device file specifying the i2c interface to use. E.g. "/dev/i2c-0". */ I2cCookie(address_t i2cAddress_, size_t maxReplyLen_, std::string deviceFile_); diff --git a/linux/uart/CMakeLists.txt b/linux/uart/CMakeLists.txt new file mode 100644 index 00000000..7b503d02 --- /dev/null +++ b/linux/uart/CMakeLists.txt @@ -0,0 +1,8 @@ +target_sources(${TARGET_NAME} PUBLIC + UartComIF.cpp + UartCookie.cpp +) + + + + diff --git a/linux/uart/UartComIF.cpp b/linux/uart/UartComIF.cpp new file mode 100644 index 00000000..79470a45 --- /dev/null +++ b/linux/uart/UartComIF.cpp @@ -0,0 +1,368 @@ +#include "UartComIF.h" + +#include +#include + +#include +#include +#include +#include + +UartComIF::UartComIF(object_id_t objectId): SystemObject(objectId){ +} + +UartComIF::~UartComIF() {} + +ReturnValue_t UartComIF::initializeInterface(CookieIF * cookie) { + + std::string deviceFile; + UartDeviceMapIter uartDeviceMapIter; + + if(cookie == nullptr) { + return NULLPOINTER; + } + + UartCookie* uartCookie = dynamic_cast(cookie); + if (uartCookie == nullptr) { + sif::error << "UartComIF::initializeInterface: Invalid UART Cookie!" << std::endl; + return NULLPOINTER; + } + + deviceFile = uartCookie->getDeviceFile(); + + uartDeviceMapIter = uartDeviceMap.find(deviceFile); + if(uartDeviceMapIter == uartDeviceMap.end()) { + int fileDescriptor = configureUartPort(uartCookie); + if (fileDescriptor < 0) { + return RETURN_FAILED; + } + size_t maxReplyLen = uartCookie->getMaxReplyLen(); + UartElements_t uartElements = {fileDescriptor, std::vector(maxReplyLen), 0}; + std::pair status = uartDeviceMap.emplace(deviceFile, uartElements); + if (status.second == false) { + sif::debug << "UartComIF::initializeInterface: Failed to insert device " << deviceFile + << "to Uart device map" << std::endl; + return RETURN_FAILED; + } + } + else { + sif::debug << "UartComIF::initializeInterface: Uart device " << deviceFile << "already in " + << "use" << std::endl; + return RETURN_FAILED; + } + + return RETURN_OK; +} + +int UartComIF::configureUartPort(UartCookie* uartCookie) { + + struct termios options; + + std::string deviceFile = uartCookie->getDeviceFile(); + int fd = open(deviceFile.c_str(), O_RDWR); + + if (fd < 0) { + sif::debug << "UartComIF::configureUartPort: Failed to open uart " << deviceFile << "with" + << " error code " << errno << strerror(errno) << std::endl; + return fd; + } + + /* Read in existing settings */ + if(tcgetattr(fd, &options) != 0) { + sif::debug << "UartComIF::configureUartPort: Error " << errno << "from tcgetattr: " + << strerror(errno) << std::endl; + return fd; + } + + setParityOptions(&options, uartCookie); + setStopBitOptions(&options, uartCookie); + setDatasizeOptions(&options, uartCookie); + setFixedOptions(&options); + + /* Sets uart to non-blocking mode. Read returns immediately when there are no data available */ + options.c_cc[VTIME] = 0; + options.c_cc[VMIN] = 0; + + configureBaudrate(&options, uartCookie); + + /* Save option settings */ + if (tcsetattr(fd, TCSANOW, &options) != 0) { + sif::debug << "UartComIF::configureUartPort: Failed to set options with error " << errno + << ": " << strerror(errno); + return fd; + } + return fd; +} + +void UartComIF::setParityOptions(struct termios* options, UartCookie* uartCookie) { + /* Clear parity bit */ + options->c_cflag &= ~PARENB; + switch (uartCookie->getParity()) { + case Parity::EVEN: + options->c_cflag |= PARENB; + options->c_cflag &= ~PARODD; + break; + case Parity::ODD: + options->c_cflag |= PARENB; + options->c_cflag |= PARODD; + break; + default: + break; + } +} + +void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCookie) { + /* Clear stop field. Sets stop bit to one bit */ + options->c_cflag &= ~CSTOPB; + switch (uartCookie->getStopBits()) { + case StopBits::TWO_STOP_BITS: + options->c_cflag |= CSTOPB; + break; + default: + break; + } +} + +void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCookie) { + /* Clear size bits */ + options->c_cflag &= ~CSIZE; + switch (uartCookie->getBitsPerWord()) { + case 5: + options->c_cflag |= CS5; + break; + case 6: + options->c_cflag |= CS6; + break; + case 7: + options->c_cflag |= CS7; + break; + case 8: + options->c_cflag |= CS8; + break; + default: + sif::debug << "UartComIF::setDatasizeOptions: Invalid size specified" << std::endl; + break; + } +} + +void UartComIF::setFixedOptions(struct termios* options) { + /* Disable RTS/CTS hardware flow control */ + options->c_cflag &= ~CRTSCTS; + /* Turn on READ & ignore ctrl lines (CLOCAL = 1) */ + options->c_cflag |= CREAD | CLOCAL; + /* Disable canonical mode */ + options->c_lflag &= ~ICANON; + /* Disable echo */ + options->c_lflag &= ~ECHO; + /* Disable erasure */ + options->c_lflag &= ~ECHOE; + /* Disable new-line echo */ + options->c_lflag &= ~ECHONL; + /* Disable interpretation of INTR, QUIT and SUSP */ + options->c_lflag &= ~ISIG; + /* Turn off s/w flow ctrl */ + options->c_iflag &= ~(IXON | IXOFF | IXANY); + /* Disable any special handling of received bytes */ + options->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); + /* Prevent special interpretation of output bytes (e.g. newline chars) */ + options->c_oflag &= ~OPOST; + /* Prevent conversion of newline to carriage return/line feed */ + options->c_oflag &= ~ONLCR; +} + +void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) { + switch (uartCookie->getBaudrate()) { + case 50: + cfsetispeed(options, B50); + cfsetospeed(options, B50); + break; + case 75: + cfsetispeed(options, B75); + cfsetospeed(options, B75); + break; + case 110: + cfsetispeed(options, B110); + cfsetospeed(options, B110); + break; + case 134: + cfsetispeed(options, B134); + cfsetospeed(options, B134); + break; + case 150: + cfsetispeed(options, B150); + cfsetospeed(options, B150); + break; + case 200: + cfsetispeed(options, B200); + cfsetospeed(options, B200); + break; + case 300: + cfsetispeed(options, B300); + cfsetospeed(options, B300); + break; + case 600: + cfsetispeed(options, B600); + cfsetospeed(options, B600); + break; + case 1200: + cfsetispeed(options, B1200); + cfsetospeed(options, B1200); + break; + case 1800: + cfsetispeed(options, B1800); + cfsetospeed(options, B1800); + break; + case 2400: + cfsetispeed(options, B2400); + cfsetospeed(options, B2400); + break; + case 4800: + cfsetispeed(options, B4800); + cfsetospeed(options, B4800); + break; + case 9600: + cfsetispeed(options, B9600); + cfsetospeed(options, B9600); + break; + case 19200: + cfsetispeed(options, B19200); + cfsetospeed(options, B19200); + break; + case 38400: + cfsetispeed(options, B38400); + cfsetospeed(options, B38400); + break; + case 57600: + cfsetispeed(options, B57600); + cfsetospeed(options, B57600); + break; + case 115200: + cfsetispeed(options, B115200); + cfsetospeed(options, B115200); + break; + case 230400: + cfsetispeed(options, B230400); + cfsetospeed(options, B230400); + break; + case 460800: + cfsetispeed(options, B460800); + cfsetospeed(options, B460800); + break; + default: + sif::debug << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl; + break; + } +} + +ReturnValue_t UartComIF::sendMessage(CookieIF *cookie, + const uint8_t *sendData, size_t sendLen) { + + int fd; + std::string deviceFile; + UartDeviceMapIter uartDeviceMapIter; + + if(sendData == nullptr) { + sif::debug << "UartComIF::sendMessage: Send Data is nullptr" << std::endl; + return RETURN_FAILED; + } + + if(sendLen == 0) { + return RETURN_OK; + } + + UartCookie* uartCookie = dynamic_cast(cookie); + if(uartCookie == nullptr) { + sif::debug << "UartComIF::sendMessasge: Invalid Uart Cookie!" << std::endl; + return NULLPOINTER; + } + + deviceFile = uartCookie->getDeviceFile(); + uartDeviceMapIter = uartDeviceMap.find(deviceFile); + if (uartDeviceMapIter == uartDeviceMap.end()) { + sif::debug << "UartComIF::sendMessage: Device file " << deviceFile << "not in uart map" + << std::endl; + return RETURN_FAILED; + } + + fd = uartDeviceMapIter->second.fileDescriptor; + + if (write(fd, sendData, sendLen) != (int)sendLen) { + sif::error << "UartComIF::sendMessage: Failed to send data with error code " << errno + << ": Error description: " << strerror(errno) << std::endl; + return RETURN_FAILED; + } + + return RETURN_OK; +} + +ReturnValue_t UartComIF::getSendSuccess(CookieIF *cookie) { + return RETURN_OK; +} + +ReturnValue_t UartComIF::requestReceiveMessage(CookieIF *cookie, + size_t requestLen) { + + int fd; + std::string deviceFile; + UartDeviceMapIter uartDeviceMapIter; + uint8_t* bufferPtr; + + if(requestLen == 0) { + return RETURN_OK; + } + + UartCookie* uartCookie = dynamic_cast(cookie); + if(uartCookie == nullptr) { + sif::debug << "UartComIF::requestReceiveMessage: Invalid Uart Cookie!" << std::endl; + return NULLPOINTER; + } + + deviceFile = uartCookie->getDeviceFile(); + uartDeviceMapIter = uartDeviceMap.find(deviceFile); + if (uartDeviceMapIter == uartDeviceMap.end()) { + sif::debug << "UartComIF::requestReceiveMessage: Device file " << deviceFile + << " not in uart map" << std::endl; + return RETURN_FAILED; + } + + fd = uartDeviceMapIter->second.fileDescriptor; + bufferPtr = uartDeviceMapIter->second.replyBuffer.data(); + int bytesRead = read(fd, bufferPtr, requestLen); + if (bytesRead != static_cast(requestLen)) { + sif::debug << "UartComIF::requestReceiveMessage: Only read " << bytesRead + << " of " << requestLen << " bytes" << std::endl; + return RETURN_FAILED; + } + else { + uartDeviceMapIter->second.replyLen = bytesRead; + } + + return RETURN_OK; +} + +ReturnValue_t UartComIF::readReceivedMessage(CookieIF *cookie, + uint8_t **buffer, size_t* size) { + + std::string deviceFile; + UartDeviceMapIter uartDeviceMapIter; + + UartCookie* uartCookie = dynamic_cast(cookie); + if(uartCookie == nullptr) { + sif::debug << "UartComIF::readReceivedMessage: Invalid uart cookie!" << std::endl; + return NULLPOINTER; + } + + deviceFile = uartCookie->getDeviceFile(); + uartDeviceMapIter = uartDeviceMap.find(deviceFile); + if (uartDeviceMapIter == uartDeviceMap.end()) { + sif::debug << "UartComIF::readReceivedMessage: Device file " << deviceFile + << " not in uart map" << std::endl; + return RETURN_FAILED; + } + + *buffer = uartDeviceMapIter->second.replyBuffer.data(); + *size = uartDeviceMapIter->second.replyLen; + + return RETURN_OK; +} + diff --git a/linux/uart/UartComIF.h b/linux/uart/UartComIF.h new file mode 100644 index 00000000..9dd854da --- /dev/null +++ b/linux/uart/UartComIF.h @@ -0,0 +1,94 @@ +#ifndef BSP_Q7S_COMIF_UARTCOMIF_H_ +#define BSP_Q7S_COMIF_UARTCOMIF_H_ + +#include +#include + +#include +#include + +#include "UartCookie.h" + +/** + * @brief This is the communication interface to access serial ports on linux based operating + * systems. + * + * @details The implementation follows the instructions from https://blog.mbedded.ninja/programming/ + * operating-systems/linux/linux-serial-ports-using-c-cpp/#disabling-canonical-mode + * + * @author J. Meier + */ +class UartComIF: public DeviceCommunicationIF, public SystemObject { +public: + UartComIF(object_id_t objectId); + + virtual ~UartComIF(); + + 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: + + using UartDeviceFile_t = std::string; + + typedef struct UartElements { + int fileDescriptor; + std::vector replyBuffer; + /** Number of bytes read will be written to this variable */ + size_t replyLen; + } UartElements_t; + + using UartDeviceMap = std::unordered_map; + using UartDeviceMapIter = UartDeviceMap::iterator; + + /** + * The uart devie map stores informations of initialized uart ports. + */ + UartDeviceMap uartDeviceMap; + + /** + * @brief This function opens and configures a uart device by using the information stored + * in the uart cookie. + * @param uartCookie Pointer to uart cookie with information about the uart. Contains the + * uart device file, baudrate, parity, stopbits etc. + * @return The file descriptor of the configured uart. + */ + int configureUartPort(UartCookie* uartCookie); + + /** + * @brief This function adds the parity settings to the termios options struct. + * + * @param options Pointer to termios options struct which will be modified to enable or disable + * parity checking. + * @param uartCookie Pointer to uart cookie containing the information about the desired + * parity settings. + * + */ + void setParityOptions(struct termios* options, UartCookie* uartCookie); + + void setStopBitOptions(struct termios* options, UartCookie* uartCookie); + + /** + * @brief This function sets options which are not configurable by the uartCookie. + */ + void setFixedOptions(struct termios* options); + + /** + * @brief With this function the datasize settings are added to the termios options struct. + */ + void setDatasizeOptions(struct termios* options, UartCookie* uartCookie); + + /** + * @brief This functions adds the baudrate specified in the uartCookie to the termios options + * struct. + */ + void configureBaudrate(struct termios* options, UartCookie* uartCookie); +}; + +#endif /* BSP_Q7S_COMIF_UARTCOMIF_H_ */ diff --git a/linux/uart/UartCookie.cpp b/linux/uart/UartCookie.cpp new file mode 100644 index 00000000..b8149388 --- /dev/null +++ b/linux/uart/UartCookie.cpp @@ -0,0 +1,63 @@ +#include "UartCookie.h" + +#include + +UartCookie::UartCookie(std::string deviceFile, uint32_t baudrate, size_t maxReplyLen) : + deviceFile(deviceFile), baudrate(baudrate), maxReplyLen(maxReplyLen) { +} + +UartCookie::~UartCookie() {} + +uint32_t UartCookie::getBaudrate() const { + return baudrate; +} + +size_t UartCookie::getMaxReplyLen() const { + return maxReplyLen; +} + +std::string UartCookie::getDeviceFile() const { + return deviceFile; +} + +void UartCookie::setParityOdd() { + parity = Parity::ODD; +} + +void UartCookie::setParityEven() { + parity = Parity::EVEN; +} + +Parity UartCookie::getParity() const { + return parity; +} + +void UartCookie::setBitsPerWord(uint8_t bitsPerWord_) { + switch(bitsPerWord_) { + case 5: + case 6: + case 7: + case 8: + break; + default: + sif::debug << "UartCookie::setBitsPerWord: Invalid bits per word specified" << std::endl; + return; + } + bitsPerWord = bitsPerWord_; +} + +uint8_t UartCookie::getBitsPerWord() const { + return bitsPerWord; +} + +StopBits UartCookie::getStopBits() const { + return stopBits; +} + +void UartCookie::setTwoStopBits() { + stopBits = StopBits::TWO_STOP_BITS; +} + +void UartCookie::setOneStopBit() { + stopBits = StopBits::ONE_STOP_BIT; +} diff --git a/linux/uart/UartCookie.h b/linux/uart/UartCookie.h new file mode 100644 index 00000000..59004719 --- /dev/null +++ b/linux/uart/UartCookie.h @@ -0,0 +1,81 @@ +#ifndef SAM9G20_COMIF_COOKIES_UART_COOKIE_H_ +#define SAM9G20_COMIF_COOKIES_UART_COOKIE_H_ + +#include +#include + +enum class Parity { + NONE, + EVEN, + ODD +}; + +enum class StopBits { + ONE_STOP_BIT, + TWO_STOP_BITS +}; + +/** + * @brief Cookie for the UartComIF. There are many options available to configure the uart driver. + * The constructor only requests for common options like the baudrate. Other options can + * be set by member functions. + * + * @author J. Meier + */ +class UartCookie: public CookieIF { +public: + + /** + * @brief Constructor for the uart cookie. + * @param deviceFile The device file specifying the uart to use. E.g. "/dev/ttyPS1". + * @param baudrate The baudrate to use for input and output. Possible Baudrates are: 50, + * 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, B19200, + * 38400, 57600, 115200, 230400, 460800 + * @param maxReplyLen The maximum size an object using this cookie expects. + * + * @details Default configuration: No parity + * 8 databits (number of bits transfered with one uart frame) + * One stop bit + * + * + */ + UartCookie(std::string deviceFile, uint32_t baudrate, size_t maxReplyLen); + + virtual ~UartCookie(); + + uint32_t getBaudrate() const; + size_t getMaxReplyLen() const; + std::string getDeviceFile() const; + Parity getParity() const; + uint8_t getBitsPerWord() const; + StopBits getStopBits() const; + + /** + * Functions two enable parity checking. + */ + void setParityOdd(); + void setParityEven(); + + /** + * Function two set number of bits per UART frame. + */ + void setBitsPerWord(uint8_t bitsPerWord_); + + /** + * Function to specify the number of stopbits. + */ + void setTwoStopBits(); + void setOneStopBit(); + + +private: + + std::string deviceFile; + uint32_t baudrate; + size_t maxReplyLen = 0; + Parity parity = Parity::NONE; + uint8_t bitsPerWord = 8; + StopBits stopBits = StopBits::ONE_STOP_BIT; +}; + +#endif diff --git a/mission/devices/SyrlinksHkHandler.cpp b/mission/devices/SyrlinksHkHandler.cpp index a13c0286..60dc439c 100644 --- a/mission/devices/SyrlinksHkHandler.cpp +++ b/mission/devices/SyrlinksHkHandler.cpp @@ -1,9 +1,10 @@ #include #include #include +#include SyrlinksHkHandler::SyrlinksHkHandler(object_id_t objectId, object_id_t comIF, CookieIF * comCookie) : - DeviceHandlerBase(objectId, comIF, comCookie), rxStatusRegistersSet(this) { + DeviceHandlerBase(objectId, comIF, comCookie), rxDataset(this), txDataset(this) { if (comCookie == NULL) { sif::error << "SyrlinksHkHandler: Invalid com cookie" << std::endl; } @@ -25,7 +26,7 @@ void SyrlinksHkHandler::doShutDown(){ ReturnValue_t SyrlinksHkHandler::buildNormalDeviceCommand( DeviceCommandId_t * id) { - *id = READ_RX_STATUS_REGISTERS; + *id = SYRLINKS::READ_RX_STATUS_REGISTERS; return buildCommandFromCommand(*id, NULL, 0); } @@ -39,33 +40,40 @@ ReturnValue_t SyrlinksHkHandler::buildCommandFromCommand( size_t commandDataLen) { switch(deviceCommand) { case(SYRLINKS::RESET_UNIT): { - resetCommand.copy(rawPacket, resetCommand.size(), 0); + resetCommand.copy(reinterpret_cast(commandBuffer), resetCommand.size(), 0); rawPacketLen = resetCommand.size(); - rememberCommandId = SYRLINKS::RESET_UNIT; + rawPacket = commandBuffer; return RETURN_OK; } case(SYRLINKS::SET_TX_MODE_STANDBY): { - setTxModeStandby.copy(rawPacket, setTxModeStandby.size(), 0); + setTxModeStandby.copy(reinterpret_cast(commandBuffer), setTxModeStandby.size(), 0); rawPacketLen = setTxModeStandby.size(); - rememberCommandId = SYRLINKS::SET_TX_MODE_STANDBY; + rawPacket = commandBuffer; return RETURN_OK; } case(SYRLINKS::SET_TX_MODE_MODULATION): { - setTxModeModulation.copy(rawPacket, setTxModeModulation.size(), 0); + setTxModeModulation.copy(reinterpret_cast(commandBuffer), setTxModeModulation.size(), 0); rawPacketLen = setTxModeModulation.size(); - rememberCommandId = SYRLINKS::SET_TX_MODE_MODULATION; + rawPacket = commandBuffer; return RETURN_OK; } case(SYRLINKS::SET_TX_MODE_CW): { - setTxModeCw.copy(rawPacket, setTxModeCw.size(), 0); + setTxModeCw.copy(reinterpret_cast(commandBuffer), setTxModeCw.size(), 0); rawPacketLen = setTxModeCw.size(); - rememberCommandId = SYRLINKS::SET_TX_MODE_CW; + rawPacket = commandBuffer; return RETURN_OK; } case(SYRLINKS::READ_RX_STATUS_REGISTERS): { - readRxStatusRegCommand.copy(rawPacket, readRxStatusRegCommand.size(), 0); + readRxStatusRegCommand.copy(reinterpret_cast(commandBuffer), readRxStatusRegCommand.size(), 0); rawPacketLen = readRxStatusRegCommand.size(); - rememberCommandId = SYRLINKS::READ_RX_STATUS_REGISTERS; + rawPacket = commandBuffer; + return RETURN_OK; + } + case(SYRLINKS::READ_TX_STATUS): { + readTxStatus.copy(reinterpret_cast(commandBuffer), readTxStatus.size(), 0); + rawPacketLen = readTxStatus.size(); + rememberCommandId = SYRLINKS::READ_TX_STATUS; + rawPacket = commandBuffer; return RETURN_OK; } default: @@ -75,11 +83,17 @@ ReturnValue_t SyrlinksHkHandler::buildCommandFromCommand( } void SyrlinksHkHandler::fillCommandAndReplyMap() { - this->insertInCommandAndReplyMap(SYRLINKS::RESET_UNIT); - this->insertInCommandAndReplyMap(SYRLINKS::SET_TX_MODE_STANDBY); - this->insertInCommandAndReplyMap(SYRLINKS::SET_TX_MODE_MODULATION); - this->insertInCommandAndReplyMap(SYRLINKS::SET_TX_MODE_CW); - this->insertInCommandAndReplyMap(SYRLINKS::READ_RX_STATUS_REGISTERS, 1, &rxStatusRegistersSet, + this->insertInCommandAndReplyMap(SYRLINKS::RESET_UNIT, 1, nullptr, SYRLINKS::ACK_SIZE, false, + true, SYRLINKS::ACK_REPLY); + this->insertInCommandAndReplyMap(SYRLINKS::SET_TX_MODE_STANDBY, 1, nullptr, SYRLINKS::ACK_SIZE, + false, true, SYRLINKS::ACK_REPLY); + this->insertInCommandAndReplyMap(SYRLINKS::SET_TX_MODE_MODULATION, 1, nullptr, + SYRLINKS::ACK_SIZE, false, true, SYRLINKS::ACK_REPLY); + this->insertInCommandAndReplyMap(SYRLINKS::SET_TX_MODE_CW, 1, nullptr, SYRLINKS::ACK_SIZE, + false, true, SYRLINKS::ACK_REPLY); + this->insertInCommandAndReplyMap(SYRLINKS::READ_TX_STATUS, 1, &txDataset, + SYRLINKS::READ_TX_STATUS); + this->insertInCommandAndReplyMap(SYRLINKS::READ_RX_STATUS_REGISTERS, 1, &rxDataset, SYRLINKS::RX_STATUS_REGISTERS_REPLY_SIZE); } @@ -88,59 +102,33 @@ ReturnValue_t SyrlinksHkHandler::scanForReply(const uint8_t *start, ReturnValue_t result = RETURN_OK; - switch(rememberCommandId) { - case(SYRLINKS::RESET_UNIT): - if (remainingSize != SYRLINKS::REQUEST_STATUS_REPLY_SIZE) { - result = REPLY_WRONG_SIZE; - break; - } - *foundLen = SYRLINKS::REQUEST_STATUS_REPLY_SIZE; - *foundId = SYRLINKS::RESET_UNIT; - rememberCommandId = SYRLINKS::NONE; + if(*start != '<') { + sif::error << "SyrlinksHkHandler::scanForReply: Missing start frame character" << std::endl; + return MISSING_START_FRAME_CHARACTER; + } + + switch(*(start + 1)) { + case('A'): + *foundLen = SYRLINKS::ACK_SIZE; + *foundId = SYRLINKS::ACK_REPLY; break; - case(SYRLINKS::SET_TX_MODE_STANDBY): - if (remainingSize != SYRLINKS::REQUEST_STATUS_REPLY_SIZE) { - result = REPLY_WRONG_SIZE; - } - *foundLen = SYRLINKS::REQUEST_STATUS_REPLY_SIZE; - rememberCommandId = SYRLINKS::NONE; - *foundId = SYRLINKS::SET_TX_MODE_STANDBY; - break; - case(SYRLINKS::SET_TX_MODE_MODULATION): - if (remainingSize != SYRLINKS::REQUEST_STATUS_REPLY_SIZE) { - result = REPLY_WRONG_SIZE; - } - *foundLen = SYRLINKS::REQUEST_STATUS_REPLY_SIZE; - *foundId = SYRLINKS::SET_TX_MODE_MODULATION; - rememberCommandId = SYRLINKS::NONE; - break; - case(SYRLINKS::SET_TX_MODE_CW): - if (remainingSize != SYRLINKS::REQUEST_STATUS_REPLY_SIZE) { - result = REPLY_WRONG_SIZE; - } - *foundLen = SYRLINKS::REQUEST_STATUS_REPLY_SIZE; - *foundId = SYRLINKS::SET_TX_MODE_CW; - rememberCommandId = SYRLINKS::NONE; - break; - case(SYRLINKS::READ_RX_STATUS_REGISTERS): - if (remainingSize != SYRLINKS::RX_STATUS_REGISTERS_REPLY_SIZE) { - result = REPLY_WRONG_SIZE; - } + case('E'): *foundLen = SYRLINKS::RX_STATUS_REGISTERS_REPLY_SIZE; *foundId = SYRLINKS::READ_RX_STATUS_REGISTERS; - rememberCommandId = SYRLINKS::NONE; + break; + case('R'): + if (rememberCommandId == SYRLINKS::READ_TX_STATUS) { + *foundLen = SYRLINKS::READ_TX_STATUS_REPLY_SIZE; + *foundId = SYRLINKS::READ_TX_STATUS; + rememberCommandId = SYRLINKS::NONE; + } break; default: + sif::error << "SyrlinksHkHandler::scanForReply: Unknown reply identifier" << std::endl; result = IGNORE_REPLY_DATA; break; } - if (result == REPLY_WRONG_SIZE) { - sif::debug << "SyrlinksHkHandler::scanForReply: Received reply with invalid length" - << std::endl; - return result; - } - return result; } @@ -150,53 +138,44 @@ ReturnValue_t SyrlinksHkHandler::interpretDeviceReply(DeviceCommandId_t id, ReturnValue_t result; switch (id) { - case (SYRLINKS::RESET_UNIT): - case (SYRLINKS::SET_TX_MODE_STANDBY): - case (SYRLINKS::SET_TX_MODE_MODULATION): - case (SYRLINKS::SET_TX_MODE_CW): - result = verifyTansmissionStatusReply(packet); + case (SYRLINKS::ACK_REPLY): + result = verifyReply(packet, SYRLINKS::ACK_SIZE); if (result != RETURN_OK) { - sif::debug << "SyrlinksHkHandler::interpretDeviceReply: Status reply has invalid crc" - << std::endl; + sif::error << "SyrlinksHkHandler::interpretDeviceReply: Acknowledgement reply has " + "invalid crc" << std::endl; return CRC_FAILURE; } - result = parseReplyStatus(static_cast(packet + SYRLINKS::MESSAGE_HEADER_SIZE)); + result = parseReplyStatus(reinterpret_cast(packet + SYRLINKS::MESSAGE_HEADER_SIZE)); if (result != RETURN_OK) { return result; } break; case(SYRLINKS::READ_RX_STATUS_REGISTERS): - result = verifyReadRxStatusRegistersReply(packet); + result = verifyReply(packet, SYRLINKS::RX_STATUS_REGISTERS_REPLY_SIZE); if (result != RETURN_OK) { - sif::debug << "SyrlinksHkHandler::interpretDeviceReply: Read rx status registers reply " + sif::error << "SyrlinksHkHandler::interpretDeviceReply: Read rx status registers reply " << "has invalid crc" << std::endl; return CRC_FAILURE; } - + parseRxStatusRegistersReply(packet); + break; + case(SYRLINKS::READ_TX_STATUS): + result = verifyReply(packet, SYRLINKS::READ_TX_STATUS_REPLY_SIZE); + if (result != RETURN_OK) { + sif::error << "SyrlinksHkHandler::interpretDeviceReply: Read tx status reply " + << "has invalid crc" << std::endl; + return CRC_FAILURE; + } + parseTxStatusReply(packet); break; default: { + sif::debug << "SyrlinksHkHandler::interpretDeviceReply: Unknown device reply id" + << std::endl; return DeviceHandlerIF::UNKNOWN_DEVICE_REPLY; } - } - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t SyrlinksHkHandler::verifyTansmissionStatusReply() { - int result = 0; - uint16_t crc = CRC::crc16ccitt(packet, - SYRLINKS::REQUEST_STATUS_REPLY_SIZE - SYRLINKS::SIZE_CRC_AND_TERMINATION, - CRC_INITIAL_VALUE); - std::string recalculatedCrc = convertIntToHexString(crc); - const char* replyCrc = packet + SYRLINKS::REQUEST_STATUS_REPLY_SIZE - - SYRLINKS::SIZE_CRC_AND_TERMINATION; - size_t startPosition = 0; - result = recalculatedCrc.compare(startPosition, SYRLINKS_CRC_FIELD_SIZE, replyCrc); - if (result != 0) { - return RETURN_FAILED; - } - return RETURN_OK; + return RETURN_OK; } std::string SyrlinksHkHandler::convertIntToHexString(uint16_t intValue) { @@ -205,7 +184,7 @@ std::string SyrlinksHkHandler::convertIntToHexString(uint16_t intValue) { return stream.str(); } -ReturnValue_t SyrlinksHkHandler::parseReplyStatus(char* status) { +ReturnValue_t SyrlinksHkHandler::parseReplyStatus(const char* status) { switch (*status) { case '0': return RETURN_OK; @@ -231,29 +210,54 @@ ReturnValue_t SyrlinksHkHandler::parseReplyStatus(char* status) { sif::debug << "SyrlinksHkHandler::parseReplyStatus: Bad CRC" << std::endl; return BAD_CRC_ACK; default: - sif::debug << "SyrlinksHkHandler::parseReplyStatus: Status reply holds invalid status " - << "id" << std::endl; + sif::debug << "SyrlinksHkHandler::parseReplyStatus: Status reply contains an invalid " + << "status id" << std::endl; return RETURN_FAILED; } } -ReturnValue_t SyrlinksHkHandler::verifyReadRxStatusRegistersReply(uint8_t* packet) { +ReturnValue_t SyrlinksHkHandler::verifyReply(const uint8_t* packet, uint8_t size) { int result = 0; /* Calculate crc of received packet */ - uint16_t crc = CRC::crc16ccitt(packet, - SYRLINKS::RX_STATUS_REGISTERS_REPLY_SIZE - SYRLINKS::SIZE_CRC_AND_TERMINATION, + uint16_t crc = CRC::crc16ccitt(packet, size - SYRLINKS::SIZE_CRC_AND_TERMINATION, CRC_INITIAL_VALUE); std::string recalculatedCrc = convertIntToHexString(crc); - const char* replyCrc = packet + SYRLINKS::RX_STATUS_REGISTERS_REPLY_SIZE - - SYRLINKS::SIZE_CRC_AND_TERMINATION; + const char* replyCrc = reinterpret_cast(packet) + size - SYRLINKS::SIZE_CRC_AND_TERMINATION; size_t startPosition = 0; - result = recalculatedCrc.compare(startPosition, SYRLINKS_CRC_FIELD_SIZE, replyCrc); + result = recalculatedCrc.compare(startPosition, SYRLINKS::CRC_FIELD_SIZE, replyCrc); if (result != 0) { return RETURN_FAILED; } return RETURN_OK; } +void SyrlinksHkHandler::parseRxStatusRegistersReply(const uint8_t* packet) { + PoolReadHelper readHelper(&rxDataset); + uint16_t offset = SYRLINKS::MESSAGE_HEADER_SIZE; + rxDataset.rxStatus = *(packet + offset); + packet += 1; + rxDataset.rxSensitivity = *(packet + offset) << 16 | *(packet + offset + 1) << 8 | *(packet + offset + 2); + packet += 3; + rxDataset.rxFrequencyShift = *(packet + offset) << 16 | *(packet + offset + 1) << 8 | *(packet + offset + 2); + packet += 3; + rxDataset.rxIqPower = *(packet + offset) << 8 | *(packet + offset + 1); + packet += 2; + rxDataset.rxAgcValue = *(packet + offset + 1) << 8 | *(packet + offset); + packet += 2; + packet += 1; // reserved register + rxDataset.rxDemodEb= *(packet + offset) << 16 | *(packet + offset + 1) << 8 | *(packet + offset + 2); + packet += 3; + rxDataset.rxDemodN0= *(packet + offset) << 16 | *(packet + offset + 1) << 8 | *(packet + offset + 2); + packet += 3; + rxDataset.rxDataRate = *(packet + offset); +} + +void SyrlinksHkHandler::parseTxStatusReply(const uint8_t* packet) { + PoolReadHelper readHelper(&txDataset); + uint16_t offset = SYRLINKS::MESSAGE_HEADER_SIZE; + rxDataset.rxStatus = *(packet + offset); +} + void SyrlinksHkHandler::setNormalDatapoolEntriesInvalid(){ } @@ -264,7 +268,20 @@ uint32_t SyrlinksHkHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) ReturnValue_t SyrlinksHkHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { - localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075_1, new PoolEntry( { 0.0 })); + + localDataPoolMap.emplace(SYRLINKS::RX_STATUS, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_SENSITIVITY, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_FREQUENCY_SHIFT, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_IQ_POWER, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_AGC_VALUE, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_DEMOD_EB, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_DEMOD_N0, new PoolEntry( { 0 })); + localDataPoolMap.emplace(SYRLINKS::RX_DATA_RATE, new PoolEntry( { 0 })); + return HasReturnvaluesIF::RETURN_OK; } +void SyrlinksHkHandler::setModeNormal() { + mode = MODE_NORMAL; +} + diff --git a/mission/devices/SyrlinksHkHandler.h b/mission/devices/SyrlinksHkHandler.h index aefc99f9..23a48c13 100644 --- a/mission/devices/SyrlinksHkHandler.h +++ b/mission/devices/SyrlinksHkHandler.h @@ -3,7 +3,7 @@ #include #include -#include +#include /** * @brief This is the device handler for the syrlinks transceiver. It handles the command @@ -20,6 +20,11 @@ public: CookieIF * comCookie); virtual ~SyrlinksHkHandler(); + /** + * @brief Sets mode to MODE_NORMAL. Can be used for debugging. + */ + void setModeNormal(); + protected: void doStartUp() override; void doShutDown() override; @@ -49,6 +54,7 @@ private: static const ReturnValue_t UNKNOWN_COMMAND_ID_ACK = MAKE_RETURN_CODE(0xA5); static const ReturnValue_t BAD_CRC_ACK = MAKE_RETURN_CODE(0xA6); static const ReturnValue_t REPLY_WRONG_SIZE = MAKE_RETURN_CODE(0xA7); + static const ReturnValue_t MISSING_START_FRAME_CHARACTER = MAKE_RETURN_CODE(0xA8); static const uint8_t CRC_INITIAL_VALUE = 0x0; @@ -58,29 +64,18 @@ private: /** W - write, 04 - 4 bytes in data field, 01 - value, 40 register to write value */ std::string setTxModeModulation = ""; std::string setTxModeCw = ""; - - SYRLINKS::RxStatusRegistersDataset rxStatusRegistersSet; - - static const uint8_t MAX_CMD_LEN = 3; - - uint8_t rememberRequestedSize = 0; - uint8_t rememberCommandId = SYRLINKS::NONE; - uint8_t cmdBuffer[MAX_CMD_LEN]; - CommunicationStep communicationStep = - CommunicationStep::START_ADC_CONVERSION; - + std::string readTxStatus = ""; /** - * @brief This function verifies the checksum of a status reply packet of the syrlinks. - * - * @param packet Pointer to the received status reply. - * - * @return RETURN_OK if successful, otherwise RETURN_FAILURE. - * - * @details A status reply only contains one byte of payload data giving information about - * the transmission status. + * In some cases it is not possible to extract from the received reply the information about + * the associated command. This variable is thus used to remember the command id. */ - ReturnValue_t verifyTansmissionStatusReply(const uint8_t* packet); + DeviceCommandId_t rememberCommandId = SYRLINKS::NONE; + + SYRLINKS::RxDataset rxDataset; + SYRLINKS::TxDataset txDataset; + + uint8_t commandBuffer[SYRLINKS::MAX_COMMAND_SIZE]; /** * @brief This function converts an uint16_t into its hexadecimal string representation. @@ -89,7 +84,7 @@ private: * * @return An std::string object containing the hex representation of intValue. */ - std::string SyrlinksHkHandler::convertIntToHexString(uint16_t intValue); + std::string convertIntToHexString(uint16_t intValue); /** * @brief This function parses the status reply @@ -98,17 +93,32 @@ private: * @details Some commands reply with a status message giving information about the preceding * command transmission and/or execution was successful. */ - ReturnValue_t parseReplyStatus(char* status); + ReturnValue_t parseReplyStatus(const char* status); /** * @brief Function verifies the received reply from the syrlinks by recalculating and * comparing the crc. * * @param packet Pointer to the received reply. + * @param size Size of the whole packet including the crc and the packet termination + * character '>'. * * @return RETURN_OK if successful, otherwise RETURN_FAILED. */ - ReturnValue_t verifyReadRxStatusRegistersReply(uint8_t* packet) + ReturnValue_t verifyReply(const uint8_t* packet, uint8_t size); + + /** + * @brief This function extracts the data from a rx status registers reply and writes the + * information to the status registers dataset. + * @param packet Pointer to the reply packet. + */ + void parseRxStatusRegistersReply(const uint8_t* packet); + + /** + * @brief This function writes the read tx status register to the txStatusDataset. + * @param packet Pointer to the received packet. + */ + void parseTxStatusReply(const uint8_t* packet); }; #endif /* MISSION_DEVICES_SYRLINKSHKHANDLER_H_ */ diff --git a/mission/devices/crc/crc_ccitt_Syrlinks.cpp b/mission/devices/crc/crc_ccitt_Syrlinks.cpp deleted file mode 100644 index cb1e867d..00000000 --- a/mission/devices/crc/crc_ccitt_Syrlinks.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "crc_ccitt_Syrlinks.h" -#include -#include - -static const uint16_t crc_table[256] = { - 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, - 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, - 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, - 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, - 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, - 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, - 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, - 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, - 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, - 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, - 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, - 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, - 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, - 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, - 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, - 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, - 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, - 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, - 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, - 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, - 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, - 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, - 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, - 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, - 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, - 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, - 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, - 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, - 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, - 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, - 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, - 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 -}; - - -// CRC implementation -uint16_t Calculate_CRC_Syrlinks(uint8_t const input[], uint32_t length) -{ - uint16_t crc = 0x0000; - uint8_t *data = (uint8_t *)input; - unsigned int tbl_idx; - - while (length--) { - tbl_idx = ((crc >> 8) ^ *data) & 0xff; - crc = (crc_table[tbl_idx] ^ (crc << 8)) & 0xffff; - - data++; - } - return crc & 0xffff; - -} /* Calculate_CRC() */ - - diff --git a/mission/devices/crc/crc_ccitt_Syrlinks.h b/mission/devices/crc/crc_ccitt_Syrlinks.h deleted file mode 100644 index 8b952ee8..00000000 --- a/mission/devices/crc/crc_ccitt_Syrlinks.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef CRC_CCITT_Syrlinks_H_ -#define CRC_CCITT_Syrlinks_H_ - -#include - -/** - * @brief With this function the CRC16-CCITT over a data packet can be calculated. - * - * @param input Pointer to data over which the crc shall be calculated. - * @param length Size of data packet. - * - * @return The 16-bit wide crc calculated over the data packet. - * - * @details Wide: 16 bits - * Generator polynomial: 0x1021 - * Bit order: MSB - * Initial value: 0 - * @author Bucher, J. Meier - */ -uint16_t Calculate_CRC_Syrlinks(uint8_t const input[], uint32_t length); - - -#endif /* CRC_H_ */ diff --git a/mission/devices/devicedefinitions/SyrlinksDefinitions.h b/mission/devices/devicedefinitions/SyrlinksDefinitions.h index 2cd159af..5ab82a0c 100644 --- a/mission/devices/devicedefinitions/SyrlinksDefinitions.h +++ b/mission/devices/devicedefinitions/SyrlinksDefinitions.h @@ -1,10 +1,3 @@ -/* - * SyrlinksDefinitions.h - * - * Created on: 18.02.2021 - * Author: jakob - */ - #ifndef MISSION_DEVICES_DEVICEDEFINITIONS_SYRLINKSDEFINITIONS_H_ #define MISSION_DEVICES_DEVICEDEFINITIONS_SYRLINKSDEFINITIONS_H_ @@ -21,34 +14,57 @@ namespace SYRLINKS { static const DeviceCommandId_t SET_TX_MODE_MODULATION = 0x04; /** Sends out a single carrier wave for testing purpose */ static const DeviceCommandId_t SET_TX_MODE_CW = 0x05; + static const DeviceCommandId_t ACK_REPLY = 0x06; + static const DeviceCommandId_t READ_TX_STATUS = 0x07; /** Size of a simple transmission success response */ - static const uint8_t REQUEST_STATUS_REPLY_SIZE = 11; + static const uint8_t ACK_SIZE = 11; static const uint8_t SIZE_CRC_AND_TERMINATION = 5; /** The size of the header with the message identifier and the payload size field */ static const uint8_t MESSAGE_HEADER_SIZE = 5; /** Size of reply to an rx status registers request */ - static const uint8_t RX_STATUS_REGISTERS_REPLY_SIZE = 39; + static const uint8_t RX_STATUS_REGISTERS_REPLY_SIZE = 30; + static const uint8_t READ_TX_STATUS_REPLY_SIZE = 13; - static const uint8_t RX_STATUS_REGISTERS_SET_ID = READ_RX_STATUS_REGISTERS; + static const uint8_t RX_DATASET_ID = READ_RX_STATUS_REGISTERS; + static const uint8_t TX_DATASET_ID = READ_TX_STATUS; -class RxStatusRegistersDataset: public StaticLocalDataSet { + static const size_t MAX_REPLY_SIZE = RX_STATUS_REGISTERS_REPLY_SIZE; + static const size_t MAX_COMMAND_SIZE = 15; + + static const size_t CRC_FIELD_SIZE = 4; + + static const uint8_t RX_DATASET_SIZE = 8; + static const uint8_t TX_DATASET_SIZE = 1; + + enum SyrlinksPoolIds: lp_id_t { + RX_STATUS, + RX_SENSITIVITY, + RX_FREQUENCY_SHIFT, + RX_IQ_POWER, + RX_AGC_VALUE, + RX_DEMOD_EB, + RX_DEMOD_N0, + RX_DATA_RATE, + TX_STATUS, + TX_CONV_DIFF, + TX_CONV_FILTER, + TX_WAVEFORM, + TX_PCM_INDEX, + TX_AGC_VALUE, + }; + +class RxDataset: public StaticLocalDataSet { public: - RxStatusRegistersDataset(HasLocalDataPoolIF* owner) : - StaticLocalDataSet(owner, RX_STATUS_REGISTERS_SET_ID) { + RxDataset(HasLocalDataPoolIF* owner) : + StaticLocalDataSet(owner, RX_DATASET_ID) { } - RxStatusRegistersDataset(object_id_t objectId) : - StaticLocalDataSet(sid_t(objectId, RX_STATUS_REGISTERS_SET_ID)) { + RxDataset(object_id_t objectId) : + StaticLocalDataSet(sid_t(objectId, RX_DATASET_ID)) { } - lp_var_t fpgaVersion = lp_var_t(sid.objectId, FPGA_VERSION, this); - lp_var_t fpgaBuild = lp_var_t(sid.objectId, FPGA_BUILD, this); - lp_var_t hardwareId = lp_var_t(sid.objectId, HARDWARE_ID, this); - lp_var_t fpgaType = lp_var_t(sid.objectId, FPGA_TYPE, this); - lp_var_t lclStatus = lp_var_t(sid.objectId, LCL_STATUS, this); - lp_var_t fpgaOption = lp_var_t(sid.objectId, FPGA_OPTION, this); lp_var_t rxStatus = lp_var_t(sid.objectId, RX_STATUS, this); lp_var_t rxSensitivity = lp_var_t(sid.objectId, RX_SENSITIVITY, this); lp_var_t rxFrequencyShift = lp_var_t(sid.objectId, RX_FREQUENCY_SHIFT, this); @@ -56,13 +72,22 @@ public: lp_var_t rxAgcValue = lp_var_t(sid.objectId, RX_AGC_VALUE, this); lp_var_t rxDemodEb = lp_var_t(sid.objectId, RX_DEMOD_EB, this); lp_var_t rxDemodN0 = lp_var_t(sid.objectId, RX_DEMOD_N0, this); - lp_var_t rxDataRate = lp_var_t(sid.objectId, RX_DEMOD_N0, this); + lp_var_t rxDataRate = lp_var_t(sid.objectId, RX_DATA_RATE, this); +}; + + +class TxDataset: public StaticLocalDataSet { +public: + + TxDataset(HasLocalDataPoolIF* owner) : + StaticLocalDataSet(owner, TX_DATASET_ID) { + } + + TxDataset(object_id_t objectId) : + StaticLocalDataSet(sid_t(objectId, TX_DATASET_ID)) { + } + lp_var_t txStatus = lp_var_t(sid.objectId, TX_STATUS, this); - lp_var_t txConvDiff = lp_var_t(sid.objectId, TX_CONV_DIFF, this); - lp_var_t txConvFilter = lp_var_t(sid.objectId, TX_CONV_FILTER, this); - lp_var_t txWaveform = lp_var_t(sid.objectId, TX_WAVEFORM, this); - lp_var_t txPcmIndex = lp_var_t(sid.objectId, TX_PCM_INDEX, this); - lp_var_t txAgcValue = lp_var_t(sid.objectId, TX_AGC_VALUE, this); }; }