From f5681b298356833177bc1dc26f5f00ebd6ca578d Mon Sep 17 00:00:00 2001 From: mrfaptastic <12006953+mrfaptastic@users.noreply.github.com> Date: Mon, 6 Sep 2021 16:29:38 +0100 Subject: [PATCH] Backport tx fifo byte ordering fix for ESP32-WROOM-32 --- ESP32-HUB75-MatrixPanel-I2S-DMA.cpp | 63 ++++++++++++++++++++++++----- ESP32-HUB75-MatrixPanel-I2S-DMA.h | 26 ++++++------ 2 files changed, 67 insertions(+), 22 deletions(-) diff --git a/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp b/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp index d9d4ca9..a0bee63 100644 --- a/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp +++ b/ESP32-HUB75-MatrixPanel-I2S-DMA.cpp @@ -1,6 +1,5 @@ #include #include "ESP32-HUB75-MatrixPanel-I2S-DMA.h" -//#include "xtensa/core-macros.h" // Credits: Louis Beaudoin // and Sprite_TM: https://www.esp32.com/viewtopic.php?f=17&t=3188 and https://www.esp32.com/viewtopic.php?f=13&t=3256 @@ -484,10 +483,14 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16 * data. */ +#ifndef ESP32_S2 // We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel // 16 bit parallel mode - Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering + // Irrelevant for ESP32-S2 the way the FIFO ordering works is different - refer to page 679 of S2 technical reference manual x_coord & 1U ? --x_coord : ++x_coord; +#endif + uint16_t _colorbitclear = BITMASK_RGB1_CLEAR, _colorbitoffset = 0; if (y_coord >= ROWS_PER_FRAME){ // if we are drawing to the bottom part of the panel @@ -661,24 +664,46 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){ // let's set LAT/OE control bits for specific pixels in each color_index subrows + // Need to consider the original ESP32's (WROOM) DMA TX FIFO reordering of bytes... uint8_t coloridx = dma_buff.rowBits[row_idx]->color_depth; do { --coloridx; - // switch pointer to a row for a specific color index - row = dma_buff.rowBits[row_idx]->getDataPtr(coloridx, _buff_id); + // switch pointer to a row for a specific color index + row = dma_buff.rowBits[row_idx]->getDataPtr(coloridx, _buff_id); - // drive latch while shifting out last bit of RGB data - row[dma_buff.rowBits[row_idx]->width - 2] |= BIT_LAT; // -1 pixel to compensate array index starting at 0 - //row[dma_buff.rowBits[row_idx]->width - 1] |= BIT_LAT; // -1 pixel to compensate array index starting at 0 + #ifdef ESP32_S2 + // -1 works better on ESP32-S2 ? Because bytes get sent out in order... + row[dma_buff.rowBits[row_idx]->width - 1] |= BIT_LAT; // -1 pixel to compensate array index starting at 0 + #else + // We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel + // 16 bit parallel mode - Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering + // Irrelevant for ESP32-S2 the way the FIFO ordering works is different - refer to page 679 of S2 technical reference manual + row[dma_buff.rowBits[row_idx]->width - 2] |= BIT_LAT; // -2 in the DMA array is actually -1 when it's reordered by TX FIFO + #endif // need to disable OE before/after latch to hide row transition // Should be one clock or more before latch, otherwise can get ghosting uint8_t _blank = m_cfg.latch_blanking; do { --_blank; - row[0 + _blank] |= BIT_OE; - row[dma_buff.rowBits[row_idx]->width - _blank - 3 ] |= BIT_OE; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0 + + #ifdef ESP32_S2 + row[0 + _blank] |= BIT_OE; + row[dma_buff.rowBits[row_idx]->width - _blank - 1 ] |= BIT_OE; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0 + #else + + // Original ESP32 WROOM FIFO Ordering Sucks + uint8_t _blank_row_tx_fifo_tmp = 0 + _blank; + (_blank_row_tx_fifo_tmp & 1U) ? --_blank_row_tx_fifo_tmp : ++_blank_row_tx_fifo_tmp; + row[_blank_row_tx_fifo_tmp] |= BIT_OE; + + _blank_row_tx_fifo_tmp = dma_buff.rowBits[row_idx]->width - _blank - 1; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0 + (_blank_row_tx_fifo_tmp & 1U) ? --_blank_row_tx_fifo_tmp : ++_blank_row_tx_fifo_tmp; + row[_blank_row_tx_fifo_tmp] |= BIT_OE; + + #endif + } while (_blank); } while(coloridx); @@ -741,7 +766,17 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){ uint8_t _blank = m_cfg.latch_blanking; do { --_blank; - row[0 + _blank] |= BIT_OE; + + #ifdef ESP32_S2 + row[0 + _blank] |= BIT_OE; + #else + // Original ESP32 WROOM FIFO Ordering Sucks + uint8_t _blank_row_tx_fifo_tmp = 0 + _blank; + (_blank_row_tx_fifo_tmp & 1U) ? --_blank_row_tx_fifo_tmp : ++_blank_row_tx_fifo_tmp; + row[_blank_row_tx_fifo_tmp] |= BIT_OE; + #endif + + //row[0 + _blank] |= BIT_OE; // no need, has been done already //row[dma_buff.rowBits[row_idx]->width - _blank - 3 ] |= BIT_OE; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0 } while (_blank); @@ -860,8 +895,14 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l, int16_t _l = l; do { // iterate pixels in a row int16_t _x = x_coord + --_l; + +#ifdef ESP32_S2 + // ESP 32 doesn't need byte flipping for TX FIFO. + uint16_t &v = p[_x]; +#else // Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering uint16_t &v = p[_x & 1U ? --_x : ++_x]; +#endif v &= _colorbitclear; // reset color bits v |= RGB_output_bits; // set new color bits @@ -896,8 +937,10 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l, blue = lumConvTab[blue]; #endif - // Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering +#ifndef ESP32_S2 + // Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering x_coord & 1U ? --x_coord : ++x_coord; +#endif uint8_t color_depth_idx = PIXEL_COLOR_DEPTH_BITS; do { // Iterating through color depth bits (8 iterations) diff --git a/ESP32-HUB75-MatrixPanel-I2S-DMA.h b/ESP32-HUB75-MatrixPanel-I2S-DMA.h index 7b4212a..66cc20a 100644 --- a/ESP32-HUB75-MatrixPanel-I2S-DMA.h +++ b/ESP32-HUB75-MatrixPanel-I2S-DMA.h @@ -1,17 +1,16 @@ #ifndef _ESP32_RGB_64_32_MATRIX_PANEL_I2S_DMA #define _ESP32_RGB_64_32_MATRIX_PANEL_I2S_DMA -/***************************************************************************************/ -/* COMPILE-TIME OPTIONS - Provide as part of PlatformIO project build_flags. */ -/***************************************************************************************/ +/******************************************************************************************* + * COMPILE-TIME OPTIONS - MUST BE PROVIDED as part of PlatformIO project build_flags. * + * Changing the values just here won't work - as defines needs to persist beyond the scope * + * of just this file. * + *******************************************************************************************/ /* Enable serial debugging of the library, to see how memory is allocated etc. */ //#define SERIAL_DEBUG 1 - -/* - * Do NOT build additional methods optimized for fast drawing, - * i.e. Adafruits drawFastHLine, drawFastVLine, etc... - */ +/* Do NOT build additional methods optimized for fast drawing, + * i.e. Adafruits drawFastHLine, drawFastVLine, etc... */ //#define NO_FAST_FUNCTIONS /* Use GFX_Root (https://github.com/mrfaptastic/GFX_Root) instead of Adafruit_GFX library. @@ -21,7 +20,6 @@ */ //#define USE_GFX_ROOT 1 - /* Physical / Chained HUB75(s) RGB pixel WIDTH and HEIGHT. * * This library has been tested with a 64x32 and 64x64 RGB panels. @@ -87,11 +85,16 @@ // #define NO_CIE1931 /***************************************************************************************/ -/* Library Includes! */ +/* Core ESP32 hardware / idf includes! */ #include #include #include "esp_heap_caps.h" -#include "esp32_i2s_parallel_v2.h" + +#ifdef ESP32_S2 + #include "esp32-s2_i2s_parallel_v1.h" +#else + #include "esp32_i2s_parallel_v2.h" +#endif #ifdef USE_GFX_ROOT #include @@ -101,7 +104,6 @@ #endif - /***************************************************************************************/ /* Definitions below should NOT be ever changed without rewriting library logic */ #define ESP32_I2S_DMA_MODE I2S_PARALLEL_WIDTH_16 // From esp32_i2s_parallel_v2.h = 16 bits in parallel