diff --git a/CLC-qthing/SiliconTorch/CyanBus.cpp b/CLC-qthing/SiliconTorch/CyanBus.cpp index b53af7da117711e9e22f0f4e334845ac9aa76c64..d3b6b1cb03d4905dc75465ecd481c331ba37425e 100644 --- a/CLC-qthing/SiliconTorch/CyanBus.cpp +++ b/CLC-qthing/SiliconTorch/CyanBus.cpp @@ -1,6 +1,7 @@ #include "CyanBus.hpp" // C++ system level +#include <vector> #include <cstring> // memset, strncmp #include <cstdlib> // TODO: is this for memcpy? #include <functional> @@ -31,6 +32,13 @@ static u16 getLength(const u8* buffer) { } +// TODO: do some locking for thread-safety (or build some generalized solution for this kind of counter 😉) +static u8 nextUartChannel() { + static u8 uartChannel = 1; + return uartChannel++; +} + + namespace SiliconTorch { namespace CyanBus { @@ -39,7 +47,46 @@ namespace SiliconTorch { const char* const HEADER = "fxCyan"; - CyanBus::CyanBus(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate, u8 uartChannel) : tx(tx), rx(rx), de(de), re(re), uartChannel(uartChannel) { + static std::vector<CyanBus*> interfaces; + + u32 registerCyanBusInterface(CyanBus* iface) { + if (iface == NULL) return 0xFFFFFFFF; + + u32 number = 0; + + for (const auto& cb : interfaces) { + if (cb == iface) { + ESP_LOGW(TAG, "equality of (obj*)& and (obj*): ✅ Please remove this line from CyanBus.cpp!"); + return number; + } + number++; + } + + interfaces.push_back(iface); + + return number; + } + + u32 countCyanBusInterfaces() { + return interfaces.size(); + } + + CyanBus* getInterface(u32 number) { + if (number >= countCyanBusInterfaces()) return NULL; + else return interfaces[number]; + } + + u32 createCyanBusInterface(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate) { + return registerCyanBusInterface ( + new CyanBus(tx, rx, de, re, baudRate) + ); + } + + + CyanBus::CyanBus(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate, u8 uartChannel) : tx(tx), rx(rx), de(de), re(re) { + + if (uartChannel == UART_CHANNEL_AUTO) this->uartChannel = nextUartChannel(); + else this->uartChannel = uartChannel; u64 bitMask = 0; diff --git a/CLC-qthing/SiliconTorch/CyanBus.hpp b/CLC-qthing/SiliconTorch/CyanBus.hpp index f6c8d003e0a50635ad84128c2074b283b5b470cd..2bd8e895a90b64999dc688ba3bdc794684f56e02 100644 --- a/CLC-qthing/SiliconTorch/CyanBus.hpp +++ b/CLC-qthing/SiliconTorch/CyanBus.hpp @@ -27,6 +27,8 @@ namespace SiliconTorch { // CyanBus envelope header extern const char* const HEADER; + constexpr u8 UART_CHANNEL_AUTO = 0xFF; + typedef struct { const u8* payload; @@ -39,9 +41,17 @@ namespace SiliconTorch { } PacketMetrics; + class CyanBus; + + u32 createCyanBusInterface(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate = 115200); + u32 registerCyanBusInterface(CyanBus* iface); + u32 countCyanBusInterfaces(); + CyanBus* getInterface(u32 number = 0); + + class CyanBus { public: - CyanBus(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate = 115200, u8 uartChannel = 1); + CyanBus(u8 tx, u8 rx, u8 de, u8 re, u32 baudRate = 115200, u8 uartChannel = UART_CHANNEL_AUTO); u32 getBaudRate(); void setBaudRate(u32 baudRate); diff --git a/CLC-qthing/SiliconTorch/Service/CyanBus.cpp b/CLC-qthing/SiliconTorch/Service/CyanBus.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c0ffa8fb3831e66c150a8106cd932dfbdbe2758 --- /dev/null +++ b/CLC-qthing/SiliconTorch/Service/CyanBus.cpp @@ -0,0 +1,90 @@ +#include "CyanBus.hpp" + +// C++ system level +#include <cstdio> // sprintf +// #include <functional> + +// ESP32 specific +#include "esp_log.h" +#include "driver/gpio.h" + +// project specific +#include <Types.hpp> +#include "SiliconTorch/NVSExplorer.hpp" + +// qthing stuff +#include <qthing> +#include "SiliconTorch/CyanBus.hpp" + + + + +namespace SiliconTorch { + + namespace Service { + + void CyanBus::init() { + setName("CyanBus"); + setNameSpace("CyanBus"); + } + + void CyanBus::start() { + + for (u8 idx = 0; idx < MAX_INTERFACES; idx++) { + + InterfaceCfg cfg = readInterfaceData(idx); + + if (!cfg.valid) break; + + ESP_LOGI(getName().c_str(), "Configuring: CyanBus{ tx[ %d ] rx[ %d ] de[ %d ] re[ %d ] baud[ %d ] interface[ cb%d ] }", + cfg.tx, + cfg.rx, + cfg.de, + cfg.re, + cfg.baud, + idx + ); + + SiliconTorch::CyanBus::createCyanBusInterface(cfg.tx, cfg.rx, cfg.de, cfg.re, cfg.baud); + + } + + } + + + CyanBus::InterfaceCfg CyanBus::readInterfaceData(u32 number) const { + + NVSExplorer::NVSExplorer& nvs = NVSExplorer::NVSExplorer::instance(); + + InterfaceCfg cfg; + + char tmp[32]; + + std::snprintf(tmp, sizeof(tmp), "cb%d_tx", number); + cfg.tx = nvs.getUnsignedInt(getNameSpace(), std::string(tmp), cfg.tx); + + std::snprintf(tmp, sizeof(tmp), "cb%d_rx", number); + cfg.rx = nvs.getUnsignedInt(getNameSpace(), std::string(tmp), cfg.rx); + + std::snprintf(tmp, sizeof(tmp), "cb%d_de", number); + cfg.de = nvs.getUnsignedInt(getNameSpace(), std::string(tmp), cfg.de); + + std::snprintf(tmp, sizeof(tmp), "cb%d_re", number); + cfg.re = nvs.getUnsignedInt(getNameSpace(), std::string(tmp), cfg.re); + + std::snprintf(tmp, sizeof(tmp), "cb%d_baud", number); + cfg.baud = nvs.getUnsignedInt(getNameSpace(), std::string(tmp), cfg.baud); + + + cfg.valid = cfg.tx < 0xFF + && cfg.rx < 0xFF + && cfg.de < 0xFF + && cfg.re < 0xFF; + + return cfg; + } + + } +} + + diff --git a/CLC-qthing/SiliconTorch/Service/CyanBus.hpp b/CLC-qthing/SiliconTorch/Service/CyanBus.hpp new file mode 100644 index 0000000000000000000000000000000000000000..93746fe71509b34279f98328ee854c792c4dc90e --- /dev/null +++ b/CLC-qthing/SiliconTorch/Service/CyanBus.hpp @@ -0,0 +1,61 @@ +#pragma once + +// C++ system level +// #include <cstring> // memset, strncmp +// #include <cstdlib> // TODO: is this for memcpy? +// #include <functional> + +// ESP32 specific +#include "esp_log.h" + +// project specific +#include <Types.hpp> +#include "Service.hpp" + +// qthing stuff +#include "SiliconTorch/FxCyanRGB8.hpp" +// #include <qthing> + + +namespace SiliconTorch { + + namespace Service { + + class CyanBus : public ServiceManager::Service { + + public: + + + void init(); + + void start(); + + + static const u8 MAX_INTERFACES = 2; // Limitted to the available UART HW units + + + typedef struct { + u8 tx = 0xFF; + u8 rx = 0xFF; + u8 de = 0xFF; + u8 re = 0xFF; + u32 baud = 115200; + bool valid = false; + } InterfaceCfg; + + + + InterfaceCfg readInterfaceData(u32 number) const; + + + // TODO: should we block copy/assignment by default…? + CyanBus() {}; + CyanBus(const CyanBus&) = delete; + CyanBus& operator=(CyanBus const&) = delete; + + private: + + }; + + } +} diff --git a/CLC-qthing/SiliconTorch/Service/__services__.cpp b/CLC-qthing/SiliconTorch/Service/__services__.cpp index def22a373d801058aebd3c935e8b2b118a8211fa..1c4dd7aab4f1ceafc7f83f71e64b4c100a6a109c 100644 --- a/CLC-qthing/SiliconTorch/Service/__services__.cpp +++ b/CLC-qthing/SiliconTorch/Service/__services__.cpp @@ -2,6 +2,7 @@ // our services #include "FxCyanF.hpp" +#include "CyanBus.hpp" #include "FxPublish.hpp" #include "CyanStripe.hpp" @@ -15,6 +16,7 @@ namespace SiliconTorch { void registerSiliconTorchServices(ServiceManager* mgr) { mgr->registerService(new SiliconTorch::Service::FxCyanF()); + mgr->registerService(new SiliconTorch::Service::CyanBus()); mgr->registerService(new SiliconTorch::Service::FxPublish()); mgr->registerService(new SiliconTorch::Service::CyanStripe::CyanStripe());