Fix hidden TX FIFO ordering bugs
On ESP32 original only. Turn byte ordering logic into a compiler macro.
This commit is contained in:
parent
1d29c7b520
commit
69686a3747
2 changed files with 44 additions and 16 deletions
|
@ -8,6 +8,16 @@ static const char* TAG = "MatrixPanel";
|
|||
*/
|
||||
#define getRowDataPtr(row, _dpth, buff_id) &(dma_buff.rowBits[row]->data[_dpth * dma_buff.rowBits[row]->width + buff_id*(dma_buff.rowBits[row]->width * dma_buff.rowBits[row]->colour_depth)])
|
||||
|
||||
// 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
|
||||
#if defined (ESP32_THE_ORIG)
|
||||
#define ESP32_TX_FIFO_POSITION_ADJUST(x_coord) (x_coord & 1U ? (x_coord-1):(x_coord+1))
|
||||
#else
|
||||
#define ESP32_TX_FIFO_POSITION_ADJUST(x_coord) x_coord
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||
{
|
||||
|
@ -240,15 +250,17 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
|||
* Let's put it into IRAM to avoid situations when it could be flushed out of instruction cache
|
||||
* and had to be read from spi-flash over and over again.
|
||||
* Yes, it is always a tradeoff between memory/speed/size, but compared to DMA-buffer size is not a big deal
|
||||
*
|
||||
* Note: Cannot pass a negative co-ord as it makes no sense in the DMA bit array lookup.
|
||||
*/
|
||||
void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t y_coord, uint8_t red, uint8_t green, uint8_t blue)
|
||||
void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint16_t x_coord, uint16_t y_coord, uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
if ( !initialized ) return;
|
||||
|
||||
/* 1) Check that the co-ordinates are within range, or it'll break everything big time.
|
||||
* Valid co-ordinates are from 0 to (MATRIX_XXXX-1)
|
||||
*/
|
||||
if ( x_coord < 0 || y_coord < 0 || x_coord >= PIXELS_PER_ROW || y_coord >= m_cfg.mx_height) {
|
||||
if ( x_coord >= PIXELS_PER_ROW || y_coord >= m_cfg.mx_height) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -274,13 +286,15 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16
|
|||
* so we have to check for this and check the correct position of the MATRIX_DATA_STORAGE_TYPE
|
||||
* data.
|
||||
*/
|
||||
|
||||
/*
|
||||
#if defined (ESP32_THE_ORIG)
|
||||
// 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
|
||||
*/
|
||||
x_coord = ESP32_TX_FIFO_POSITION_ADJUST(x_coord);
|
||||
|
||||
|
||||
uint16_t _colourbitclear = BITMASK_RGB1_CLEAR, _colourbitoffset = 0;
|
||||
|
@ -417,7 +431,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
|||
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164
|
||||
row[x_pixel] = abcde & (0x18 << BITS_ADDR_OFFSET); // mask out the bottom 3 bits which are the clk di bk inputs
|
||||
} else {
|
||||
row[x_pixel] = abcde;
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(x_pixel)] = abcde;
|
||||
}
|
||||
// ESP_LOGI(TAG, "x pixel 1: %d", x_pixel);
|
||||
} while(x_pixel!=dma_buff.rowBits[row_idx]->width && x_pixel);
|
||||
|
@ -433,7 +447,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
|||
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164
|
||||
row[x_pixel] = abcde & (0x18 << BITS_ADDR_OFFSET); // mask out the bottom 3 bits which are the clk di bk inputs
|
||||
} else {
|
||||
row[x_pixel] = abcde;
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(x_pixel)] = abcde;
|
||||
}
|
||||
//row[x_pixel] = abcde;
|
||||
// ESP_LOGI(TAG, "x pixel 2: %d", x_pixel);
|
||||
|
@ -465,6 +479,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
|||
// switch pointer to a row for a specific color index
|
||||
row = dma_buff.rowBits[row_idx]->getDataPtr(colouridx, _buff_id);
|
||||
|
||||
/*
|
||||
#if defined(ESP32_THE_ORIG)
|
||||
// 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
|
||||
|
@ -474,13 +489,17 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
|||
// -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
|
||||
#endif
|
||||
*/
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(dma_buff.rowBits[row_idx]->width - 1)] |= BIT_LAT; // -1 pixel to compensate array index starting at 0
|
||||
|
||||
//ESP32_TX_FIFO_POSITION_ADJUST(dma_buff.rowBits[row_idx]->width - 1)
|
||||
|
||||
// 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;
|
||||
|
||||
/*
|
||||
#if defined(ESP32_THE_ORIG)
|
||||
// Original ESP32 WROOM FIFO Ordering Sucks
|
||||
uint8_t _blank_row_tx_fifo_tmp = 0 + _blank;
|
||||
|
@ -494,6 +513,11 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
|||
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
|
||||
#endif
|
||||
*/
|
||||
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(0 + _blank)] |= BIT_OE;
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(dma_buff.rowBits[row_idx]->width - _blank - 1)] |= BIT_OE; // (LAT pulse is (width-2) -1 pixel to compensate array index starting at 0
|
||||
|
||||
|
||||
} while (_blank);
|
||||
|
||||
|
@ -535,11 +559,11 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
|||
--x_coord;
|
||||
|
||||
// clear OE bit for all other pixels
|
||||
row[x_coord] &= BITMASK_OE_CLEAR;
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] &= BITMASK_OE_CLEAR;
|
||||
|
||||
// Brightness control via OE toggle - disable matrix output at specified x_coord
|
||||
if((colouridx > lsbMsbTransitionBit || !colouridx) && ((x_coord) >= brt)){
|
||||
row[x_coord] |= BIT_OE; // Disable output after this point.
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] |= BIT_OE; // Disable output after this point.
|
||||
continue;
|
||||
}
|
||||
// special case for the bits *after* LSB through (lsbMsbTransitionBit) - OE is output after data is shifted, so need to set OE to fractional brightness
|
||||
|
@ -547,7 +571,7 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
|||
// divide brightness in half for each bit below lsbMsbTransitionBit
|
||||
int lsbBrightness = brt >> (lsbMsbTransitionBit - colouridx + 1);
|
||||
if((x_coord) >= lsbBrightness) {
|
||||
row[x_coord] |= BIT_OE; // Disable output after this point.
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(x_coord)] |= BIT_OE; // Disable output after this point.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -560,7 +584,7 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
|||
uint8_t _blank = m_cfg.latch_blanking;
|
||||
do {
|
||||
--_blank;
|
||||
|
||||
/*
|
||||
#if defined(ESP32_THE_ORIG)
|
||||
// Original ESP32 WROOM FIFO Ordering Sucks
|
||||
uint8_t _blank_row_tx_fifo_tmp = 0 + _blank;
|
||||
|
@ -569,6 +593,10 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
|||
#else
|
||||
row[0 + _blank] |= BIT_OE;
|
||||
#endif
|
||||
*/
|
||||
|
||||
row[ESP32_TX_FIFO_POSITION_ADJUST(0 + _blank)] |= BIT_OE;
|
||||
|
||||
|
||||
//row[0 + _blank] |= BIT_OE;
|
||||
// no need, has been done already
|
||||
|
|
|
@ -113,8 +113,8 @@
|
|||
#define BITMASK_CTRL_CLEAR (0b1110000000111111) // inverted bitmask for control bits ABCDE,LAT,OE in pixel vector
|
||||
#define BITMASK_OE_CLEAR (0b1111111101111111) // inverted bitmask for control bit OE in pixel vector
|
||||
|
||||
// How many clock cycles to blank OE before/after LAT signal change, default is 1 clock
|
||||
#define DEFAULT_LAT_BLANKING 1
|
||||
// How many clock cycles to blank OE before/after LAT signal change, default is 2 clocks
|
||||
#define DEFAULT_LAT_BLANKING 2
|
||||
|
||||
// Max clock cycles to blank OE before/after LAT signal change
|
||||
#define MAX_LAT_BLANKING 4
|
||||
|
@ -280,7 +280,7 @@ struct HUB75_I2S_CFG {
|
|||
shift_driver _drv = SHIFTREG,
|
||||
bool _dbuff = false,
|
||||
clk_speed _i2sspeed = HZ_10M,
|
||||
uint8_t _latblk = 1, // Anything > 1 seems to cause artefacts on ICS panels
|
||||
uint8_t _latblk = DEFAULT_LAT_BLANKING, // Anything > 1 seems to cause artefacts on ICS panels
|
||||
bool _clockphase = true,
|
||||
uint8_t _min_refresh_rate = 85
|
||||
) : mx_width(_w),
|
||||
|
@ -406,7 +406,7 @@ class MatrixPanel_I2S_DMA {
|
|||
/**
|
||||
* A wrapper to fill whatever selected DMA buffer / screen with black
|
||||
*/
|
||||
inline void clearScreen(){ updateMatrixDMABuffer(0,0,0); };
|
||||
inline void clearScreen(){ clearFrameBuffer(back_buffer_id); /*updateMatrixDMABuffer(0,0,0);*/ };
|
||||
|
||||
#ifndef NO_FAST_FUNCTIONS
|
||||
/**
|
||||
|
@ -582,7 +582,7 @@ class MatrixPanel_I2S_DMA {
|
|||
void clearFrameBuffer(bool _buff_id = 0);
|
||||
|
||||
/* Update a specific pixel in the DMA buffer to a colour */
|
||||
void updateMatrixDMABuffer(int16_t x, int16_t y, uint8_t red, uint8_t green, uint8_t blue);
|
||||
void updateMatrixDMABuffer(uint16_t x, uint16_t y, uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
/* Update the entire DMA buffer (aka. The RGB Panel) a certain colour (wipe the screen basically) */
|
||||
void updateMatrixDMABuffer(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
|
Loading…
Reference in a new issue