From 935fbca1f9ed2f48fc893a0cddc42a4cbefbcd8d Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Fri, 8 Mar 2024 17:02:08 +0100 Subject: [PATCH] introduced AltColorHeader --- README.md | 19 +++++++---------- include/DMDUtil/DMD.h | 7 ++++++- src/DMD.cpp | 10 +++++---- src/dmdServer.cpp | 47 ++++++++++++++++++++++++++----------------- 4 files changed, 48 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index fc17c70..cf309e5 100644 --- a/README.md +++ b/README.md @@ -66,14 +66,12 @@ The DmdStreamHeader is defined as a struct: ``` struct DMDUtil::DMD::StreamHeader { - char protocol[10] = "DMDStream"; // \0 terminated string + char header[10] = "DMDStream"; // \0 terminated string uint8_t version = 1; - Mode mode = Mode::Data; // int + Mode mode = Mode::Data; // int uint16_t width = 0; uint16_t height = 0; uint32_t length = 0; - char name[16] = {0}; // \0 terminated string, ROM name - char path[256] = {0}; // \0 terminated string, altcolor path }; ``` @@ -97,9 +95,11 @@ Each pixel consist of one uint16_t having its color encoded in 16bit according t `Mode::Data` is a serialized stream of the `DMDUtil::DMD::Update` struct. It will be sent from a client which uses libdmdutil itself (for example VPX Standalone or PPUC). In case of `Mode::Data`, `StreamHeader.width`, `StreamHeader.height` and `StreamHeader.length` should be set to zero. -`StreamHeader.name` and `StreamHeader.path` have to be set to the ROM name and the altcolor path if Serum colorization should be used. -The data itself contains that information and a lot of additional data like instructions to map alphanummeric displays to DMDs or -colorizations of grayscale content. +There will be an additional `AltColorHeader` header sent before the data to the transmit the ROM name and the altcolor path +in case Serum colorization should be used. +The data itself contains a lot of additional data like instructions to map alphanummeric displays to DMDs or colorizations of +grayscale content. + So if you want to write a general purpose client to display images or text, you're adviced to use `Mode::RGB24` or `Mode::RGB216`! ### Notes @@ -108,9 +108,6 @@ At the moment, `StreamHeader.length` is a redundant information as it could be c `StreamHeader.height` in combination with `StreamHeader.mode`. But if data compression will be supported in future versions, it will become important. -In case of `Mode::RGB24` and `Mode::RGB216` it seems strange to append 16 + 256 zeros to the end of the header. -But for effency and maintainability we decided to work with a fixed header size for all modes. - ### Examples To send a RGB24 image of 4x2 pixels, you have to sent these two packages: @@ -122,8 +119,6 @@ To send a RGB24 image of 4x2 pixels, you have to sent these two packages: 0x04 0x00 // width 4 (if your system is big endian, the byte order needs to be swapped) 0x02 0x00 // height 2 (if your system is big endian, the byte order needs to be swapped) 0x18 0x00 0x00 0x00 // length 24 (if your system is big endian, the byte order needs to be swapped) -0x00 ... // 16 bytes of zeros -0x00 ... // 256 bytes of zeros ``` ``` diff --git a/include/DMDUtil/DMD.h b/include/DMDUtil/DMD.h index e1a9758..8ff9303 100644 --- a/include/DMDUtil/DMD.h +++ b/include/DMDUtil/DMD.h @@ -97,12 +97,17 @@ class DMDUTILAPI DMD struct StreamHeader { - char protocol[10] = "DMDStream"; + char header[10] = "DMDStream"; uint8_t version = 1; Mode mode = Mode::Data; // int uint16_t width = 0; uint16_t height = 0; uint32_t length = 0; + }; + + struct AltColorHeader + { + char header[9] = "AltColor"; char name[DMDUTIL_MAX_NAME_SIZE] = {0}; char path[DMDUTIL_MAX_ALTCOLORPATH_SIZE] = {0}; }; diff --git a/src/DMD.cpp b/src/DMD.cpp index f8c687a..7e5bd7d 100644 --- a/src/DMD.cpp +++ b/src/DMD.cpp @@ -297,10 +297,12 @@ void DMD::QueueUpdate(Update dmdUpdate) if (m_pDMDServerConnector) { - StreamHeader header; - strcpy(header.name, m_romName); - strcpy(header.path, m_altColorPath); - m_pDMDServerConnector->write_n(&header, sizeof(StreamHeader)); + StreamHeader streamHeader; + m_pDMDServerConnector->write_n(&streamHeader, sizeof(StreamHeader)); + AltColorHeader altColorHeader; + strcpy(altColorHeader.name, m_romName); + strcpy(altColorHeader.path, m_altColorPath); + m_pDMDServerConnector->write_n(&altColorHeader, sizeof(AltColorHeader)); m_pDMDServerConnector->write_n(&dmdUpdate, sizeof(Update)); } }) diff --git a/src/dmdServer.cpp b/src/dmdServer.cpp index 381d167..0d091a0 100644 --- a/src/dmdServer.cpp +++ b/src/dmdServer.cpp @@ -47,7 +47,7 @@ void DMDUTILCALLBACK LogCallback(const char* format, va_list args) void run(sockpp::tcp_socket sock, uint32_t threadId) { uint8_t buffer[sizeof(DMDUtil::DMD::Update)]; - DMDUtil::DMD::StreamHeader* pHeader = (DMDUtil::DMD::StreamHeader*)malloc(sizeof(DMDUtil::DMD::StreamHeader)); + DMDUtil::DMD::StreamHeader* pStreamHeader = (DMDUtil::DMD::StreamHeader*)malloc(sizeof(DMDUtil::DMD::StreamHeader)); ssize_t n; while ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::StreamHeader))) > 0) @@ -56,44 +56,55 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) { // At the moment the server only listens on localhost. // Therefore, we don't have to take care about litte vs. big endian and can use memcpy. - memcpy(pHeader, buffer, n); - if (strcmp(pHeader->protocol, "DMDStream") == 0 && pHeader->version == 1) + memcpy(pStreamHeader, buffer, n); + if (strcmp(pStreamHeader->header, "DMDStream") == 0 && pStreamHeader->version == 1) { - switch (pHeader->mode) + switch (pStreamHeader->mode) { case DMDUtil::DMD::Mode::Data: - if ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::Update))) == sizeof(DMDUtil::DMD::Update) && + if ((n = sock.read_n(buffer, sizeof(DMDUtil::DMD::AltColorHeader))) == + sizeof(DMDUtil::DMD::AltColorHeader) && threadId == currentThreadId) { - DMDUtil::DMD::Update data; - memcpy(&data, buffer, n); + DMDUtil::DMD::AltColorHeader altColorHeader; + memcpy(&altColorHeader, buffer, n); - if (data.width <= DMDSERVER_MAX_WIDTH && data.height <= DMDSERVER_MAX_HEIGHT) + if (strcmp(altColorHeader.header, "AltColor") == 0 && + (n = sock.read_n(buffer, sizeof(DMDUtil::DMD::Update))) == sizeof(DMDUtil::DMD::Update) && + threadId == currentThreadId) { - pDmd->SetRomName(pHeader->name); - pDmd->SetAltColorPath(pHeader->path); + DMDUtil::DMD::Update data; + memcpy(&data, buffer, n); - pDmd->QueueUpdate(data); + if (data.width <= DMDSERVER_MAX_WIDTH && data.height <= DMDSERVER_MAX_HEIGHT) + { + pDmd->SetRomName(altColorHeader.name); + pDmd->SetAltColorPath(altColorHeader.path); + + pDmd->QueueUpdate(data); + } } } break; case DMDUtil::DMD::Mode::RGB16: - if ((n = sock.read_n(buffer, pHeader->length)) == pHeader->length && threadId == currentThreadId && - pHeader->width <= DMDSERVER_MAX_WIDTH && pHeader->height <= DMDSERVER_MAX_HEIGHT) + if ((n = sock.read_n(buffer, pStreamHeader->length)) == pStreamHeader->length && + threadId == currentThreadId && pStreamHeader->width <= DMDSERVER_MAX_WIDTH && + pStreamHeader->height <= DMDSERVER_MAX_HEIGHT) { // At the moment the server only listens on localhost. // Therefore, we don't have to take care about litte vs. big endian and can use the buffer as uint16_t as // it is. - pDmd->UpdateRGB16Data((uint16_t*)buffer, pHeader->width, pHeader->height); + pDmd->UpdateRGB16Data((uint16_t*)buffer, pStreamHeader->width, pStreamHeader->height); } break; case DMDUtil::DMD::Mode::RGB24: - if ((n = sock.read_n(buffer, pHeader->length)) == pHeader->length && threadId == currentThreadId && - pHeader->width <= DMDSERVER_MAX_WIDTH && pHeader->height <= DMDSERVER_MAX_HEIGHT) + if ((n = sock.read_n(buffer, pStreamHeader->length)) == pStreamHeader->length && + threadId == currentThreadId && pStreamHeader->width <= DMDSERVER_MAX_WIDTH && + pStreamHeader->height <= DMDSERVER_MAX_HEIGHT) { - pDmd->UpdateRGB24Data(buffer, pHeader->width, pHeader->height); + pDmd->UpdateRGB24Data(buffer, pStreamHeader->width, pStreamHeader->height); } break; @@ -113,7 +124,7 @@ void run(sockpp::tcp_socket sock, uint32_t threadId) threads.erase(remove(threads.begin(), threads.end(), threadId), threads.end()); currentThreadId = threads.back(); - free(pHeader); + free(pStreamHeader); } int main(int argc, char* argv[])