From 0ec6327c2f435e5600f1393d04ab25cd20d286f7 Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Wed, 13 Dec 2023 17:15:15 +0100 Subject: [PATCH 1/7] new wifi mode --- src/main.cpp | 1161 ++++++++++++++++++++++++++++---------------------- 1 file changed, 651 insertions(+), 510 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4afe8b0..e072c7b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,6 @@ #define ZEDMD_VERSION_MAJOR 3 // X Digits #define ZEDMD_VERSION_MINOR 3 // Max 2 Digits -#define ZEDMD_VERSION_PATCH 1 // Max 2 Digits +#define ZEDMD_VERSION_PATCH 2 // Max 2 Digits #ifdef ZEDMD_128_64_2 #define PANEL_WIDTH 128 // Width: number of LEDs for 1 panel. @@ -58,6 +58,7 @@ // 26: turn on flow control version 2 // 27: set WiFi SSID // 28: set WiFi password +// 29: set WiFi port // 30: save settings // 31: reset // 32: get version string, returns (int8) major, (int8) minor, (int8) patch level @@ -82,13 +83,30 @@ #include #include -const char *ssid = "****"; -const char *pwd = "****"; - -uint8_t udpCurrentFrameId = 255; +String ssid; +String pwd; +uint16_t port; AsyncUDP udp; IPAddress ip; + +unsigned long rotNextRotationTime[1]; +#else +#ifdef ZEDMD_128_64_2 +uint8_t doubleBuffer[TOTAL_HEIGHT][TOTAL_WIDTH] = {0}; +uint8_t existsBuffer[TOTAL_HEIGHT][TOTAL_WIDTH / 2] = {0}; +#else +uint8_t doubleBuffer[TOTAL_BYTES] = {0}; +#endif + +// color rotation +unsigned char rotFirstColor[MAX_COLOR_ROTATIONS]; +unsigned char rotAmountColors[MAX_COLOR_ROTATIONS]; +unsigned int rotStepDurationTime[MAX_COLOR_ROTATIONS]; +unsigned long rotNextRotationTime[MAX_COLOR_ROTATIONS]; +unsigned char tmpColor[3] = {0}; + +bool upscaling = true; #endif // Pinout derived from ESP32-HUB75-MatrixPanel-I2S-DMA.h @@ -150,23 +168,7 @@ unsigned char *palette; unsigned char *renderBuffer; uint8_t renderBufferInUse = 0; // 0: not used; 1: USB; 2: WiFi -#ifdef ZEDMD_128_64_2 -uint8_t doubleBuffer[TOTAL_HEIGHT][TOTAL_WIDTH] = {0}; -uint8_t existsBuffer[TOTAL_HEIGHT][TOTAL_WIDTH / 2] = {0}; -#else -uint8_t doubleBuffer[TOTAL_BYTES] = {0}; -#endif - -// color rotation -unsigned char rotFirstColor[MAX_COLOR_ROTATIONS]; -unsigned char rotAmountColors[MAX_COLOR_ROTATIONS]; -unsigned int rotStepDurationTime[MAX_COLOR_ROTATIONS]; -unsigned long rotNextRotationTime[MAX_COLOR_ROTATIONS]; -unsigned char tmpColor[3] = { 0 }; - - bool mode64 = false; -bool upscaling = true; int RomWidth = 128, RomHeight = 32; int RomWidthPlane = 128 >> 3; @@ -297,15 +299,17 @@ void ClearScreen() { dma_display->clearScreen(); dma_display->setBrightness8(lumval[lumstep]); - +#ifndef ZEDMD_WIFI #ifdef ZEDMD_128_64_2 memset(doubleBuffer, 0, TOTAL_HEIGHT * TOTAL_WIDTH); memset(existsBuffer, 0, TOTAL_HEIGHT * TOTAL_WIDTH / 2); #else memset(doubleBuffer, 0, TOTAL_BYTES); #endif +#endif } +#ifndef ZEDMD_WIFI bool CmpColor(uint8_t *px1, uint8_t *px2, uint8_t colors) { if (colors == 3) @@ -610,9 +614,11 @@ void ScaleImage(uint8_t colors) free(panel); } +#endif void DrawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { +#ifndef ZEDMD_WIFI #ifdef ZEDMD_128_64_2 uint8_t colors = ((r >> 5) << 5) + ((g >> 5) << 2) + (b >> 6); uint8_t colorsExist = (r ? 8 : 0) + (g ? 4 : 0) + (b ? 2 : 0) + ((r || g || b) ? 1 : 0); @@ -631,8 +637,31 @@ void DrawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) doubleBuffer[pos + 1] = g; doubleBuffer[pos + 2] = b; #endif - +#endif dma_display->drawPixelRGB888(x, y, r, g, b); +#ifndef ZEDMD_WIFI + } +#endif +} + +void fillZoneRaw(uint8_t idx) +{ + uint8_t yOffset = idx / (TOTAL_WIDTH / 16) * 8; + uint8_t xOffset = (idx % (TOTAL_WIDTH / 16)) * 16; + + for (int y = 0; y < 8; y++) + { + for (int x = 0; x < 16; x++) + { + uint16_t pos = (y * 16 + x) * 3; + + DrawPixel( + x + xOffset, + y + yOffset, + renderBuffer[pos + ordreRGB[acordreRGB * 3]], + renderBuffer[pos + ordreRGB[acordreRGB * 3 + 1]], + renderBuffer[pos + ordreRGB[acordreRGB * 3 + 2]]); + } } } @@ -676,6 +705,7 @@ void fillPanelUsingPalette() } } +#ifndef ZEDMD_WIFI void fillPanelUsingChangedPalette(bool *paletteAffected) { int pos; @@ -698,6 +728,7 @@ void fillPanelUsingChangedPalette(bool *paletteAffected) } } } +#endif void LoadOrdreRGB() { @@ -731,9 +762,40 @@ void SaveLum() flum.close(); } +#ifdef ZEDMD_WIFI +bool LoadWiFiConfig() +{ + File wifiConfig = LittleFS.open("/wifi_config.txt", "r"); + if (!wifiConfig) + return false; + + while (wifiConfig.available()) + { + ssid = wifiConfig.readStringUntil('\n'); + pwd = wifiConfig.readStringUntil('\n'); + port = wifiConfig.read(); + } + wifiConfig.close(); + return true; +} + +bool SaveWiFiConfig() +{ + File wifiConfig = LittleFS.open("/wifi_config.txt", "w"); + if (!wifiConfig) + return false; + + wifiConfig.println(ssid); + wifiConfig.println(pwd); + wifiConfig.write(port); + wifiConfig.close(); + return true; +} +#endif + void ledTester(void) { - uint8_t col[3] = { 255,0,0 }; + uint8_t col[3] = {255, 0, 0}; dma_display->fillScreenRGB888(col[ordreRGB[acordreRGB * 3]], col[ordreRGB[acordreRGB * 3 + 1]], col[ordreRGB[acordreRGB * 3 + 2]]); delay(LED_CHECK_DELAY); @@ -787,8 +849,10 @@ void DisplayLogo(void) DisplayText(lumtxt, 16, TOTAL_WIDTH / 2 - 16 / 2 - 2 * 4 / 2, TOTAL_HEIGHT - 5, 255, 255, 255); DisplayLum(); #ifdef ZEDMD_WIFI - if (ip = WiFi.localIP()) { - for (int i = 0; i < 4; i++) { + if (ip = WiFi.localIP()) + { + for (int i = 0; i < 4; i++) + { DisplayNombre(ip[i], 3, i * 3 * 4 + i, 0, 200, 200, 200); } } @@ -853,7 +917,8 @@ void WiFiEvent(WiFiEvent_t event) { case ARDUINO_EVENT_WIFI_STA_GOT_IP: ip = WiFi.localIP(); - for (int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) + { DisplayNombre(ip[i], 3, i * 3 * 4 + i, 0, 200, 200, 200); } break; @@ -899,74 +964,76 @@ void setup() DisplayLogo(); #ifdef ZEDMD_WIFI - WiFi.disconnect(true); - // register event handler - WiFi.onEvent(WiFiEvent); - - // Initiate connection - WiFi.begin(ssid, pwd); - - uint8_t result = WiFi.waitForConnectResult(); + if (LoadWiFiConfig()) + { + WiFi.disconnect(true); + // register event handler + WiFi.onEvent(WiFiEvent); - if(udp.listen(3333)) { - udp.onPacket([](AsyncUDPPacket packet) { - if (packet.length() >= 2) { - if (MireActive) { - ClearScreen(); - MireActive = false; - } + // Initiate connection + WiFi.begin(ssid.c_str(), pwd.c_str()); - if (renderBufferInUse == 0) { - renderBuffer = (uint8_t*)malloc(TOTAL_BYTES); - memset(renderBuffer, 0, TOTAL_BYTES); - renderBufferInUse = 2; - } - else if (renderBufferInUse == 1) { - // Blocked by rendering over USB. - return; - } + uint8_t result = WiFi.waitForConnectResult(); + if (udp.listen(port)) + { + udp.onPacket([](AsyncUDPPacket packet) + { + if (packet.length() >= 2) { + if (MireActive) { + ClearScreen(); + MireActive = false; + } - uint8_t *pPacket = packet.data(); - uint8_t compressed = pPacket[1] & 128; - uint8_t render = pPacket[1] & 64; - uint8_t frameId = pPacket[1] & 63; - - if (render == 64) { - if (frameId == udpCurrentFrameId) { - fillPanelRaw(); - udpCurrentFrameId++; - if (udpCurrentFrameId >= 64) { - udpCurrentFrameId = 0; - } + if (renderBufferInUse == 0) { + renderBufferInUse = 2; + } + else if (renderBufferInUse == 1) { + // Blocked by rendering over USB. + return; } - return; - } - else if (frameId != udpCurrentFrameId) { - fillPanelRaw(); - udpCurrentFrameId = frameId; - } - if (frameId == udpCurrentFrameId) - { - if (compressed == 128) + uint8_t *pPacket = packet.data(); + switch (pPacket[0]) { - mz_ulong uncompressedBufferSize; - mz_ulong udpPayloadSize = packet.length() - 3; + case 10: // clear screen + { + ClearScreen(); + break; + } - int status = mz_uncompress2(&renderBuffer[pPacket[2] * TOTAL_WIDTH * 3], &uncompressedBufferSize, pPacket + 3, (mz_ulong *)&udpPayloadSize); - if (status != MZ_OK) + case 3: // RGB24 { - int tmp_status = (status >= 0) ? status : (-1 * status) + 100; - Say(0, tmp_status); + uint8_t compressed = pPacket[1] & 128; + uint8_t idx = pPacket[1] & 127; + int size = (int)(pPacket[3]) + (((int)pPacket[2]) << 8); + + renderBuffer = (uint8_t*)malloc(16 * 8 * 3); + + if (compressed == 128) + { + mz_ulong uncompressedBufferSize = 16 * 8 * 3; + mz_ulong udpPayloadSize = (mz_ulong) size; + + int status = mz_uncompress2(renderBuffer, &uncompressedBufferSize, &pPacket[4], (mz_ulong *)&udpPayloadSize); + if (status != MZ_OK || uncompressedBufferSize != 16 * 8 * 3) + { + int tmp_status = (status >= 0) ? status : (-1 * status) + 100; + if (debugMode) Say(0, tmp_status); + return; + } + } + else + { + memcpy(renderBuffer, &pPacket[4], size); + } + + fillZoneRaw(idx); + free(renderBuffer); + break; } } - else - { - memcpy(&renderBuffer[pPacket[2] * TOTAL_WIDTH * 3], pPacket + 3, packet.length() - 3); - } - } - } - }); + } }); + } } #endif } @@ -1094,7 +1161,8 @@ bool SerialReadBuffer(unsigned char *pBuffer, unsigned int BufferSize) void updateColorRotations(void) { - bool rotPaletteAffected[64] = { 0 }; +#ifndef ZEDMD_WIFI + bool rotPaletteAffected[64] = {0}; unsigned long actime = millis(); bool rotfound = false; for (int ti = 0; ti < MAX_COLOR_ROTATIONS; ti++) @@ -1119,6 +1187,7 @@ void updateColorRotations(void) if (rotfound == true) fillPanelUsingChangedPalette(rotPaletteAffected); +#endif } bool wait_for_ctrl_chars(void) @@ -1246,7 +1315,8 @@ void loop() mode64 = false; unsigned char c4; - while (Serial.available() == 0); + while (Serial.available() == 0) + ; c4 = Serial.read(); if (debugMode) @@ -1263,539 +1333,610 @@ void loop() switch (c4) { - case 12: // ask for resolution (and shake hands) - { - for (int i = 0; i < N_INTERMEDIATE_CTR_CHARS; i++) - { - Serial.write(CtrlCharacters[i]); - } - Serial.write(TOTAL_WIDTH & 0xff); - Serial.write((TOTAL_WIDTH >> 8) & 0xff); - Serial.write(TOTAL_HEIGHT & 0xff); - Serial.write((TOTAL_HEIGHT >> 8) & 0xff); - handshakeSucceeded = true; - break; - } - - case 2: // set rom frame size + case 12: // ask for resolution (and shake hands) + { + for (int i = 0; i < N_INTERMEDIATE_CTR_CHARS; i++) { - unsigned char tbuf[4]; - if (SerialReadBuffer(tbuf, 4)) - { - RomWidth = (int)(tbuf[0]) + (int)(tbuf[1] << 8); - RomHeight = (int)(tbuf[2]) + (int)(tbuf[3] << 8); - RomWidthPlane = RomWidth >> 3; - if (debugMode) - { - DisplayNombre(RomWidth, 3, TOTAL_WIDTH - 7 * 4, 4, 200, 200, 200); - DisplayNombre(RomHeight, 2, TOTAL_WIDTH - 3 * 4, 4, 200, 200, 200); - } - } - break; + Serial.write(CtrlCharacters[i]); } + Serial.write(TOTAL_WIDTH & 0xff); + Serial.write((TOTAL_WIDTH >> 8) & 0xff); + Serial.write(TOTAL_HEIGHT & 0xff); + Serial.write((TOTAL_HEIGHT >> 8) & 0xff); + handshakeSucceeded = true; + break; + } - case 13: // set serial transfer chunk size + case 2: // set rom frame size + { + unsigned char tbuf[4]; + if (SerialReadBuffer(tbuf, 4)) { - while (Serial.available() == 0) - ; - int tmpSerialTransferChunkSize = ((int)Serial.read()) * 256; - if (tmpSerialTransferChunkSize <= SERIAL_BUFFER) + RomWidth = (int)(tbuf[0]) + (int)(tbuf[1] << 8); + RomHeight = (int)(tbuf[2]) + (int)(tbuf[3] << 8); + RomWidthPlane = RomWidth >> 3; + if (debugMode) { - serialTransferChunkSize = tmpSerialTransferChunkSize; - // Send an (A)cknowledge signal to tell the client that we successfully read the chunk. - Serial.write('A'); + DisplayNombre(RomWidth, 3, TOTAL_WIDTH - 7 * 4, 4, 200, 200, 200); + DisplayNombre(RomHeight, 2, TOTAL_WIDTH - 3 * 4, 4, 200, 200, 200); } - else - { - Serial.write('E'); - } - break; } + break; + } - case 14: // enable serial transfer compression + case 13: // set serial transfer chunk size + { + while (Serial.available() == 0) + ; + int tmpSerialTransferChunkSize = ((int)Serial.read()) * 256; + if (tmpSerialTransferChunkSize <= SERIAL_BUFFER) { - compression = true; + serialTransferChunkSize = tmpSerialTransferChunkSize; + // Send an (A)cknowledge signal to tell the client that we successfully read the chunk. Serial.write('A'); - break; } - - case 15: // disable serial transfer compression + else { - compression = false; - Serial.write('A'); - break; + Serial.write('E'); } + break; + } - case 16: - { - ledTester(); - break; - } + case 14: // enable serial transfer compression + { + compression = true; + Serial.write('A'); + break; + } - case 20: // turn off upscaling - { - upscaling = false; - Serial.write('A'); - break; - } + case 15: // disable serial transfer compression + { + compression = false; + Serial.write('A'); + break; + } - case 21: // turn on upscaling - upscaling = true; - Serial.write('A'); - break; + case 16: + { + Serial.write('A'); + ledTester(); + break; + } - case 22: // set brightness +#ifndef ZEDMD_WIFI + case 20: // turn off upscaling + { + upscaling = false; + Serial.write('A'); + break; + } + + case 21: // turn on upscaling + upscaling = true; + Serial.write('A'); + break; +#endif + + case 22: // set brightness + { + unsigned char tbuf[1]; + if (SerialReadBuffer(tbuf, 1)) { - unsigned char tbuf[1]; - if (SerialReadBuffer(tbuf, 1)) + if (tbuf[0] > 0 && tbuf[0] < 16) { - if (tbuf[0] > 0 && tbuf[0] < 16) - { - lumstep = tbuf[0]; - dma_display->setBrightness8(lumval[lumstep]); - } - else - { - Serial.write('E'); - } + lumstep = tbuf[0]; + dma_display->setBrightness8(lumval[lumstep]); + Serial.write('A'); + } + else + { + Serial.write('E'); } - break; } + break; + } - case 23: // set RGB order + case 23: // set RGB order + { + unsigned char tbuf[1]; + if (SerialReadBuffer(tbuf, 1)) { - unsigned char tbuf[1]; - if (SerialReadBuffer(tbuf, 1)) + if (tbuf[0] >= 0 && tbuf[0] < 6) { - if (tbuf[0] >= 0 && tbuf[0] < 6) - { - acordreRGB = tbuf[0]; - } - else - { - Serial.write('E'); - } + acordreRGB = tbuf[0]; + Serial.write('A'); + } + else + { + Serial.write('E'); } - break; } + break; + } - case 24: // get brightness - { - Serial.write(lumstep); - break; - } + case 24: // get brightness + { + Serial.write(lumstep); + break; + } - case 25: // get RGB order - { - Serial.write(acordreRGB); - break; - } + case 25: // get RGB order + { + Serial.write(acordreRGB); + break; + } - case 26: // turn on flow control version 2 - { - flowControlCounter = 1; - Serial.write('A'); - break; - } + case 26: // turn on flow control version 2 + { + flowControlCounter = 1; + Serial.write('A'); + break; + } - case 30: // save settings +#ifdef ZEDMD_WIFI + // These are one time programmig options over USB until ZeDMD could establish + // the WiFi Connection at startup. When WiFi is finally active, USB is turned off. + case 27: // set WiFi SSID + { + unsigned char tbuf[129]; + if (SerialReadBuffer(tbuf, 129)) { - SaveLum(); - SaveOrdreRGB(); + // tbuf[0] now contains the length of the string + unsigned char *tmp = (unsigned char *)malloc(tbuf[0]); + memcpy(tmp, &tbuf[1], tbuf[0]); + ssid = (const char *)tmp; + free(tmp); Serial.write('A'); - break; } - - case 31: // reset + else { - handshakeSucceeded = false; - DisplayLogo(); - Serial.write('A'); - break; + Serial.write('E'); } + } - case 32: // get version + case 28: // set WiFi password + { + unsigned char tbuf[129]; + if (SerialReadBuffer(tbuf, 129)) { - Serial.write(ZEDMD_VERSION_MAJOR); - Serial.write(ZEDMD_VERSION_MINOR); - Serial.write(ZEDMD_VERSION_PATCH); - break; + // tbuf[0] now contains the length of the string + unsigned char *tmp = (unsigned char *)malloc(tbuf[0]); + memcpy(tmp, &tbuf[1], tbuf[0]); + pwd = (const char *)tmp; + free(tmp); + Serial.write('A'); } - - case 33: // get panel resolution + else { - Serial.write(TOTAL_WIDTH & 0xff); - Serial.write((TOTAL_WIDTH >> 8) & 0xff); - Serial.write(TOTAL_HEIGHT & 0xff); - Serial.write((TOTAL_HEIGHT >> 8) & 0xff); - break; + Serial.write('E'); } + break; + } - case 98: // disable debug mode + case 29: // set WiFi port + { + uint8_t byteArray[2]; + if (Serial.readBytes(byteArray, 2)) { - debugMode = false; + port = ((((unsigned int)byteArray[0]) << 8) + + ((unsigned int)byteArray[1])); Serial.write('A'); - break; } - - case 99: // enable debug mode + else { - debugMode = true; - Serial.write('A'); - break; + Serial.write('E'); } + break; + } +#endif + + case 30: // save settings + { + Serial.write('A'); + SaveLum(); + SaveOrdreRGB(); +#ifdef ZEDMD_WIFI + SaveWiFiConfig(); +#endif + break; + } - case 6: // reinit palette (deprecated) + case 31: // reset + { + Serial.write('A'); + handshakeSucceeded = false; + DisplayLogo(); + break; + } + + case 32: // get version + { + Serial.write(ZEDMD_VERSION_MAJOR); + Serial.write(ZEDMD_VERSION_MINOR); + Serial.write(ZEDMD_VERSION_PATCH); + break; + } + + case 33: // get panel resolution + { + Serial.write(TOTAL_WIDTH & 0xff); + Serial.write((TOTAL_WIDTH >> 8) & 0xff); + Serial.write(TOTAL_HEIGHT & 0xff); + Serial.write((TOTAL_HEIGHT >> 8) & 0xff); + break; + } + + case 98: // disable debug mode + { + debugMode = false; + Serial.write('A'); + break; + } + + case 99: // enable debug mode + { + debugMode = true; + Serial.write('A'); + break; + } + + case 6: // reinit palette (deprecated) + { + // Just backward compatibility. We don't need that command anymore. + Serial.write('A'); + break; + } + + case 10: // clear screen + { + Serial.write('A'); + ClearScreen(); + displayStatus = 3; + rotNextRotationTime[0] = millis(); + break; + } + +#ifndef ZEDMD_WIFI + case 3: // mode RGB24 + { + // We need to cover downscaling, too. + int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_BYTES : RomWidth * RomHeight * 3; + if (renderBufferInUse == 2) { - // Just backward compatibility. We don't need that command anymore. - Serial.write('A'); - break; + renderBufferInUse = 1; + free(renderBuffer); } + renderBuffer = (unsigned char *)malloc(renderBufferSize); + memset(renderBuffer, 0, renderBufferSize); - case 10: // clear screen + if (SerialReadBuffer(renderBuffer, RomHeight * RomWidth * 3)) { - ClearScreen(); - displayStatus = 3; - rotNextRotationTime[0] = millis(); - Serial.write('A'); - break; + mode64 = false; + ScaleImage(3); + fillPanelRaw(); } - case 3: // mode RGB24 + free(renderBuffer); + renderBufferInUse = 0; + break; + } + + case 8: // mode 4 couleurs avec 1 palette 4 couleurs (4*3 bytes) suivis de 4 pixels par byte + { + int bufferSize = 12 + 2 * RomWidthPlane * RomHeight; + unsigned char *buffer = (unsigned char *)malloc(bufferSize); + + if (SerialReadBuffer(buffer, bufferSize)) { // We need to cover downscaling, too. - int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_BYTES : RomWidth * RomHeight * 3; - if (renderBufferInUse == 2) { + int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; + if (renderBufferInUse == 2) + { renderBufferInUse = 1; free(renderBuffer); } renderBuffer = (unsigned char *)malloc(renderBufferSize); memset(renderBuffer, 0, renderBufferSize); + palette = (unsigned char *)malloc(12); + memcpy(palette, buffer, 12); - if (SerialReadBuffer(renderBuffer, RomHeight * RomWidth * 3)) + unsigned char *frame = &buffer[12]; + for (int tj = 0; tj < RomHeight; tj++) { - mode64 = false; - ScaleImage(3); - fillPanelRaw(); - } - - free(renderBuffer); - renderBufferInUse = 0; - break; - } - - case 8: // mode 4 couleurs avec 1 palette 4 couleurs (4*3 bytes) suivis de 4 pixels par byte - { - int bufferSize = 12 + 2 * RomWidthPlane * RomHeight; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); - - if (SerialReadBuffer(buffer, bufferSize)) - { - // We need to cover downscaling, too. - int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); - memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(12); - memcpy(palette, buffer, 12); - - unsigned char *frame = &buffer[12]; - for (int tj = 0; tj < RomHeight; tj++) + for (int ti = 0; ti < RomWidthPlane; ti++) { - for (int ti = 0; ti < RomWidthPlane; ti++) + unsigned char mask = 1; + unsigned char planes[2]; + planes[0] = frame[ti + tj * RomWidthPlane]; + planes[1] = frame[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + for (int tk = 0; tk < 8; tk++) { - unsigned char mask = 1; - unsigned char planes[2]; - planes[0] = frame[ti + tj * RomWidthPlane]; - planes[1] = frame[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - for (int tk = 0; tk < 8; tk++) - { - unsigned char idx = 0; - if ((planes[0] & mask) > 0) - idx |= 1; - if ((planes[1] & mask) > 0) - idx |= 2; - renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; - mask <<= 1; - } + unsigned char idx = 0; + if ((planes[0] & mask) > 0) + idx |= 1; + if ((planes[1] & mask) > 0) + idx |= 2; + renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; + mask <<= 1; } } - free(buffer); + } + free(buffer); - mode64 = false; + mode64 = false; - ScaleImage(1); - fillPanelUsingPalette(); + ScaleImage(1); + fillPanelUsingPalette(); - free(renderBuffer); - renderBufferInUse = 0; - free(palette); - } - else - { - free(buffer); - } - break; + free(renderBuffer); + renderBufferInUse = 0; + free(palette); } - - case 7: // mode 16 couleurs avec 1 palette 4 couleurs (4*3 bytes) suivis de 2 pixels par byte + else { - int bufferSize = 12 + 4 * RomWidthPlane * RomHeight; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + free(buffer); + } + break; + } - if (SerialReadBuffer(buffer, bufferSize)) + case 7: // mode 16 couleurs avec 1 palette 4 couleurs (4*3 bytes) suivis de 2 pixels par byte + { + int bufferSize = 12 + 4 * RomWidthPlane * RomHeight; + unsigned char *buffer = (unsigned char *)malloc(bufferSize); + + if (SerialReadBuffer(buffer, bufferSize)) + { + // We need to cover downscaling, too. + int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; + if (renderBufferInUse == 2) { - // We need to cover downscaling, too. - int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); - memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(48); - memcpy(palette, buffer, 48); - - palette[0] = palette[1] = palette[2] = 0; - palette[3] = palette[3 * 3] / 3; - palette[4] = palette[3 * 3 + 1] / 3; - palette[5] = palette[3 * 3 + 2] / 3; - palette[6] = 2 * (palette[3 * 3] / 3); - palette[7] = 2 * (palette[3 * 3 + 1] / 3); - palette[8] = 2 * (palette[3 * 3 + 2] / 3); - - palette[12] = palette[3 * 3] + (palette[7 * 3] - palette[3 * 3]) / 4; - palette[13] = palette[3 * 3 + 1] + (palette[7 * 3 + 1] - palette[3 * 3 + 1]) / 4; - palette[14] = palette[3 * 3 + 2] + (palette[7 * 3 + 2] - palette[3 * 3 + 2]) / 4; - palette[15] = palette[3 * 3] + 2 * ((palette[7 * 3] - palette[3 * 3]) / 4); - palette[16] = palette[3 * 3 + 1] + 2 * ((palette[7 * 3 + 1] - palette[3 * 3 + 1]) / 4); - palette[17] = palette[3 * 3 + 2] + 2 * ((palette[7 * 3 + 2] - palette[3 * 3 + 2]) / 4); - palette[18] = palette[3 * 3] + 3 * ((palette[7 * 3] - palette[3 * 3]) / 4); - palette[19] = palette[3 * 3 + 1] + 3 * ((palette[7 * 3 + 1] - palette[3 * 3 + 1]) / 4); - palette[20] = palette[3 * 3 + 2] + 3 * ((palette[7 * 3 + 2] - palette[3 * 3 + 2]) / 4); - - palette[24] = palette[7 * 3] + (palette[11 * 3] - palette[7 * 3]) / 4; - palette[25] = palette[7 * 3 + 1] + (palette[11 * 3 + 1] - palette[7 * 3 + 1]) / 4; - palette[26] = palette[7 * 3 + 2] + (palette[11 * 3 + 2] - palette[7 * 3 + 2]) / 4; - palette[27] = palette[7 * 3] + 2 * ((palette[11 * 3] - palette[7 * 3]) / 4); - palette[28] = palette[7 * 3 + 1] + 2 * ((palette[11 * 3 + 1] - palette[7 * 3 + 1]) / 4); - palette[29] = palette[7 * 3 + 2] + 2 * ((palette[11 * 3 + 2] - palette[7 * 3 + 2]) / 4); - palette[30] = palette[7 * 3] + 3 * ((palette[11 * 3] - palette[7 * 3]) / 4); - palette[31] = palette[7 * 3 + 1] + 3 * ((palette[11 * 3 + 1] - palette[7 * 3 + 1]) / 4); - palette[32] = palette[7 * 3 + 2] + 3 * ((palette[11 * 3 + 2] - palette[7 * 3 + 2]) / 4); - - palette[36] = palette[11 * 3] + (palette[15 * 3] - palette[11 * 3]) / 4; - palette[37] = palette[11 * 3 + 1] + (palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4; - palette[38] = palette[11 * 3 + 2] + (palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4; - palette[39] = palette[11 * 3] + 2 * ((palette[15 * 3] - palette[11 * 3]) / 4); - palette[40] = palette[11 * 3 + 1] + 2 * ((palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4); - palette[41] = palette[11 * 3 + 2] + 2 * ((palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4); - palette[42] = palette[11 * 3] + 3 * ((palette[15 * 3] - palette[11 * 3]) / 4); - palette[43] = palette[11 * 3 + 1] + 3 * ((palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4); - palette[44] = palette[11 * 3 + 2] + 3 * ((palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4); - - unsigned char *pBuffer = &buffer[12]; - for (int tj = 0; tj < RomHeight; tj++) + renderBufferInUse = 1; + free(renderBuffer); + } + renderBuffer = (unsigned char *)malloc(renderBufferSize); + memset(renderBuffer, 0, renderBufferSize); + palette = (unsigned char *)malloc(48); + memcpy(palette, buffer, 48); + + palette[0] = palette[1] = palette[2] = 0; + palette[3] = palette[3 * 3] / 3; + palette[4] = palette[3 * 3 + 1] / 3; + palette[5] = palette[3 * 3 + 2] / 3; + palette[6] = 2 * (palette[3 * 3] / 3); + palette[7] = 2 * (palette[3 * 3 + 1] / 3); + palette[8] = 2 * (palette[3 * 3 + 2] / 3); + + palette[12] = palette[3 * 3] + (palette[7 * 3] - palette[3 * 3]) / 4; + palette[13] = palette[3 * 3 + 1] + (palette[7 * 3 + 1] - palette[3 * 3 + 1]) / 4; + palette[14] = palette[3 * 3 + 2] + (palette[7 * 3 + 2] - palette[3 * 3 + 2]) / 4; + palette[15] = palette[3 * 3] + 2 * ((palette[7 * 3] - palette[3 * 3]) / 4); + palette[16] = palette[3 * 3 + 1] + 2 * ((palette[7 * 3 + 1] - palette[3 * 3 + 1]) / 4); + palette[17] = palette[3 * 3 + 2] + 2 * ((palette[7 * 3 + 2] - palette[3 * 3 + 2]) / 4); + palette[18] = palette[3 * 3] + 3 * ((palette[7 * 3] - palette[3 * 3]) / 4); + palette[19] = palette[3 * 3 + 1] + 3 * ((palette[7 * 3 + 1] - palette[3 * 3 + 1]) / 4); + palette[20] = palette[3 * 3 + 2] + 3 * ((palette[7 * 3 + 2] - palette[3 * 3 + 2]) / 4); + + palette[24] = palette[7 * 3] + (palette[11 * 3] - palette[7 * 3]) / 4; + palette[25] = palette[7 * 3 + 1] + (palette[11 * 3 + 1] - palette[7 * 3 + 1]) / 4; + palette[26] = palette[7 * 3 + 2] + (palette[11 * 3 + 2] - palette[7 * 3 + 2]) / 4; + palette[27] = palette[7 * 3] + 2 * ((palette[11 * 3] - palette[7 * 3]) / 4); + palette[28] = palette[7 * 3 + 1] + 2 * ((palette[11 * 3 + 1] - palette[7 * 3 + 1]) / 4); + palette[29] = palette[7 * 3 + 2] + 2 * ((palette[11 * 3 + 2] - palette[7 * 3 + 2]) / 4); + palette[30] = palette[7 * 3] + 3 * ((palette[11 * 3] - palette[7 * 3]) / 4); + palette[31] = palette[7 * 3 + 1] + 3 * ((palette[11 * 3 + 1] - palette[7 * 3 + 1]) / 4); + palette[32] = palette[7 * 3 + 2] + 3 * ((palette[11 * 3 + 2] - palette[7 * 3 + 2]) / 4); + + palette[36] = palette[11 * 3] + (palette[15 * 3] - palette[11 * 3]) / 4; + palette[37] = palette[11 * 3 + 1] + (palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4; + palette[38] = palette[11 * 3 + 2] + (palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4; + palette[39] = palette[11 * 3] + 2 * ((palette[15 * 3] - palette[11 * 3]) / 4); + palette[40] = palette[11 * 3 + 1] + 2 * ((palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4); + palette[41] = palette[11 * 3 + 2] + 2 * ((palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4); + palette[42] = palette[11 * 3] + 3 * ((palette[15 * 3] - palette[11 * 3]) / 4); + palette[43] = palette[11 * 3 + 1] + 3 * ((palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4); + palette[44] = palette[11 * 3 + 2] + 3 * ((palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4); + + unsigned char *pBuffer = &buffer[12]; + for (int tj = 0; tj < RomHeight; tj++) + { + for (int ti = 0; ti < RomWidthPlane; ti++) { - for (int ti = 0; ti < RomWidthPlane; ti++) + unsigned char mask = 1; + unsigned char planes[4]; + planes[0] = pBuffer[ti + tj * RomWidthPlane]; + planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + for (int tk = 0; tk < 8; tk++) { - unsigned char mask = 1; - unsigned char planes[4]; - planes[0] = pBuffer[ti + tj * RomWidthPlane]; - planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - for (int tk = 0; tk < 8; tk++) - { - unsigned char idx = 0; - if ((planes[0] & mask) > 0) - idx |= 1; - if ((planes[1] & mask) > 0) - idx |= 2; - if ((planes[2] & mask) > 0) - idx |= 4; - if ((planes[3] & mask) > 0) - idx |= 8; - renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; - mask <<= 1; - } + unsigned char idx = 0; + if ((planes[0] & mask) > 0) + idx |= 1; + if ((planes[1] & mask) > 0) + idx |= 2; + if ((planes[2] & mask) > 0) + idx |= 4; + if ((planes[3] & mask) > 0) + idx |= 8; + renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; + mask <<= 1; } } - free(buffer); + } + free(buffer); - mode64 = false; + mode64 = false; - ScaleImage(1); - fillPanelUsingPalette(); + ScaleImage(1); + fillPanelUsingPalette(); - free(renderBuffer); - renderBufferInUse = 0; - free(palette); - } - else - { - free(buffer); - } - break; + free(renderBuffer); + renderBufferInUse = 0; + free(palette); } - - case 9: // mode 16 couleurs avec 1 palette 16 couleurs (16*3 bytes) suivis de 4 bytes par groupe de 8 points (séparés en plans de bits 4*512 bytes) + else { - int bufferSize = 48 + 4 * RomWidthPlane * RomHeight; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + free(buffer); + } + break; + } - if (SerialReadBuffer(buffer, bufferSize)) + case 9: // mode 16 couleurs avec 1 palette 16 couleurs (16*3 bytes) suivis de 4 bytes par groupe de 8 points (séparés en plans de bits 4*512 bytes) + { + int bufferSize = 48 + 4 * RomWidthPlane * RomHeight; + unsigned char *buffer = (unsigned char *)malloc(bufferSize); + + if (SerialReadBuffer(buffer, bufferSize)) + { + // We need to cover downscaling, too. + int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; + if (renderBufferInUse == 2) { - // We need to cover downscaling, too. - int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); - memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(48); - memcpy(palette, buffer, 48); + renderBufferInUse = 1; + free(renderBuffer); + } + renderBuffer = (unsigned char *)malloc(renderBufferSize); + memset(renderBuffer, 0, renderBufferSize); + palette = (unsigned char *)malloc(48); + memcpy(palette, buffer, 48); - unsigned char *pBuffer = &buffer[48]; - for (int tj = 0; tj < RomHeight; tj++) + unsigned char *pBuffer = &buffer[48]; + for (int tj = 0; tj < RomHeight; tj++) + { + for (int ti = 0; ti < RomWidthPlane; ti++) { - for (int ti = 0; ti < RomWidthPlane; ti++) + // on reconstitue un indice à partir des plans puis une couleur à partir de la palette + unsigned char mask = 1; + unsigned char planes[4]; + planes[0] = pBuffer[ti + tj * RomWidthPlane]; + planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + for (int tk = 0; tk < 8; tk++) { - // on reconstitue un indice à partir des plans puis une couleur à partir de la palette - unsigned char mask = 1; - unsigned char planes[4]; - planes[0] = pBuffer[ti + tj * RomWidthPlane]; - planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - for (int tk = 0; tk < 8; tk++) - { - unsigned char idx = 0; - if ((planes[0] & mask) > 0) - idx |= 1; - if ((planes[1] & mask) > 0) - idx |= 2; - if ((planes[2] & mask) > 0) - idx |= 4; - if ((planes[3] & mask) > 0) - idx |= 8; - renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; - mask <<= 1; - } + unsigned char idx = 0; + if ((planes[0] & mask) > 0) + idx |= 1; + if ((planes[1] & mask) > 0) + idx |= 2; + if ((planes[2] & mask) > 0) + idx |= 4; + if ((planes[3] & mask) > 0) + idx |= 8; + renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; + mask <<= 1; } } - free(buffer); + } + free(buffer); - mode64 = false; + mode64 = false; - ScaleImage(1); - fillPanelUsingPalette(); + ScaleImage(1); + fillPanelUsingPalette(); - free(renderBuffer); - renderBufferInUse = 0; - free(palette); - } - else - { - free(buffer); - } - break; + free(renderBuffer); + renderBufferInUse = 0; + free(palette); } - - case 11: // mode 64 couleurs avec 1 palette 64 couleurs (64*3 bytes) suivis de 6 bytes par groupe de 8 points (séparés en plans de bits 6*512 bytes) suivis de 3*8 bytes de rotations de couleurs + else { - int bufferSize = 192 + 6 * RomWidthPlane * RomHeight + 3 * MAX_COLOR_ROTATIONS; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + free(buffer); + } + break; + } + + case 11: // mode 64 couleurs avec 1 palette 64 couleurs (64*3 bytes) suivis de 6 bytes par groupe de 8 points (séparés en plans de bits 6*512 bytes) suivis de 3*8 bytes de rotations de couleurs + { + int bufferSize = 192 + 6 * RomWidthPlane * RomHeight + 3 * MAX_COLOR_ROTATIONS; + unsigned char *buffer = (unsigned char *)malloc(bufferSize); - if (SerialReadBuffer(buffer, bufferSize)) + if (SerialReadBuffer(buffer, bufferSize)) + { + // We need to cover downscaling, too. + int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; + if (renderBufferInUse == 2) { - // We need to cover downscaling, too. - int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); - memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(192); - memcpy(palette, buffer, 192); + renderBufferInUse = 1; + free(renderBuffer); + } + renderBuffer = (unsigned char *)malloc(renderBufferSize); + memset(renderBuffer, 0, renderBufferSize); + palette = (unsigned char *)malloc(192); + memcpy(palette, buffer, 192); - unsigned char *pBuffer = &buffer[192]; - for (int tj = 0; tj < RomHeight; tj++) + unsigned char *pBuffer = &buffer[192]; + for (int tj = 0; tj < RomHeight; tj++) + { + for (int ti = 0; ti < RomWidthPlane; ti++) { - for (int ti = 0; ti < RomWidthPlane; ti++) + // on reconstitue un indice à partir des plans puis une couleur à partir de la palette + unsigned char mask = 1; + unsigned char planes[6]; + planes[0] = pBuffer[ti + tj * RomWidthPlane]; + planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[4] = pBuffer[4 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + planes[5] = pBuffer[5 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; + for (int tk = 0; tk < 8; tk++) { - // on reconstitue un indice à partir des plans puis une couleur à partir de la palette - unsigned char mask = 1; - unsigned char planes[6]; - planes[0] = pBuffer[ti + tj * RomWidthPlane]; - planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[4] = pBuffer[4 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - planes[5] = pBuffer[5 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; - for (int tk = 0; tk < 8; tk++) - { - unsigned char idx = 0; - if ((planes[0] & mask) > 0) - idx |= 1; - if ((planes[1] & mask) > 0) - idx |= 2; - if ((planes[2] & mask) > 0) - idx |= 4; - if ((planes[3] & mask) > 0) - idx |= 8; - if ((planes[4] & mask) > 0) - idx |= 0x10; - if ((planes[5] & mask) > 0) - idx |= 0x20; - renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; - mask <<= 1; - } + unsigned char idx = 0; + if ((planes[0] & mask) > 0) + idx |= 1; + if ((planes[1] & mask) > 0) + idx |= 2; + if ((planes[2] & mask) > 0) + idx |= 4; + if ((planes[3] & mask) > 0) + idx |= 8; + if ((planes[4] & mask) > 0) + idx |= 0x10; + if ((planes[5] & mask) > 0) + idx |= 0x20; + renderBuffer[(ti * 8 + tk) + tj * RomWidth] = idx; + mask <<= 1; } } + } - // Handle up to 8 different rotations for each frame. - // first byte: first color in the rotation - // second byte: number of contiguous colors in the rotation - // third byte: delay between 2 rotations (5 -> 50ms, 12 -> 120ms) - pBuffer = &buffer[192 + 6 * RomWidthPlane * RomHeight]; - unsigned long actime = millis(); + // Handle up to 8 different rotations for each frame. + // first byte: first color in the rotation + // second byte: number of contiguous colors in the rotation + // third byte: delay between 2 rotations (5 -> 50ms, 12 -> 120ms) + pBuffer = &buffer[192 + 6 * RomWidthPlane * RomHeight]; + unsigned long actime = millis(); - for (int ti = 0; ti < MAX_COLOR_ROTATIONS; ti++) - { - rotFirstColor[ti] = pBuffer[ti * 3]; - rotAmountColors[ti] = pBuffer[ti * 3 + 1]; - rotStepDurationTime[ti] = 10 * pBuffer[ti * 3 + 2]; - rotNextRotationTime[ti] = actime + rotStepDurationTime[ti]; - } + for (int ti = 0; ti < MAX_COLOR_ROTATIONS; ti++) + { + rotFirstColor[ti] = pBuffer[ti * 3]; + rotAmountColors[ti] = pBuffer[ti * 3 + 1]; + rotStepDurationTime[ti] = 10 * pBuffer[ti * 3 + 2]; + rotNextRotationTime[ti] = actime + rotStepDurationTime[ti]; + } - free(buffer); + free(buffer); - mode64 = true; + mode64 = true; - ScaleImage(1); - fillPanelUsingPalette(); + ScaleImage(1); + fillPanelUsingPalette(); - free(renderBuffer); - renderBufferInUse = 0; - free(palette); - } - else - { - free(buffer); - } - break; + free(renderBuffer); + renderBufferInUse = 0; + free(palette); } - - default: + else { - Serial.write('E'); + free(buffer); } + break; + } +#endif + default: + { + Serial.write('E'); + } } if (debugMode) From 454dafa551308612cc734412d886fcbc9035e45c Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Wed, 13 Dec 2023 17:55:07 +0100 Subject: [PATCH 2/7] use RGB24 streaming for ZeDMD HD --- platformio.ini | 29 +++--------------- src/main.cpp | 79 +++++++++++++++++++++++++++----------------------- 2 files changed, 46 insertions(+), 62 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6c965c7..46be150 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ default_envs = 128x32 [env:128x32] framework = arduino -platform = espressif32 +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.06.01/platform-espressif32.zip board = esp32dev board_build.partitions = partitions.csv board_build.filesystem = littlefs @@ -33,28 +33,7 @@ build_flags = [env:256x64] framework = arduino -platform = espressif32 -board = esp32dev -board_build.partitions = partitions.csv -board_build.filesystem = littlefs -board_build.flash_mode = qio -lib_deps = - https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA#3.0.9 - thomasfredericks/Bounce2 -build_flags = - -DNO_GFX=1 - -DZEDMD_128_64_2=1 - -DPIXEL_COLOR_DEPTH_BITS=5 - -DMINIZ_NO_STDIO=1 - -DMINIZ_NO_TIME=1 - -DMINIZ_NO_DEFLATE_APIS=1 - -DMINIZ_NO_ARCHIVE_APIS=1 - -DMINIZ_NO_ARCHIVE_WRITING_APIS=1 - -DMINIZ_NO_ZLIB_COMPATIBLE_NAMES=1 - -[env:256x64_7bit] -framework = arduino -platform = espressif32 +platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.06.01/platform-espressif32.zip board = esp32dev board_build.partitions = partitions.csv board_build.filesystem = littlefs @@ -64,7 +43,7 @@ lib_deps = thomasfredericks/Bounce2 build_flags = -DNO_GFX=1 - -DZEDMD_128_64_2=1 + -DZEDMD_HD=1 -DPIXEL_COLOR_DEPTH_BITS=7 -DMINIZ_NO_STDIO=1 -DMINIZ_NO_TIME=1 @@ -106,7 +85,7 @@ lib_deps = thomasfredericks/Bounce2 build_flags = -DNO_GFX=1 - -DZEDMD_128_64_2=1 + -DZEDMD_HD=1 -DZEDMD_WIFI=1 -DPIXEL_COLOR_DEPTH_BITS=7 -DMINIZ_NO_STDIO=1 diff --git a/src/main.cpp b/src/main.cpp index e072c7b..ab9e4fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,8 @@ #define ZEDMD_VERSION_MAJOR 3 // X Digits -#define ZEDMD_VERSION_MINOR 3 // Max 2 Digits -#define ZEDMD_VERSION_PATCH 2 // Max 2 Digits +#define ZEDMD_VERSION_MINOR 4 // Max 2 Digits +#define ZEDMD_VERSION_PATCH 0 // Max 2 Digits -#ifdef ZEDMD_128_64_2 +#ifdef ZEDMD_HD #define PANEL_WIDTH 128 // Width: number of LEDs for 1 panel. #define PANEL_HEIGHT 64 // Height: number of LEDs. #define PANELS_NUMBER 2 // Number of horizontally chained panels. @@ -92,12 +92,10 @@ IPAddress ip; unsigned long rotNextRotationTime[1]; #else -#ifdef ZEDMD_128_64_2 -uint8_t doubleBuffer[TOTAL_HEIGHT][TOTAL_WIDTH] = {0}; -uint8_t existsBuffer[TOTAL_HEIGHT][TOTAL_WIDTH / 2] = {0}; +#ifdef ZEDMD_HD +unsigned long rotNextRotationTime[1]; #else uint8_t doubleBuffer[TOTAL_BYTES] = {0}; -#endif // color rotation unsigned char rotFirstColor[MAX_COLOR_ROTATIONS]; @@ -108,6 +106,7 @@ unsigned char tmpColor[3] = {0}; bool upscaling = true; #endif +#endif // Pinout derived from ESP32-HUB75-MatrixPanel-I2S-DMA.h #define R1_PIN 25 @@ -299,17 +298,12 @@ void ClearScreen() { dma_display->clearScreen(); dma_display->setBrightness8(lumval[lumstep]); -#ifndef ZEDMD_WIFI -#ifdef ZEDMD_128_64_2 - memset(doubleBuffer, 0, TOTAL_HEIGHT * TOTAL_WIDTH); - memset(existsBuffer, 0, TOTAL_HEIGHT * TOTAL_WIDTH / 2); -#else +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) memset(doubleBuffer, 0, TOTAL_BYTES); #endif -#endif } -#ifndef ZEDMD_WIFI +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) bool CmpColor(uint8_t *px1, uint8_t *px2, uint8_t colors) { if (colors == 3) @@ -618,17 +612,7 @@ void ScaleImage(uint8_t colors) void DrawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) { -#ifndef ZEDMD_WIFI -#ifdef ZEDMD_128_64_2 - uint8_t colors = ((r >> 5) << 5) + ((g >> 5) << 2) + (b >> 6); - uint8_t colorsExist = (r ? 8 : 0) + (g ? 4 : 0) + (b ? 2 : 0) + ((r || g || b) ? 1 : 0); - uint8_t buf = (x % 2) ? (existsBuffer[y][x / 2] >> 4) : ((existsBuffer[y][x / 2] << 4) >> 4); - - if (colors != doubleBuffer[y][x] || colorsExist != buf) - { - doubleBuffer[y][x] = colors; - existsBuffer[y][x / 2] = (x % 2) ? (((existsBuffer[y][x / 2] << 4) >> 4) + (colorsExist << 4)) : (((existsBuffer[y][x / 2] >> 4) << 4) + colorsExist); -#else +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) int pos = (y * TOTAL_WIDTH + x) * 3; if (r != doubleBuffer[pos] || g != doubleBuffer[pos + 1] || b != doubleBuffer[pos + 2]) @@ -636,15 +620,14 @@ void DrawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) doubleBuffer[pos] = r; doubleBuffer[pos + 1] = g; doubleBuffer[pos + 2] = b; -#endif #endif dma_display->drawPixelRGB888(x, y, r, g, b); -#ifndef ZEDMD_WIFI +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) } #endif } -void fillZoneRaw(uint8_t idx) +void fillZoneRaw(uint8_t idx, uint8_t *pBuffer) { uint8_t yOffset = idx / (TOTAL_WIDTH / 16) * 8; uint8_t xOffset = (idx % (TOTAL_WIDTH / 16)) * 16; @@ -658,9 +641,9 @@ void fillZoneRaw(uint8_t idx) DrawPixel( x + xOffset, y + yOffset, - renderBuffer[pos + ordreRGB[acordreRGB * 3]], - renderBuffer[pos + ordreRGB[acordreRGB * 3 + 1]], - renderBuffer[pos + ordreRGB[acordreRGB * 3 + 2]]); + pBuffer[pos + ordreRGB[acordreRGB * 3]], + pBuffer[pos + ordreRGB[acordreRGB * 3 + 1]], + pBuffer[pos + ordreRGB[acordreRGB * 3 + 2]]); } } } @@ -705,7 +688,7 @@ void fillPanelUsingPalette() } } -#ifndef ZEDMD_WIFI +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) void fillPanelUsingChangedPalette(bool *paletteAffected) { int pos; @@ -1027,7 +1010,7 @@ void setup() memcpy(renderBuffer, &pPacket[4], size); } - fillZoneRaw(idx); + fillZoneRaw(idx, renderBuffer); free(renderBuffer); break; } @@ -1083,7 +1066,7 @@ bool SerialReadBuffer(unsigned char *pBuffer, unsigned int BufferSize) if (debugMode) { debugLines[4] = ++errorCount; -#ifdef ZEDMD_128_64_2 +#ifdef ZEDMD_HD Say(9, remainingBytes); Say(10, chunkSize); Say(11, receivedBytes); @@ -1161,7 +1144,7 @@ bool SerialReadBuffer(unsigned char *pBuffer, unsigned int BufferSize) void updateColorRotations(void) { -#ifndef ZEDMD_WIFI +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) bool rotPaletteAffected[64] = {0}; unsigned long actime = millis(); bool rotfound = false; @@ -1403,7 +1386,7 @@ void loop() break; } -#ifndef ZEDMD_WIFI +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) case 20: // turn off upscaling { upscaling = false; @@ -1596,7 +1579,29 @@ void loop() break; } -#ifndef ZEDMD_WIFI +#ifdef ZEDMD_HD + case 3: // mode RGB24 + { + if (renderBufferInUse == 2) + { + renderBufferInUse = 1; + free(renderBuffer); + } + + renderBuffer = (uint8_t *)malloc(16 * 8 * 3 + 1); + + if (SerialReadBuffer(renderBuffer, 16 * 8 * 3)) + { + fillZoneRaw(renderBuffer[0], &renderBuffer[1]); + free(renderBuffer); + } + + renderBufferInUse = 0; + break; + } +#endif + +#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) case 3: // mode RGB24 { // We need to cover downscaling, too. From 8c2e364d15caee69fb0afa572a710a2644c15a4d Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Wed, 13 Dec 2023 22:38:37 +0100 Subject: [PATCH 3/7] disabled parallel use od usb and wifi rendering --- src/main.cpp | 187 +++++++++++++++++++-------------------------------- 1 file changed, 70 insertions(+), 117 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index ab9e4fa..38e9882 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -98,11 +98,11 @@ unsigned long rotNextRotationTime[1]; uint8_t doubleBuffer[TOTAL_BYTES] = {0}; // color rotation -unsigned char rotFirstColor[MAX_COLOR_ROTATIONS]; -unsigned char rotAmountColors[MAX_COLOR_ROTATIONS]; +uint8_t rotFirstColor[MAX_COLOR_ROTATIONS]; +uint8_t rotAmountColors[MAX_COLOR_ROTATIONS]; unsigned int rotStepDurationTime[MAX_COLOR_ROTATIONS]; unsigned long rotNextRotationTime[MAX_COLOR_ROTATIONS]; -unsigned char tmpColor[3] = {0}; +uint8_t tmpColor[3] = {0}; bool upscaling = true; #endif @@ -137,7 +137,7 @@ bool debugMode = false; unsigned int debugLines[6] = {0}; // !!!!! NE METTRE AUCUNE VALEURE IDENTIQUE !!!!! -unsigned char CtrlCharacters[6] = {0x5a, 0x65, 0x64, 0x72, 0x75, 0x6d}; +uint8_t CtrlCharacters[6] = {0x5a, 0x65, 0x64, 0x72, 0x75, 0x6d}; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! bool lumtxt[16 * 5] = {0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, @@ -146,7 +146,7 @@ bool lumtxt[16 * 5] = {0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0}; -unsigned char lumval[16] = {0, 2, 4, 7, 11, 18, 30, 40, 50, 65, 80, 100, 125, 160, 200, 255}; // Non-linear brightness progression +uint8_t lumval[16] = {0, 2, 4, 7, 11, 18, 30, 40, 50, 65, 80, 100, 125, 160, 200, 255}; // Non-linear brightness progression HUB75_I2S_CFG::i2s_pins _pins = {R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN}; HUB75_I2S_CFG mxconfig( @@ -163,16 +163,15 @@ int ordreRGB[3 * 6] = {0, 1, 2, 2, 0, 1, 1, 2, 0, 0, 2, 1, 1, 0, 2, 2, 1, 0}; int acordreRGB = 0; -unsigned char *palette; -unsigned char *renderBuffer; -uint8_t renderBufferInUse = 0; // 0: not used; 1: USB; 2: WiFi +uint8_t *palette; +uint8_t *renderBuffer; bool mode64 = false; int RomWidth = 128, RomHeight = 32; int RomWidthPlane = 128 >> 3; -unsigned char lumstep = 1; +uint8_t lumstep = 1; bool MireActive = false; // 0: screen saver @@ -186,7 +185,7 @@ bool compression = false; int serialTransferChunkSize = 256; unsigned int frameCount = 0; unsigned int errorCount = 0; -unsigned char flowControlCounter = 0; +uint8_t flowControlCounter = 0; void DisplayChiffre(unsigned int chf, int x, int y, int R, int G, int B) { @@ -223,7 +222,7 @@ void DisplayChiffre(unsigned int chf, int x, int y, int R, int G, int B) } } -void DisplayNombre(unsigned int chf, unsigned char nc, int x, int y, int R, int G, int B) +void DisplayNombre(unsigned int chf, uint8_t nc, int x, int y, int R, int G, int B) { // affiche un nombre verticalement unsigned int acc = chf, acd = 1; @@ -287,7 +286,7 @@ void DisplayText(bool *text, int width, int x, int y, int R, int G, int B) } } -void Say(unsigned char where, unsigned int what) +void Say(uint8_t where, unsigned int what) { DisplayNombre(where, 3, 0, where * 5, 255, 255, 255); if (what != (unsigned int)-1) @@ -316,7 +315,7 @@ bool CmpColor(uint8_t *px1, uint8_t *px2, uint8_t colors) return px1[0] == px2[0]; } -void SetColor(unsigned char *px1, unsigned char *px2, uint8_t colors) +void SetColor(uint8_t *px1, uint8_t *px2, uint8_t colors) { px1[0] = px2[0]; @@ -383,7 +382,7 @@ void ScaleImage(uint8_t colors) return; } - unsigned char *panel = (unsigned char *)malloc(RomWidth * RomHeight * colors); + uint8_t *panel = (uint8_t *)malloc(RomWidth * RomHeight * colors); memcpy(panel, renderBuffer, RomWidth * RomHeight * colors); memset(renderBuffer, 0, TOTAL_WIDTH * TOTAL_HEIGHT); @@ -632,9 +631,9 @@ void fillZoneRaw(uint8_t idx, uint8_t *pBuffer) uint8_t yOffset = idx / (TOTAL_WIDTH / 16) * 8; uint8_t xOffset = (idx % (TOTAL_WIDTH / 16)) * 16; - for (int y = 0; y < 8; y++) + for (uint8_t y = 0; y < 8; y++) { - for (int x = 0; x < 16; x++) + for (uint8_t x = 0; x < 16; x++) { uint16_t pos = (y * 16 + x) * 3; @@ -817,7 +816,7 @@ void DisplayLogo(void) return; } - renderBuffer = (unsigned char *)malloc(TOTAL_BYTES); + renderBuffer = (uint8_t *)malloc(TOTAL_BYTES); for (unsigned int tj = 0; tj < TOTAL_BYTES; tj++) { renderBuffer[tj] = flogo.read(); @@ -867,7 +866,7 @@ void DisplayUpdate(void) return; } - renderBuffer = (unsigned char *)malloc(TOTAL_BYTES); + renderBuffer = (uint8_t *)malloc(TOTAL_BYTES); for (unsigned int tj = 0; tj < TOTAL_BYTES; tj++) { renderBuffer[tj] = flogo.read(); @@ -960,26 +959,16 @@ void setup() if (udp.listen(port)) { udp.onPacket([](AsyncUDPPacket packet) - { - if (packet.length() >= 2) { - if (MireActive) { - ClearScreen(); - MireActive = false; - } - - if (renderBufferInUse == 0) { - renderBufferInUse = 2; - } - else if (renderBufferInUse == 1) { - // Blocked by rendering over USB. - return; - } - + { + if (packet.length() >= 1) { uint8_t *pPacket = packet.data(); switch (pPacket[0]) { case 10: // clear screen { + if (MireActive) { + MireActive = false; + } ClearScreen(); break; } @@ -1015,18 +1004,19 @@ void setup() break; } } - } }); + } + }); } } #endif } -bool SerialReadBuffer(unsigned char *pBuffer, unsigned int BufferSize) +bool SerialReadBuffer(uint8_t *pBuffer, unsigned int BufferSize) { memset(pBuffer, 0, BufferSize); unsigned int transferBufferSize = BufferSize; - unsigned char *transferBuffer; + uint8_t *transferBuffer; if (compression) { @@ -1035,7 +1025,7 @@ bool SerialReadBuffer(unsigned char *pBuffer, unsigned int BufferSize) transferBufferSize = ((((unsigned int)byteArray[0]) << 8) + ((unsigned int)byteArray[1])); - transferBuffer = (unsigned char *)malloc(transferBufferSize); + transferBuffer = (uint8_t *)malloc(transferBufferSize); } else { @@ -1176,7 +1166,7 @@ void updateColorRotations(void) bool wait_for_ctrl_chars(void) { unsigned long ms = millis(); - unsigned char nCtrlCharFound = 0; + uint8_t nCtrlCharFound = 0; while (nCtrlCharFound < N_CTRL_CHARS) { @@ -1297,7 +1287,7 @@ void loop() // Updates to mode64 color rotations have been handled within wait_for_ctrl_chars(), now reset it to false. mode64 = false; - unsigned char c4; + uint8_t c4; while (Serial.available() == 0) ; c4 = Serial.read(); @@ -1332,7 +1322,7 @@ void loop() case 2: // set rom frame size { - unsigned char tbuf[4]; + uint8_t tbuf[4]; if (SerialReadBuffer(tbuf, 4)) { RomWidth = (int)(tbuf[0]) + (int)(tbuf[1] << 8); @@ -1402,7 +1392,7 @@ void loop() case 22: // set brightness { - unsigned char tbuf[1]; + uint8_t tbuf[1]; if (SerialReadBuffer(tbuf, 1)) { if (tbuf[0] > 0 && tbuf[0] < 16) @@ -1421,7 +1411,7 @@ void loop() case 23: // set RGB order { - unsigned char tbuf[1]; + uint8_t tbuf[1]; if (SerialReadBuffer(tbuf, 1)) { if (tbuf[0] >= 0 && tbuf[0] < 6) @@ -1461,11 +1451,11 @@ void loop() // the WiFi Connection at startup. When WiFi is finally active, USB is turned off. case 27: // set WiFi SSID { - unsigned char tbuf[129]; + uint8_t tbuf[129]; if (SerialReadBuffer(tbuf, 129)) { // tbuf[0] now contains the length of the string - unsigned char *tmp = (unsigned char *)malloc(tbuf[0]); + uint8_t *tmp = (uint8_t *)malloc(tbuf[0]); memcpy(tmp, &tbuf[1], tbuf[0]); ssid = (const char *)tmp; free(tmp); @@ -1479,11 +1469,11 @@ void loop() case 28: // set WiFi password { - unsigned char tbuf[129]; + uint8_t tbuf[129]; if (SerialReadBuffer(tbuf, 129)) { // tbuf[0] now contains the length of the string - unsigned char *tmp = (unsigned char *)malloc(tbuf[0]); + uint8_t *tmp = (uint8_t *)malloc(tbuf[0]); memcpy(tmp, &tbuf[1], tbuf[0]); pwd = (const char *)tmp; free(tmp); @@ -1579,24 +1569,17 @@ void loop() break; } -#ifdef ZEDMD_HD +#if !defined(ZEDMD_WIFI) && defined(ZEDMD_HD) case 3: // mode RGB24 { - if (renderBufferInUse == 2) - { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (uint8_t *)malloc(16 * 8 * 3 + 1); - if (SerialReadBuffer(renderBuffer, 16 * 8 * 3)) + if (SerialReadBuffer(renderBuffer, 16 * 8 * 3 + 1)) { fillZoneRaw(renderBuffer[0], &renderBuffer[1]); - free(renderBuffer); } - - renderBufferInUse = 0; + + free(renderBuffer); break; } #endif @@ -1606,12 +1589,7 @@ void loop() { // We need to cover downscaling, too. int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_BYTES : RomWidth * RomHeight * 3; - if (renderBufferInUse == 2) - { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); + renderBuffer = (uint8_t *)malloc(renderBufferSize); memset(renderBuffer, 0, renderBufferSize); if (SerialReadBuffer(renderBuffer, RomHeight * RomWidth * 3)) @@ -1622,41 +1600,35 @@ void loop() } free(renderBuffer); - renderBufferInUse = 0; break; } case 8: // mode 4 couleurs avec 1 palette 4 couleurs (4*3 bytes) suivis de 4 pixels par byte { int bufferSize = 12 + 2 * RomWidthPlane * RomHeight; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + uint8_t *buffer = (uint8_t *)malloc(bufferSize); if (SerialReadBuffer(buffer, bufferSize)) { // We need to cover downscaling, too. int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) - { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); + renderBuffer = (uint8_t *)malloc(renderBufferSize); memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(12); + palette = (uint8_t *)malloc(12); memcpy(palette, buffer, 12); - unsigned char *frame = &buffer[12]; + uint8_t *frame = &buffer[12]; for (int tj = 0; tj < RomHeight; tj++) { for (int ti = 0; ti < RomWidthPlane; ti++) { - unsigned char mask = 1; - unsigned char planes[2]; + uint8_t mask = 1; + uint8_t planes[2]; planes[0] = frame[ti + tj * RomWidthPlane]; planes[1] = frame[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; for (int tk = 0; tk < 8; tk++) { - unsigned char idx = 0; + uint8_t idx = 0; if ((planes[0] & mask) > 0) idx |= 1; if ((planes[1] & mask) > 0) @@ -1674,7 +1646,6 @@ void loop() fillPanelUsingPalette(); free(renderBuffer); - renderBufferInUse = 0; free(palette); } else @@ -1687,20 +1658,15 @@ void loop() case 7: // mode 16 couleurs avec 1 palette 4 couleurs (4*3 bytes) suivis de 2 pixels par byte { int bufferSize = 12 + 4 * RomWidthPlane * RomHeight; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + uint8_t *buffer = (uint8_t *)malloc(bufferSize); if (SerialReadBuffer(buffer, bufferSize)) { // We need to cover downscaling, too. int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) - { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); + renderBuffer = (uint8_t *)malloc(renderBufferSize); memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(48); + palette = (uint8_t *)malloc(48); memcpy(palette, buffer, 48); palette[0] = palette[1] = palette[2] = 0; @@ -1741,20 +1707,20 @@ void loop() palette[43] = palette[11 * 3 + 1] + 3 * ((palette[15 * 3 + 1] - palette[11 * 3 + 1]) / 4); palette[44] = palette[11 * 3 + 2] + 3 * ((palette[15 * 3 + 2] - palette[11 * 3 + 2]) / 4); - unsigned char *pBuffer = &buffer[12]; + uint8_t *pBuffer = &buffer[12]; for (int tj = 0; tj < RomHeight; tj++) { for (int ti = 0; ti < RomWidthPlane; ti++) { - unsigned char mask = 1; - unsigned char planes[4]; + uint8_t mask = 1; + uint8_t planes[4]; planes[0] = pBuffer[ti + tj * RomWidthPlane]; planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; for (int tk = 0; tk < 8; tk++) { - unsigned char idx = 0; + uint8_t idx = 0; if ((planes[0] & mask) > 0) idx |= 1; if ((planes[1] & mask) > 0) @@ -1776,7 +1742,6 @@ void loop() fillPanelUsingPalette(); free(renderBuffer); - renderBufferInUse = 0; free(palette); } else @@ -1789,37 +1754,32 @@ void loop() case 9: // mode 16 couleurs avec 1 palette 16 couleurs (16*3 bytes) suivis de 4 bytes par groupe de 8 points (séparés en plans de bits 4*512 bytes) { int bufferSize = 48 + 4 * RomWidthPlane * RomHeight; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + uint8_t *buffer = (uint8_t *)malloc(bufferSize); if (SerialReadBuffer(buffer, bufferSize)) { // We need to cover downscaling, too. int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) - { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); + renderBuffer = (uint8_t *)malloc(renderBufferSize); memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(48); + palette = (uint8_t *)malloc(48); memcpy(palette, buffer, 48); - unsigned char *pBuffer = &buffer[48]; + uint8_t *pBuffer = &buffer[48]; for (int tj = 0; tj < RomHeight; tj++) { for (int ti = 0; ti < RomWidthPlane; ti++) { // on reconstitue un indice à partir des plans puis une couleur à partir de la palette - unsigned char mask = 1; - unsigned char planes[4]; + uint8_t mask = 1; + uint8_t planes[4]; planes[0] = pBuffer[ti + tj * RomWidthPlane]; planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; planes[3] = pBuffer[3 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; for (int tk = 0; tk < 8; tk++) { - unsigned char idx = 0; + uint8_t idx = 0; if ((planes[0] & mask) > 0) idx |= 1; if ((planes[1] & mask) > 0) @@ -1841,7 +1801,6 @@ void loop() fillPanelUsingPalette(); free(renderBuffer); - renderBufferInUse = 0; free(palette); } else @@ -1854,30 +1813,25 @@ void loop() case 11: // mode 64 couleurs avec 1 palette 64 couleurs (64*3 bytes) suivis de 6 bytes par groupe de 8 points (séparés en plans de bits 6*512 bytes) suivis de 3*8 bytes de rotations de couleurs { int bufferSize = 192 + 6 * RomWidthPlane * RomHeight + 3 * MAX_COLOR_ROTATIONS; - unsigned char *buffer = (unsigned char *)malloc(bufferSize); + uint8_t *buffer = (uint8_t *)malloc(bufferSize); if (SerialReadBuffer(buffer, bufferSize)) { // We need to cover downscaling, too. int renderBufferSize = (RomWidth < TOTAL_WIDTH || RomHeight < TOTAL_HEIGHT) ? TOTAL_WIDTH * TOTAL_HEIGHT : RomWidth * RomHeight; - if (renderBufferInUse == 2) - { - renderBufferInUse = 1; - free(renderBuffer); - } - renderBuffer = (unsigned char *)malloc(renderBufferSize); + renderBuffer = (uint8_t *)malloc(renderBufferSize); memset(renderBuffer, 0, renderBufferSize); - palette = (unsigned char *)malloc(192); + palette = (uint8_t *)malloc(192); memcpy(palette, buffer, 192); - unsigned char *pBuffer = &buffer[192]; + uint8_t *pBuffer = &buffer[192]; for (int tj = 0; tj < RomHeight; tj++) { for (int ti = 0; ti < RomWidthPlane; ti++) { // on reconstitue un indice à partir des plans puis une couleur à partir de la palette - unsigned char mask = 1; - unsigned char planes[6]; + uint8_t mask = 1; + uint8_t planes[6]; planes[0] = pBuffer[ti + tj * RomWidthPlane]; planes[1] = pBuffer[RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; planes[2] = pBuffer[2 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; @@ -1886,7 +1840,7 @@ void loop() planes[5] = pBuffer[5 * RomWidthPlane * RomHeight + ti + tj * RomWidthPlane]; for (int tk = 0; tk < 8; tk++) { - unsigned char idx = 0; + uint8_t idx = 0; if ((planes[0] & mask) > 0) idx |= 1; if ((planes[1] & mask) > 0) @@ -1928,7 +1882,6 @@ void loop() fillPanelUsingPalette(); free(renderBuffer); - renderBufferInUse = 0; free(palette); } else @@ -1955,7 +1908,7 @@ void loop() debugLines[0] = ++frameCount; for (int i = 0; i < 6; i++) { - Say((unsigned char)i, debugLines[i]); + Say((uint8_t)i, debugLines[i]); } } } From a40bb764f759b3c5352d5f73c144c50b92b69cd5 Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Thu, 14 Dec 2023 00:38:36 +0100 Subject: [PATCH 4/7] fixed WiFi startup screen --- src/main.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 38e9882..9ea5eaa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -961,14 +961,17 @@ void setup() udp.onPacket([](AsyncUDPPacket packet) { if (packet.length() >= 1) { + if (MireActive) + { + MireActive = false; + ClearScreen(); + } + uint8_t *pPacket = packet.data(); switch (pPacket[0]) { case 10: // clear screen { - if (MireActive) { - MireActive = false; - } ClearScreen(); break; } From 7ce66e037c7d65401367736ea3a268aa78ab1bd4 Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Sun, 17 Dec 2023 17:06:44 +0100 Subject: [PATCH 5/7] Use 8bit color depth for HD, removed doubel buffer, improved zones streaming --- platformio.ini | 4 +-- src/main.cpp | 81 ++++++++++++++++++-------------------------------- 2 files changed, 31 insertions(+), 54 deletions(-) diff --git a/platformio.ini b/platformio.ini index 46be150..6216690 100644 --- a/platformio.ini +++ b/platformio.ini @@ -44,7 +44,7 @@ lib_deps = build_flags = -DNO_GFX=1 -DZEDMD_HD=1 - -DPIXEL_COLOR_DEPTH_BITS=7 + -DPIXEL_COLOR_DEPTH_BITS=8 -DMINIZ_NO_STDIO=1 -DMINIZ_NO_TIME=1 -DMINIZ_NO_DEFLATE_APIS=1 @@ -87,7 +87,7 @@ build_flags = -DNO_GFX=1 -DZEDMD_HD=1 -DZEDMD_WIFI=1 - -DPIXEL_COLOR_DEPTH_BITS=7 + -DPIXEL_COLOR_DEPTH_BITS=8 -DMINIZ_NO_STDIO=1 -DMINIZ_NO_TIME=1 -DMINIZ_NO_DEFLATE_APIS=1 diff --git a/src/main.cpp b/src/main.cpp index 9ea5eaa..4200506 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,6 +38,7 @@ // Commands: // 2: set rom frame size as (int16) width, (int16) height // 3: render raw data, RGB24 +// 4: render raw data, RGB24 zones streaming // 6: init palette (deprectated, backward compatibility) // 7: render 16 colors using a 4 color palette (3*4 bytes), 2 pixels per byte // 8: render 4 colors using a 4 color palette (3*4 bytes), 4 pixels per byte @@ -70,6 +71,9 @@ #define TOTAL_WIDTH_PLANE (TOTAL_WIDTH >> 3) #define TOTAL_HEIGHT PANEL_HEIGHT #define TOTAL_BYTES (TOTAL_WIDTH * TOTAL_HEIGHT * 3) +#define ZONES_PER_ROW (TOTAL_WIDTH / 16) +#define TOTAL_ZONES ((TOTAL_HEIGHT / 8) * ZONES_PER_ROW) +#define ZONE_SIZE (16 * 8 * 3) #define MAX_COLOR_ROTATIONS 8 #define LED_CHECK_DELAY 1000 // ms per color @@ -95,8 +99,6 @@ unsigned long rotNextRotationTime[1]; #ifdef ZEDMD_HD unsigned long rotNextRotationTime[1]; #else -uint8_t doubleBuffer[TOTAL_BYTES] = {0}; - // color rotation uint8_t rotFirstColor[MAX_COLOR_ROTATIONS]; uint8_t rotAmountColors[MAX_COLOR_ROTATIONS]; @@ -297,9 +299,6 @@ void ClearScreen() { dma_display->clearScreen(); dma_display->setBrightness8(lumval[lumstep]); -#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) - memset(doubleBuffer, 0, TOTAL_BYTES); -#endif } #if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) @@ -609,27 +608,10 @@ void ScaleImage(uint8_t colors) } #endif -void DrawPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) -{ -#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) - int pos = (y * TOTAL_WIDTH + x) * 3; - - if (r != doubleBuffer[pos] || g != doubleBuffer[pos + 1] || b != doubleBuffer[pos + 2]) - { - doubleBuffer[pos] = r; - doubleBuffer[pos + 1] = g; - doubleBuffer[pos + 2] = b; -#endif - dma_display->drawPixelRGB888(x, y, r, g, b); -#if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) - } -#endif -} - void fillZoneRaw(uint8_t idx, uint8_t *pBuffer) { - uint8_t yOffset = idx / (TOTAL_WIDTH / 16) * 8; - uint8_t xOffset = (idx % (TOTAL_WIDTH / 16)) * 16; + uint8_t yOffset = (idx / ZONES_PER_ROW) * 8; + uint8_t xOffset = (idx % ZONES_PER_ROW) * 16; for (uint8_t y = 0; y < 8; y++) { @@ -637,7 +619,7 @@ void fillZoneRaw(uint8_t idx, uint8_t *pBuffer) { uint16_t pos = (y * 16 + x) * 3; - DrawPixel( + dma_display->drawPixelRGB888( x + xOffset, y + yOffset, pBuffer[pos + ordreRGB[acordreRGB * 3]], @@ -657,7 +639,7 @@ void fillPanelRaw() { pos = (y * TOTAL_WIDTH + x) * 3; - DrawPixel( + dma_display->drawPixelRGB888( x, y, renderBuffer[pos + ordreRGB[acordreRGB * 3]], @@ -677,7 +659,7 @@ void fillPanelUsingPalette() { pos = renderBuffer[y * TOTAL_WIDTH + x] * 3; - DrawPixel( + dma_display->drawPixelRGB888( x, y, palette[pos + ordreRGB[acordreRGB * 3]], @@ -700,7 +682,7 @@ void fillPanelUsingChangedPalette(bool *paletteAffected) if (paletteAffected[pos]) { pos *= 3; - DrawPixel( + dma_display->drawPixelRGB888( x, y, palette[pos + ordreRGB[acordreRGB * 3]], @@ -1014,7 +996,7 @@ void setup() #endif } -bool SerialReadBuffer(uint8_t *pBuffer, unsigned int BufferSize) +bool SerialReadBuffer(uint8_t *pBuffer, unsigned int BufferSize, bool fixedSize = true) { memset(pBuffer, 0, BufferSize); @@ -1095,7 +1077,7 @@ bool SerialReadBuffer(uint8_t *pBuffer, unsigned int BufferSize) debugLines[3] = tmp_status; } - if ((MZ_OK == status) && (uncompressed_buffer_size == BufferSize)) + if ((MZ_OK == status) && (!fixedSize || (fixedSize && uncompressed_buffer_size == BufferSize))) { if (debugMode) { @@ -1103,11 +1085,6 @@ bool SerialReadBuffer(uint8_t *pBuffer, unsigned int BufferSize) debugLines[3] = 0; } - while (Serial.available()) - { - Serial.read(); - } - return true; } @@ -1118,20 +1095,10 @@ bool SerialReadBuffer(uint8_t *pBuffer, unsigned int BufferSize) debugLines[3] = 99; } - while (Serial.available()) - { - Serial.read(); - } - Serial.write('E'); return false; } - while (Serial.available()) - { - Serial.read(); - } - return true; } @@ -1178,6 +1145,12 @@ bool wait_for_ctrl_chars(void) if (Serial.read() != CtrlCharacters[nCtrlCharFound++]) { nCtrlCharFound = 0; + if (debugMode) + { + // There's garbage on the line. + Say(3, 666); + debugLines[3] = 666; + } } } @@ -1572,20 +1545,24 @@ void loop() break; } -#if !defined(ZEDMD_WIFI) && defined(ZEDMD_HD) - case 3: // mode RGB24 + case 4: // mode RGB24 zones streaming { - renderBuffer = (uint8_t *)malloc(16 * 8 * 3 + 1); - - if (SerialReadBuffer(renderBuffer, 16 * 8 * 3 + 1)) + renderBuffer = (uint8_t *)malloc(TOTAL_ZONES * ZONE_SIZE + ZONES_PER_ROW); + if (SerialReadBuffer(renderBuffer, TOTAL_ZONES * ZONE_SIZE + ZONES_PER_ROW, false)) { - fillZoneRaw(renderBuffer[0], &renderBuffer[1]); + uint16_t idx = 0; + // SerialReadBuffer prefills buffer with zeros. That will fill Zone 0 black if buffer is not used entirely. + // Ensure that Zone 0 is only allowed at the beginning of the buffer. + while (idx <= ((TOTAL_ZONES * ZONE_SIZE + ZONES_PER_ROW) - (ZONE_SIZE + 1)) && (renderBuffer[idx] < TOTAL_ZONES) && (idx == 0 || renderBuffer[idx] > 0)) + { + fillZoneRaw(renderBuffer[idx], &renderBuffer[++idx]); + idx += ZONE_SIZE; + } } free(renderBuffer); break; } -#endif #if !defined(ZEDMD_WIFI) && !defined(ZEDMD_HD) case 3: // mode RGB24 From 392c481638ff93c2c02bb3a726de48f0f9832328 Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Mon, 18 Dec 2023 00:30:59 +0100 Subject: [PATCH 6/7] reduced color depth for HD --- platformio.ini | 4 ++-- src/main.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6216690..46be150 100644 --- a/platformio.ini +++ b/platformio.ini @@ -44,7 +44,7 @@ lib_deps = build_flags = -DNO_GFX=1 -DZEDMD_HD=1 - -DPIXEL_COLOR_DEPTH_BITS=8 + -DPIXEL_COLOR_DEPTH_BITS=7 -DMINIZ_NO_STDIO=1 -DMINIZ_NO_TIME=1 -DMINIZ_NO_DEFLATE_APIS=1 @@ -87,7 +87,7 @@ build_flags = -DNO_GFX=1 -DZEDMD_HD=1 -DZEDMD_WIFI=1 - -DPIXEL_COLOR_DEPTH_BITS=8 + -DPIXEL_COLOR_DEPTH_BITS=7 -DMINIZ_NO_STDIO=1 -DMINIZ_NO_TIME=1 -DMINIZ_NO_DEFLATE_APIS=1 diff --git a/src/main.cpp b/src/main.cpp index 4200506..4935492 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,7 +17,7 @@ #define SERIAL_TIMEOUT 8 // Time in milliseconds to wait for the next data chunk. #define SERIAL_BUFFER 8192 // Serial buffer size in byte. #define LOGO_TIMEOUT 20000 // Time in milliseconds before the logo vanishes. -#define FLOW_CONTROL_TIMEOUT 1 // Time in milliseconds to wait before sensinf a new ready signal. +#define FLOW_CONTROL_TIMEOUT 1 // Time in milliseconds to wait before sending a new ready signal. // ------------------------------------------ ZeDMD by MK47 & Zedrummer (http://ppuc.org) -------------------------------------------------- // - If you have blurry pictures, the display is not clean, try to reduce the input voltage of your LED matrix panels, often, 5V panels need From 543bacee48d94f436dc663911c051c10971b7b7a Mon Sep 17 00:00:00 2001 From: Markus Kalkbrenner Date: Mon, 18 Dec 2023 00:57:10 +0100 Subject: [PATCH 7/7] build wifi variations --- .github/workflows/ZeDMD.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ZeDMD.yml b/.github/workflows/ZeDMD.yml index 2cddbe5..5cdf6df 100644 --- a/.github/workflows/ZeDMD.yml +++ b/.github/workflows/ZeDMD.yml @@ -29,7 +29,7 @@ jobs: needs: [ version ] strategy: matrix: - panels: ['128x32', '256x64', '256x64_7bit'] + panels: ['128x32', '256x64', '128x32_wifi', '256x64_wifi'] name: ZeDMD ${{ matrix.panels }} @@ -89,9 +89,12 @@ jobs: cd ../ZeDMD-256x64 echo "${{ needs.version.outputs.tag }}" > version.txt zip ../ZeDMD-256x64.zip ZeDMD.bin version.txt - cd ../ZeDMD-256x64_7bit + cd ../ZeDMD-128x32_wifi echo "${{ needs.version.outputs.tag }}" > version.txt - zip ../ZeDMD-256x64_7bit.zip ZeDMD.bin version.txt + zip ../ZeDMD-128x32_wifi.zip ZeDMD.bin version.txt + cd ../ZeDMD-256x64_wifi + echo "${{ needs.version.outputs.tag }}" > version.txt + zip ../ZeDMD-256x64_wifi.zip ZeDMD.bin version.txt cd .. - name: Release uses: softprops/action-gh-release@v1 @@ -101,4 +104,5 @@ jobs: files: | ZeDMD-128x32.zip ZeDMD-256x64.zip - ZeDMD-256x64_7bit.zip + ZeDMD-128x32_wifi.zip + ZeDMD-256x64_wifi.zip