From 65df7b19127acbddf262a8c8ea97ec0432b2a25e Mon Sep 17 00:00:00 2001 From: AlexanderHD27 Date: Mon, 30 Dec 2024 02:23:38 +0100 Subject: [PATCH] Implemented UART_CTRL Interface (missing Hardware implementation) --- i2c-hub/backend/Protocol.md | 3 + .../src/gobotrpc/cmake/CMakeLists.txt | 5 ++ .../src/gobotrpc/error_msg.cpp | 4 +- .../src/gobotrpc/include/gobotrpc.hpp | 1 + .../src/gobotrpc/include/uart_ctrl.hpp | 58 +++++++++++++++ .../gobotrpc/include/uart_ctrl_hardware.hpp | 8 ++ .../i2c-hub-firmware/src/gobotrpc/init.cpp | 1 + .../i2c-hub-firmware/src/gobotrpc/rx.cpp | 5 ++ .../src/gobotrpc/uart_ctrl/uart_ctrl_base.cpp | 17 +++++ .../uart_ctrl/uart_ctrl_registers.cpp | 22 ++++++ .../src/gobotrpc/uart_ctrl/uart_ctrl_rx.cpp | 73 +++++++++++++++++++ .../src/gobotrpc/uart_ctrl/uart_ctrl_tx.cpp | 49 +++++++++++++ .../firmware/i2c-hub-firmware/src/main.cpp | 4 +- 13 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 i2c-hub/backend/Protocol.md create mode 100644 i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl.hpp create mode 100644 i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl_hardware.hpp create mode 100644 i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_base.cpp create mode 100644 i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_registers.cpp create mode 100644 i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_rx.cpp create mode 100644 i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_tx.cpp diff --git a/i2c-hub/backend/Protocol.md b/i2c-hub/backend/Protocol.md new file mode 100644 index 0000000..f7b849f --- /dev/null +++ b/i2c-hub/backend/Protocol.md @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdc093813757df0c3d3920fe9066e93c0fb6e36e7ed911db3a29ba996ff46be6 +size 1931 diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/cmake/CMakeLists.txt b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/cmake/CMakeLists.txt index 16ef9f0..60a81c2 100644 --- a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/cmake/CMakeLists.txt +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/cmake/CMakeLists.txt @@ -3,6 +3,11 @@ add_library(GobotRPC STATIC ${CMAKE_CURRENT_LIST_DIR}/../init.cpp ${CMAKE_CURRENT_LIST_DIR}/../protocol.cpp ${CMAKE_CURRENT_LIST_DIR}/../error_msg.cpp + + ${CMAKE_CURRENT_LIST_DIR}/../uart_ctrl/uart_ctrl_base.cpp + ${CMAKE_CURRENT_LIST_DIR}/../uart_ctrl/uart_ctrl_registers.cpp + ${CMAKE_CURRENT_LIST_DIR}/../uart_ctrl/uart_ctrl_rx.cpp + ${CMAKE_CURRENT_LIST_DIR}/../uart_ctrl/uart_ctrl_tx.cpp ) target_include_directories(GobotRPC PUBLIC diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/error_msg.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/error_msg.cpp index 7b52875..4773219 100644 --- a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/error_msg.cpp +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/error_msg.cpp @@ -23,9 +23,9 @@ char * mapFrameSubmitionResult2String(FrameSubmitionResult res) { void GobotRPCParser::print_out_slots() { for(int i = 0; i < NUM_SLOTS; i++) { - printf("[%d] %d%d (%x-%d) %d T%08x ", i, + printf("[%d] %d%d (%x-%d) %d T%08x S=%02d ", i, buffer[i].is_complete, buffer[i].is_in_use, buffer[i].sender_address, - buffer[i].rpcNum, buffer[i].type, buffer[i].timestamp + buffer[i].rpcNum, buffer[i].type, buffer[i].timestamp, buffer[i].length ); for(int j = 0; j < MAX_PAGE_SIZES; j++) { diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/gobotrpc.hpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/gobotrpc.hpp index ca45337..bb38770 100644 --- a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/gobotrpc.hpp +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/gobotrpc.hpp @@ -25,6 +25,7 @@ struct RPC_RX_PackageSlot { enum RPCType type; uint32_t used_bit_masked; uint32_t timestamp; + size_t length; }; struct RPCPackage { diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl.hpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl.hpp new file mode 100644 index 0000000..93841d7 --- /dev/null +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl.hpp @@ -0,0 +1,58 @@ +#pragma once +#include +#include "gobotrpc.hpp" +#include "uart_ctrl_hardware.hpp" + +struct HubInfo { + uint8_t slotNumbers; +}; + +typedef void (*UART_CTRL_Callback_Packet)(void * args, RPCPackage package); +typedef void (*UART_CTRL_Callback_PerformScan)(void * args, bool enable); +typedef void (*UART_CTRL_Callback_ReqSlotUpdate)(void * args, bool enable); +typedef HubInfo (*UART_CTRL_Callback_GetInfo)(void * args); + +void externalCallback_RX(void * args, char * data, size_t length); + +class UART_CTRL_Interface { +private: + UART_CTRL_Callback_Packet packetCallback; + UART_CTRL_Callback_PerformScan performScanCallback; + UART_CTRL_Callback_ReqSlotUpdate reqSlotUpdateCallback; + UART_CTRL_Callback_GetInfo getInfoCallback; + void * packetCallbackArgs; + void * performScanCallbackArgs; + void * reqSlotUpdateCallbackArgs; + void * getInfoCallbackArgs; + + I_UART_CTRL_Hardware_Handler * handler; +protected: + void onRX_Packet(char * data, size_t length); + void onRX_PerformScan(char * data, size_t length); + void onRX_ReqSlotUpdate(char * data, size_t length); + void onRX_GetInfo(char * data, size_t length); + +public: + UART_CTRL_Interface(I_UART_CTRL_Hardware_Handler * handler); + void onRX(char * data, size_t length); + + void pushPacket(RPCPackage package); + void pushScanResulst(uint32_t addr, bool running); + void pushPackageSlotUpdate(bool complete, bool inUse, uint32_t slot, uint32_t addr, uint32_t timestamp, uint32_t bits); + void pushInfo(uint8_t slotNumbers); + + void registerCallback_Packet(UART_CTRL_Callback_Packet callback, void * args); + void registerCallback_PerformScan(UART_CTRL_Callback_PerformScan callback, void * args); + void registerCallback_ReqSlotUpdate(UART_CTRL_Callback_ReqSlotUpdate callback, void * args); + void registerCallback_GetInfo(UART_CTRL_Callback_GetInfo callback, void * args); +}; + + +enum UART_CTRL_Command_ID { + UART_CMD_PACKET = 0x01, // Host <-> Hub + UART_CMD_PERFORM_SCAN = 0x02, // Host -> Hub + UART_CMD_SCAN_RESULT = 0x03, // Hub -> Host + UART_CMD_SLOT_UPDATE = 0x04, // Hub -> Host + UART_CMD_REQ_SLOT_UPDATE = 0x05, // Host -> Hub + UART_CMD_INFO = 0xff, // Host -> Hub, Hub -> Host +}; \ No newline at end of file diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl_hardware.hpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl_hardware.hpp new file mode 100644 index 0000000..91aa403 --- /dev/null +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/include/uart_ctrl_hardware.hpp @@ -0,0 +1,8 @@ +#pragma once +typedef void (*UART_CTRL_Callback_RX)(void * args, char * data, size_t length); + +class I_UART_CTRL_Hardware_Handler { +public: + virtual void send(char * data, size_t length) = 0; + virtual void registerCallback(UART_CTRL_Callback_RX) = 0; +}; diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/init.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/init.cpp index de8e827..fbcb865 100644 --- a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/init.cpp +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/init.cpp @@ -10,6 +10,7 @@ GobotRPCParser::GobotRPCParser() { buffer[i].sender_address = 0; buffer[i].rpcNum = Invalid; buffer[i].type = INVALID; + buffer[i].length = 0; memset(buffer[i].buffer, 0, MAX_PAGE_SIZES); } diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/rx.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/rx.cpp index 92aec4a..509769a 100644 --- a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/rx.cpp +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/rx.cpp @@ -2,6 +2,8 @@ #include "protocol.hpp" #include +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) + RPCHeader parseRPCHeader(char data) { RPCHeader header; @@ -50,6 +52,7 @@ FrameSubmitionResult GobotRPCParser::submit_frame(char *data, size_t length, uin insertFrameInPackageSlot(&this->buffer[slotNum], data, header.segment, length); this->buffer[slotNum].timestamp = timestamp; + this->buffer[slotNum].length = MAX(this->buffer[slotNum].length, header.segment*7 + (length - 1)); volatile FrameSubmitionResult res = getPackageStatus(&(this->buffer[slotNum])); if (res == COMPLEATE) { @@ -112,6 +115,7 @@ void GobotRPCParser::retrivePackage(RPCPackage *dest, int index) { dest->addr = buffer[index].sender_address; dest->rpcNum = buffer[index].rpcNum; dest->type = buffer[index].type; + dest->length = buffer[index].length; freePackageSlot(index); } @@ -124,4 +128,5 @@ void GobotRPCParser::freePackageSlot(size_t index) { this->buffer[index].sender_address = 0; this->buffer[index].rpcNum = Invalid; this->buffer[index].type = INVALID; + this->buffer[index].length = 0; } \ No newline at end of file diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_base.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_base.cpp new file mode 100644 index 0000000..94d7c43 --- /dev/null +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_base.cpp @@ -0,0 +1,17 @@ +#include "uart_ctrl.hpp" +#include + +UART_CTRL_Interface::UART_CTRL_Interface(I_UART_CTRL_Hardware_Handler *handler) { + this->handler = handler; + handler->registerCallback(externalCallback_RX); + + packetCallback = nullptr; + performScanCallback = nullptr; + getInfoCallback = nullptr; + + packetCallbackArgs = nullptr; + performScanCallbackArgs = nullptr; + getInfoCallbackArgs = nullptr; +} + + diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_registers.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_registers.cpp new file mode 100644 index 0000000..cdeb0f8 --- /dev/null +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_registers.cpp @@ -0,0 +1,22 @@ +#include "uart_ctrl.hpp" +#include + +void UART_CTRL_Interface::registerCallback_Packet(UART_CTRL_Callback_Packet callback, void *args) { + packetCallback = callback; + packetCallbackArgs = args; +} + +void UART_CTRL_Interface::registerCallback_PerformScan(UART_CTRL_Callback_PerformScan callback, void *args) { + performScanCallback = callback; + performScanCallbackArgs = args; +} + +void UART_CTRL_Interface::registerCallback_ReqSlotUpdate(UART_CTRL_Callback_ReqSlotUpdate callback, void *args) { + reqSlotUpdateCallback = callback; + reqSlotUpdateCallbackArgs = args; +} + +void UART_CTRL_Interface::registerCallback_GetInfo(UART_CTRL_Callback_GetInfo callback, void *args) { + getInfoCallback = callback; + getInfoCallbackArgs = args; +} \ No newline at end of file diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_rx.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_rx.cpp new file mode 100644 index 0000000..764a66f --- /dev/null +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_rx.cpp @@ -0,0 +1,73 @@ +#include "uart_ctrl.hpp" +#include "gobotrpc.hpp" +#include + +void externalCallback_RX(void * args, char * data, size_t length) { + UART_CTRL_Interface *interface = (UART_CTRL_Interface *)args; + interface->onRX(data, length); +} + +void UART_CTRL_Interface::onRX(char * data, size_t length) { + uint8_t cmd = data[0]; + switch (cmd) { + case UART_CMD_PACKET: + onRX_Packet(data, length); + break; + + case UART_CMD_PERFORM_SCAN: + onRX_PerformScan(data, length); + break; + + case UART_CMD_REQ_SLOT_UPDATE: + onRX_ReqSlotUpdate(data, length); + break; + + case UART_CMD_INFO: + onRX_GetInfo(data, length); + break; + + default: + break; + } +} + +void UART_CTRL_Interface::onRX_Packet(char *data, size_t length) { + if(length < 7) + return; + + + if (packetCallback != nullptr) { + RPCPackage package; + package.length = data[1]; + package.type = RPCType(data[2] & 0b11); + package.rpcNum = RPCNumber(data[2] >> 4); + memcpy(&package.addr, &data[3], 4); + memcpy(package.buffer, &data[7], package.length); + + packetCallback(packetCallbackArgs, package); + } +} + +void UART_CTRL_Interface::onRX_PerformScan(char *data, size_t length) { + if(length < 2) + return; + + if (performScanCallback != nullptr) + performScanCallback(performScanCallbackArgs, data[1] == 1); +} + +void UART_CTRL_Interface::onRX_ReqSlotUpdate(char *data, size_t length) { + if (length < 2) + return; + + if (reqSlotUpdateCallback != nullptr) + reqSlotUpdateCallback(reqSlotUpdateCallbackArgs, data[1] == 1); +} + +void UART_CTRL_Interface::onRX_GetInfo(char *data, size_t length) { + if (length < 1) + return; + + if (getInfoCallback != nullptr) + getInfoCallback(getInfoCallbackArgs); +} \ No newline at end of file diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_tx.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_tx.cpp new file mode 100644 index 0000000..e820e72 --- /dev/null +++ b/i2c-hub/firmware/i2c-hub-firmware/src/gobotrpc/uart_ctrl/uart_ctrl_tx.cpp @@ -0,0 +1,49 @@ +#include "uart_ctrl.hpp" +#include + +// This function should be called when a package is sent +void UART_CTRL_Interface::pushPacket(RPCPackage package) { + char buffer[MAX_PAGE_SIZES + 7]; + + buffer[0] = UART_CMD_PACKET; + buffer[1] = package.length; + buffer[2] = package.type | (package.rpcNum << 4); + memcpy(&buffer[3], &package.addr, 4); + memcpy(&buffer[7], package.buffer, package.length); + + handler->send(buffer, package.length + 2); +} + +void UART_CTRL_Interface::pushScanResulst(uint32_t addr, bool running) { + char buffer[7]; + + buffer[0] = UART_CMD_SCAN_RESULT; + buffer[1] = running ? 1 : 0; + memcpy(&buffer[2], &addr, 4); + buffer[6] = 0; // This is where the type would go + + handler->send(buffer, 7); +} + +void UART_CTRL_Interface::pushPackageSlotUpdate(bool complete, bool inUse, uint32_t slot, uint32_t addr, uint32_t timestamp, uint32_t bits) { + char buffer[16]; + + buffer[0] = UART_CMD_SLOT_UPDATE; + buffer[1] = complete ? 1 : 0; + buffer[2] = inUse ? 1 : 0; + buffer[3] = slot; + memcpy(&buffer[4], &addr, 4); + memcpy(&buffer[8], ×tamp, 4); + memcpy(&buffer[12], &bits, 4); + + handler->send(buffer, 14); +} + +void UART_CTRL_Interface::pushInfo(uint8_t slotNumbers) { + char buffer[2]; + + buffer[0] = UART_CMD_INFO; + buffer[1] = slotNumbers; + + handler->send(buffer, 2); +} \ No newline at end of file diff --git a/i2c-hub/firmware/i2c-hub-firmware/src/main.cpp b/i2c-hub/firmware/i2c-hub-firmware/src/main.cpp index 553cb8a..e935881 100644 --- a/i2c-hub/firmware/i2c-hub-firmware/src/main.cpp +++ b/i2c-hub/firmware/i2c-hub-firmware/src/main.cpp @@ -21,7 +21,7 @@ void TaskFn(void * args) { char data2[] = "\x84\xaa\xbb"; - rpcRXParser.submit_frame(data0, 7, 0x42, xTaskGetTickCount()); + rpcRXParser.submit_frame(data2, 3, 0x42, xTaskGetTickCount()); rpcRXParser.print_out_slots(); printf("\n"); @@ -39,7 +39,7 @@ void TaskFn(void * args) { rpcRXParser.print_out_slots(); printf("\n"); - rpcRXParser.submit_frame(data2, 3, 0x42, xTaskGetTickCount()); + rpcRXParser.submit_frame(data0, 7, 0x42, xTaskGetTickCount()); rpcRXParser.print_out_slots(); printf("\n");