Backport tx fifo byte ordering fix for ESP32-WROOM-32

This commit is contained in:
mrfaptastic 2021-09-06 16:29:38 +01:00
parent 2f8f465cc6
commit f5681b2983
2 changed files with 67 additions and 22 deletions

View file

@ -1,6 +1,5 @@
#include <Arduino.h> #include <Arduino.h>
#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h" #include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
//#include "xtensa/core-macros.h"
// Credits: Louis Beaudoin <https://github.com/pixelmatix/SmartMatrix/tree/teensylc> // Credits: Louis Beaudoin <https://github.com/pixelmatix/SmartMatrix/tree/teensylc>
// and Sprite_TM: https://www.esp32.com/viewtopic.php?f=17&t=3188 and https://www.esp32.com/viewtopic.php?f=13&t=3256 // 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. * data.
*/ */
#ifndef ESP32_S2
// We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel // 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 // 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; x_coord & 1U ? --x_coord : ++x_coord;
#endif
uint16_t _colorbitclear = BITMASK_RGB1_CLEAR, _colorbitoffset = 0; 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 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 // 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; uint8_t coloridx = dma_buff.rowBits[row_idx]->color_depth;
do { do {
--coloridx; --coloridx;
// switch pointer to a row for a specific color index // switch pointer to a row for a specific color index
row = dma_buff.rowBits[row_idx]->getDataPtr(coloridx, _buff_id); row = dma_buff.rowBits[row_idx]->getDataPtr(coloridx, _buff_id);
// drive latch while shifting out last bit of RGB data #ifdef ESP32_S2
row[dma_buff.rowBits[row_idx]->width - 2] |= BIT_LAT; // -1 pixel to compensate array index starting at 0 // -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 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 // need to disable OE before/after latch to hide row transition
// Should be one clock or more before latch, otherwise can get ghosting // Should be one clock or more before latch, otherwise can get ghosting
uint8_t _blank = m_cfg.latch_blanking; uint8_t _blank = m_cfg.latch_blanking;
do { do {
--_blank; --_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 (_blank);
} while(coloridx); } while(coloridx);
@ -741,7 +766,17 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
uint8_t _blank = m_cfg.latch_blanking; uint8_t _blank = m_cfg.latch_blanking;
do { do {
--_blank; --_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 // 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 //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); } 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; int16_t _l = l;
do { // iterate pixels in a row do { // iterate pixels in a row
int16_t _x = x_coord + --_l; 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 // 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]; uint16_t &v = p[_x & 1U ? --_x : ++_x];
#endif
v &= _colorbitclear; // reset color bits v &= _colorbitclear; // reset color bits
v |= RGB_output_bits; // set new 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]; blue = lumConvTab[blue];
#endif #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; x_coord & 1U ? --x_coord : ++x_coord;
#endif
uint8_t color_depth_idx = PIXEL_COLOR_DEPTH_BITS; uint8_t color_depth_idx = PIXEL_COLOR_DEPTH_BITS;
do { // Iterating through color depth bits (8 iterations) do { // Iterating through color depth bits (8 iterations)

View file

@ -1,17 +1,16 @@
#ifndef _ESP32_RGB_64_32_MATRIX_PANEL_I2S_DMA #ifndef _ESP32_RGB_64_32_MATRIX_PANEL_I2S_DMA
#define _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. */ /* Enable serial debugging of the library, to see how memory is allocated etc. */
//#define SERIAL_DEBUG 1 //#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 //#define NO_FAST_FUNCTIONS
/* Use GFX_Root (https://github.com/mrfaptastic/GFX_Root) instead of Adafruit_GFX library. /* Use GFX_Root (https://github.com/mrfaptastic/GFX_Root) instead of Adafruit_GFX library.
@ -21,7 +20,6 @@
*/ */
//#define USE_GFX_ROOT 1 //#define USE_GFX_ROOT 1
/* Physical / Chained HUB75(s) RGB pixel WIDTH and HEIGHT. /* Physical / Chained HUB75(s) RGB pixel WIDTH and HEIGHT.
* *
* This library has been tested with a 64x32 and 64x64 RGB panels. * This library has been tested with a 64x32 and 64x64 RGB panels.
@ -87,11 +85,16 @@
// #define NO_CIE1931 // #define NO_CIE1931
/***************************************************************************************/ /***************************************************************************************/
/* Library Includes! */ /* Core ESP32 hardware / idf includes! */
#include <vector> #include <vector>
#include <memory> #include <memory>
#include "esp_heap_caps.h" #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 #ifdef USE_GFX_ROOT
#include <FastLED.h> #include <FastLED.h>
@ -101,7 +104,6 @@
#endif #endif
/***************************************************************************************/ /***************************************************************************************/
/* Definitions below should NOT be ever changed without rewriting library logic */ /* 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 #define ESP32_I2S_DMA_MODE I2S_PARALLEL_WIDTH_16 // From esp32_i2s_parallel_v2.h = 16 bits in parallel