Cleanup
Consistent spelling of 'colour', double buffering works technically on S3.
This commit is contained in:
parent
f0a5d1ad54
commit
69e75cde12
8 changed files with 197 additions and 271 deletions
|
@ -20,13 +20,11 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
// iterate through number of rows
|
// iterate through number of rows
|
||||||
for (int malloc_num =0; malloc_num < ROWS_PER_FRAME; ++malloc_num)
|
for (int malloc_num =0; malloc_num < ROWS_PER_FRAME; ++malloc_num)
|
||||||
{
|
{
|
||||||
auto ptr = std::make_shared<rowBitStruct>(PIXELS_PER_ROW, PIXEL_COLOR_DEPTH_BITS, m_cfg.double_buff);
|
auto ptr = std::make_shared<rowBitStruct>(PIXELS_PER_ROW, PIXEL_COLOUR_DEPTH_BITS, m_cfg.double_buff);
|
||||||
|
|
||||||
if (ptr->data == nullptr)
|
if (ptr->data == nullptr)
|
||||||
{
|
{
|
||||||
#if SERIAL_DEBUG
|
ESP_LOGE(TAG, "ERROR: Couldn't malloc rowBitStruct %d! Critical fail.\r\n", malloc_num);
|
||||||
Serial.printf_P(PSTR("ERROR: Couldn't malloc rowBitStruct %d! Critical fail.\r\n"), malloc_num);
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
// TODO: should we release all previous rowBitStructs here???
|
// TODO: should we release all previous rowBitStructs here???
|
||||||
}
|
}
|
||||||
|
@ -41,24 +39,22 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
int nsPerLatch = ((PIXELS_PER_ROW + CLKS_DURING_LATCH) * psPerClock) / 1000;
|
int nsPerLatch = ((PIXELS_PER_ROW + CLKS_DURING_LATCH) * psPerClock) / 1000;
|
||||||
|
|
||||||
// add time to shift out LSBs + LSB-MSB transition bit - this ignores fractions...
|
// add time to shift out LSBs + LSB-MSB transition bit - this ignores fractions...
|
||||||
int nsPerRow = PIXEL_COLOR_DEPTH_BITS * nsPerLatch;
|
int nsPerRow = PIXEL_COLOUR_DEPTH_BITS * nsPerLatch;
|
||||||
|
|
||||||
// add time to shift out MSBs
|
// add time to shift out MSBs
|
||||||
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_DEPTH_BITS; i++)
|
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOUR_DEPTH_BITS; i++)
|
||||||
nsPerRow += (1<<(i - lsbMsbTransitionBit - 1)) * (PIXEL_COLOR_DEPTH_BITS - i) * nsPerLatch;
|
nsPerRow += (1<<(i - lsbMsbTransitionBit - 1)) * (PIXEL_COLOUR_DEPTH_BITS - i) * nsPerLatch;
|
||||||
|
|
||||||
int nsPerFrame = nsPerRow * ROWS_PER_FRAME;
|
int nsPerFrame = nsPerRow * ROWS_PER_FRAME;
|
||||||
int actualRefreshRate = 1000000000UL/(nsPerFrame);
|
int actualRefreshRate = 1000000000UL/(nsPerFrame);
|
||||||
calculated_refresh_rate = actualRefreshRate;
|
calculated_refresh_rate = actualRefreshRate;
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
ESP_LOGW(TAG, "lsbMsbTransitionBit of %d gives %d Hz refresh rate.", lsbMsbTransitionBit, actualRefreshRate);
|
||||||
Serial.printf_P(PSTR("lsbMsbTransitionBit of %d gives %d Hz refresh: \r\n"), lsbMsbTransitionBit, actualRefreshRate);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (actualRefreshRate > m_cfg.min_refresh_rate)
|
if (actualRefreshRate > m_cfg.min_refresh_rate)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(lsbMsbTransitionBit < PIXEL_COLOR_DEPTH_BITS - 1)
|
if(lsbMsbTransitionBit < PIXEL_COLOUR_DEPTH_BITS - 1)
|
||||||
lsbMsbTransitionBit++;
|
lsbMsbTransitionBit++;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
|
@ -71,22 +67,20 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
* memory allocation of the DMA linked list memory structure.
|
* memory allocation of the DMA linked list memory structure.
|
||||||
*/
|
*/
|
||||||
int numDMAdescriptorsPerRow = 1;
|
int numDMAdescriptorsPerRow = 1;
|
||||||
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_DEPTH_BITS; i++) {
|
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOUR_DEPTH_BITS; i++) {
|
||||||
numDMAdescriptorsPerRow += (1<<(i - lsbMsbTransitionBit - 1));
|
numDMAdescriptorsPerRow += (1<<(i - lsbMsbTransitionBit - 1));
|
||||||
}
|
}
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.printf_P(PSTR("Recalculated number of DMA descriptors per row: %d\n"), numDMAdescriptorsPerRow);
|
ESP_LOGI(TAG, "Recalculated number of DMA descriptors per row: %d", numDMAdescriptorsPerRow);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Refer to 'DMA_LL_PAYLOAD_SPLIT' code in configureDMA() below to understand why this exists.
|
// Refer to 'DMA_LL_PAYLOAD_SPLIT' code in configureDMA() below to understand why this exists.
|
||||||
// numDMAdescriptorsPerRow is also used to calculate descount which is super important in i2s_parallel_config_t SoC DMA setup.
|
// numDMAdescriptorsPerRow is also used to calculate descount which is super important in i2s_parallel_config_t SoC DMA setup.
|
||||||
if ( dma_buff.rowBits[0]->size() > DMA_MAX ) {
|
if ( dma_buff.rowBits[0]->size() > DMA_MAX )
|
||||||
|
{
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
ESP_LOGW(TAG, "rowColorDepthStruct struct is too large, split DMA payload required. Adding %d DMA descriptors\n", PIXEL_COLOUR_DEPTH_BITS-1);
|
||||||
Serial.printf_P(PSTR("rowColorDepthStruct struct is too large, split DMA payload required. Adding %d DMA descriptors\n"), PIXEL_COLOR_DEPTH_BITS-1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
numDMAdescriptorsPerRow += PIXEL_COLOR_DEPTH_BITS-1;
|
numDMAdescriptorsPerRow += PIXEL_COLOUR_DEPTH_BITS-1;
|
||||||
// Note: If numDMAdescriptorsPerRow is even just one descriptor too large, DMA linked list will not correctly loop.
|
// Note: If numDMAdescriptorsPerRow is even just one descriptor too large, DMA linked list will not correctly loop.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,31 +97,6 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
|
|
||||||
dma_bus.allocate_dma_desc_memory(desccount);
|
dma_bus.allocate_dma_desc_memory(desccount);
|
||||||
|
|
||||||
/*
|
|
||||||
//lldesc_t * dmadesc_a = (lldesc_t *)heap_caps_malloc(desccount * sizeof(lldesc_t), MALLOC_CAP_DMA);
|
|
||||||
dmadesc_a = (lldesc_t *)heap_caps_malloc(desccount * sizeof(lldesc_t), MALLOC_CAP_DMA);
|
|
||||||
assert("Can't allocate descriptor framebuffer a");
|
|
||||||
if(!dmadesc_a) {
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println(F("ERROR: Could not malloc descriptor framebuffer a."));
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_cfg.double_buff) // reserve space for second framebuffer linked list
|
|
||||||
{
|
|
||||||
//lldesc_t * dmadesc_b = (lldesc_t *)heap_caps_malloc(desccount * sizeof(lldesc_t), MALLOC_CAP_DMA);
|
|
||||||
dmadesc_b = (lldesc_t *)heap_caps_malloc(desccount * sizeof(lldesc_t), MALLOC_CAP_DMA);
|
|
||||||
assert("Could not malloc descriptor framebuffer b.");
|
|
||||||
if(!dmadesc_b) {
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println(F("ERROR: Could not malloc descriptor framebuffer b."));
|
|
||||||
#endif
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Just os we know
|
// Just os we know
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
|
@ -144,27 +113,26 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
// lldesc_t *previous_dmadesc_b = 0;
|
// lldesc_t *previous_dmadesc_b = 0;
|
||||||
int current_dmadescriptor_offset = 0;
|
int current_dmadescriptor_offset = 0;
|
||||||
|
|
||||||
// HACK: If we need to split the payload in 1/2 so that it doesn't breach DMA_MAX, lets do it by the color_depth.
|
// HACK: If we need to split the payload in 1/2 so that it doesn't breach DMA_MAX, lets do it by the colour_depth.
|
||||||
int num_dma_payload_color_depths = PIXEL_COLOR_DEPTH_BITS;
|
int num_dma_payload_colour_depths = PIXEL_COLOUR_DEPTH_BITS;
|
||||||
if ( dma_buff.rowBits[0]->size() > DMA_MAX ) {
|
if ( dma_buff.rowBits[0]->size() > DMA_MAX ) {
|
||||||
num_dma_payload_color_depths = 1;
|
num_dma_payload_colour_depths = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill DMA linked lists for both frames (as in, halves of the HUB75 panel) and if double buffering is enabled, link it up for both buffers.
|
// Fill DMA linked lists for both frames (as in, halves of the HUB75 panel) and if double buffering is enabled, link it up for both buffers.
|
||||||
for(int row = 0; row < ROWS_PER_FRAME; row++) {
|
for(int row = 0; row < ROWS_PER_FRAME; row++)
|
||||||
|
{
|
||||||
// first set of data is LSB through MSB, single pass (IF TOTAL SIZE < DMA_MAX) - all color bits are displayed once, which takes care of everything below and including LSBMSB_TRANSITION_BIT
|
// first set of data is LSB through MSB, single pass (IF TOTAL SIZE < DMA_MAX) - all colour bits are displayed once, which takes care of everything below and including LSBMSB_TRANSITION_BIT
|
||||||
// NOTE: size must be less than DMA_MAX - worst case for library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
// NOTE: size must be less than DMA_MAX - worst case for library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
||||||
//link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
//link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths));
|
||||||
// previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
// previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
||||||
|
|
||||||
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(0, 0), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), false);
|
||||||
|
|
||||||
if (m_cfg.double_buff) {
|
if (m_cfg.double_buff)
|
||||||
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(), dma_buff.rowBits[row]->size(num_dma_payload_color_depths), true);
|
{
|
||||||
//link_dma_desc(&dmadesc_b[current_dmadescriptor_offset], previous_dmadesc_b, dma_buff.rowBits[row]->getDataPtr(0, 1), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(0, 1), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), true);
|
||||||
//previous_dmadesc_b = &dmadesc_b[current_dmadescriptor_offset];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
current_dmadescriptor_offset++;
|
current_dmadescriptor_offset++;
|
||||||
|
|
||||||
|
@ -172,14 +140,12 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
if ( dma_buff.rowBits[0]->size() > DMA_MAX )
|
if ( dma_buff.rowBits[0]->size() > DMA_MAX )
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int cd = 1; cd < PIXEL_COLOR_DEPTH_BITS; cd++)
|
for (int cd = 1; cd < PIXEL_COLOUR_DEPTH_BITS; cd++)
|
||||||
{
|
{
|
||||||
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(cd, 0), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(cd, 0), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), false);
|
||||||
|
|
||||||
if (m_cfg.double_buff) {
|
if (m_cfg.double_buff) {
|
||||||
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(cd, 0), dma_buff.rowBits[row]->size(num_dma_payload_color_depths),true);
|
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(cd, 1), dma_buff.rowBits[row]->size(num_dma_payload_colour_depths), true);
|
||||||
//link_dma_desc(&dmadesc_b[current_dmadescriptor_offset], previous_dmadesc_b, dma_buff.rowBits[row]->getDataPtr(cd, 1), dma_buff.rowBits[row]->size(num_dma_payload_color_depths));
|
|
||||||
//previous_dmadesc_b = &dmadesc_b[current_dmadescriptor_offset];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_dmadescriptor_offset++;
|
current_dmadescriptor_offset++;
|
||||||
|
@ -188,74 +154,28 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
} // row depth struct
|
} // row depth struct
|
||||||
|
|
||||||
|
|
||||||
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_DEPTH_BITS; i++)
|
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOUR_DEPTH_BITS; i++)
|
||||||
{
|
{
|
||||||
// binary time division setup: we need 2 of bit (LSBMSB_TRANSITION_BIT + 1) four of (LSBMSB_TRANSITION_BIT + 2), etc
|
// binary time division setup: we need 2 of bit (LSBMSB_TRANSITION_BIT + 1) four of (LSBMSB_TRANSITION_BIT + 2), etc
|
||||||
// because we sweep through to MSB each time, it divides the number of times we have to sweep in half (saving linked list RAM)
|
// because we sweep through to MSB each time, it divides the number of times we have to sweep in half (saving linked list RAM)
|
||||||
// we need 2^(i - LSBMSB_TRANSITION_BIT - 1) == 1 << (i - LSBMSB_TRANSITION_BIT - 1) passes from i to MSB
|
// we need 2^(i - LSBMSB_TRANSITION_BIT - 1) == 1 << (i - LSBMSB_TRANSITION_BIT - 1) passes from i to MSB
|
||||||
|
|
||||||
|
|
||||||
for(int k=0; k < (1<<(i - lsbMsbTransitionBit - 1)); k++)
|
for(int k=0; k < (1<<(i - lsbMsbTransitionBit - 1)); k++)
|
||||||
{
|
{
|
||||||
// link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, dma_buff.rowBits[row]->getDataPtr(i, 0), dma_buff.rowBits[row]->size(PIXEL_COLOR_DEPTH_BITS - i) );
|
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 0), dma_buff.rowBits[row]->size(PIXEL_COLOUR_DEPTH_BITS - i), false);
|
||||||
// previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
|
||||||
|
|
||||||
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 0), dma_buff.rowBits[row]->size(PIXEL_COLOR_DEPTH_BITS - i) );
|
|
||||||
|
|
||||||
if (m_cfg.double_buff) {
|
if (m_cfg.double_buff) {
|
||||||
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 0), dma_buff.rowBits[row]->size(PIXEL_COLOR_DEPTH_BITS - i), true );
|
dma_bus.create_dma_desc_link(dma_buff.rowBits[row]->getDataPtr(i, 1), dma_buff.rowBits[row]->size(PIXEL_COLOUR_DEPTH_BITS - i), true );
|
||||||
//link_dma_desc(&dmadesc_b[current_dmadescriptor_offset], previous_dmadesc_b, dma_buff.rowBits[row]->getDataPtr(i, 1), dma_buff.rowBits[row]->size(PIXEL_COLOR_DEPTH_BITS - i) );
|
|
||||||
//previous_dmadesc_b = &dmadesc_b[current_dmadescriptor_offset];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_dmadescriptor_offset++;
|
current_dmadescriptor_offset++;
|
||||||
|
|
||||||
} // end color depth ^ 2 linked list
|
} // end colour depth ^ 2 linked list
|
||||||
} // end color depth loop
|
} // end colour depth loop
|
||||||
|
|
||||||
} // end frame rows
|
} // end frame rows
|
||||||
/*
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.printf_P(PSTR("configureDMA(): Configured LL structure. %d DMA Linked List descriptors populated.\r\n"), current_dmadescriptor_offset);
|
|
||||||
|
|
||||||
if ( desccount != current_dmadescriptor_offset)
|
ESP_LOGI(TAG, "%d DMA descriptors linked to buffer data.");
|
||||||
{
|
|
||||||
Serial.printf_P(PSTR("configureDMA(): ERROR! Expected descriptor count of %d != actual DMA descriptors of %d!\r\n"), desccount, current_dmadescriptor_offset);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//End markers for DMA LL
|
|
||||||
dmadesc_a[desccount-1].eof = 1;
|
|
||||||
dmadesc_a[desccount-1].qe.stqe_next=(lldesc_t*)&dmadesc_a[0];
|
|
||||||
|
|
||||||
if (m_cfg.double_buff) {
|
|
||||||
dmadesc_b[desccount-1].eof = 1;
|
|
||||||
dmadesc_b[desccount-1].qe.stqe_next=(lldesc_t*)&dmadesc_b[0];
|
|
||||||
} else {
|
|
||||||
dmadesc_b = dmadesc_a; // link to same 'a' buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println(F("Performing I2S setup:"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
i2s_parallel_config_t dma_cfg = {
|
|
||||||
.gpio_bus={_cfg.gpio.r1, _cfg.gpio.g1, _cfg.gpio.b1, _cfg.gpio.r2, _cfg.gpio.g2, _cfg.gpio.b2, _cfg.gpio.lat, _cfg.gpio.oe, _cfg.gpio.a, _cfg.gpio.b, _cfg.gpio.c, _cfg.gpio.d, _cfg.gpio.e, -1, -1, -1},
|
|
||||||
.gpio_clk=_cfg.gpio.clk,
|
|
||||||
.sample_rate=_cfg.i2sspeed,
|
|
||||||
.sample_width=ESP32_I2S_DMA_MODE,
|
|
||||||
.desccount_a=desccount,
|
|
||||||
.lldesc_a=dmadesc_a,
|
|
||||||
.desccount_b=desccount,
|
|
||||||
.lldesc_b=dmadesc_b,
|
|
||||||
.clkphase=_cfg.clkphase,
|
|
||||||
.int_ena_out_eof=_cfg.double_buff
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup I2S
|
|
||||||
//i2s_parallel_driver_install(ESP32_I2S_DEVICE, &dma_cfg);
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Setup DMA and Output to GPIO
|
// Setup DMA and Output to GPIO
|
||||||
|
@ -315,12 +235,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
*/
|
*/
|
||||||
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(int16_t x_coord, int16_t y_coord, uint8_t red, uint8_t green, uint8_t blue)
|
||||||
{
|
{
|
||||||
if ( !initialized ) {
|
if ( !initialized ) return;
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println(F("Cannot updateMatrixDMABuffer as setup failed!"));
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 1) Check that the co-ordinates are within range, or it'll break everything big time.
|
/* 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)
|
* Valid co-ordinates are from 0 to (MATRIX_XXXX-1)
|
||||||
|
@ -331,7 +246,7 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16
|
||||||
|
|
||||||
/* LED Brightness Compensation. Because if we do a basic "red & mask" for example,
|
/* LED Brightness Compensation. Because if we do a basic "red & mask" for example,
|
||||||
* we'll NEVER send the dimmest possible colour, due to binary skew.
|
* we'll NEVER send the dimmest possible colour, due to binary skew.
|
||||||
* i.e. It's almost impossible for color_depth_idx of 0 to be sent out to the MATRIX unless the 'value' of a color is exactly '1'
|
* i.e. It's almost impossible for colour_depth_idx of 0 to be sent out to the MATRIX unless the 'value' of a color is exactly '1'
|
||||||
* https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/
|
* https://ledshield.wordpress.com/2012/11/13/led-brightness-to-your-eye-gamma-correction-no/
|
||||||
*/
|
*/
|
||||||
#ifndef NO_CIE1931
|
#ifndef NO_CIE1931
|
||||||
|
@ -360,23 +275,23 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
uint16_t _colorbitclear = BITMASK_RGB1_CLEAR, _colorbitoffset = 0;
|
uint16_t _colourbitclear = BITMASK_RGB1_CLEAR, _colourbitoffset = 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
|
||||||
_colorbitoffset = BITS_RGB2_OFFSET;
|
_colourbitoffset = BITS_RGB2_OFFSET;
|
||||||
_colorbitclear = BITMASK_RGB2_CLEAR;
|
_colourbitclear = BITMASK_RGB2_CLEAR;
|
||||||
y_coord -= ROWS_PER_FRAME;
|
y_coord -= ROWS_PER_FRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterating through colour depth bits, which we assume are 8 bits per RGB subpixel (24bpp)
|
// Iterating through colour depth bits, which we assume are 8 bits per RGB subpixel (24bpp)
|
||||||
uint8_t color_depth_idx = PIXEL_COLOR_DEPTH_BITS;
|
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
||||||
do {
|
do {
|
||||||
--color_depth_idx;
|
--colour_depth_idx;
|
||||||
// uint8_t mask = (1 << (color_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST)); // expect 24 bit color (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
#if PIXEL_COLOR_DEPTH_BITS < 8
|
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (color_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
#else
|
#else
|
||||||
uint8_t mask = (1 << (color_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#endif
|
#endif
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
|
|
||||||
|
@ -387,20 +302,20 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16
|
||||||
RGB_output_bits |= (bool)(green & mask); // -BG
|
RGB_output_bits |= (bool)(green & mask); // -BG
|
||||||
RGB_output_bits <<= 1;
|
RGB_output_bits <<= 1;
|
||||||
RGB_output_bits |= (bool)(red & mask); // BGR
|
RGB_output_bits |= (bool)(red & mask); // BGR
|
||||||
RGB_output_bits <<= _colorbitoffset; // shift color bits to the required position
|
RGB_output_bits <<= _colourbitoffset; // shift colour bits to the required position
|
||||||
|
|
||||||
|
|
||||||
// Get the contents at this address,
|
// Get the contents at this address,
|
||||||
// it would represent a vector pointing to the full row of pixels for the specified color depth bit at Y coordinate
|
// it would represent a vector pointing to the full row of pixels for the specified color depth bit at Y coordinate
|
||||||
//ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(y_coord, color_depth_idx, back_buffer_id);
|
//ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(y_coord, colour_depth_idx, back_buffer_id);
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[y_coord]->getDataPtr(color_depth_idx, back_buffer_id);
|
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[y_coord]->getDataPtr(colour_depth_idx, back_buffer_id);
|
||||||
|
|
||||||
|
|
||||||
// We need to update the correct uint16_t word in the rowBitStruct array pointing to a specific pixel at X - coordinate
|
// We need to update the correct uint16_t word in the rowBitStruct array pointing to a specific pixel at X - coordinate
|
||||||
p[x_coord] &= _colorbitclear; // reset RGB bits
|
p[x_coord] &= _colourbitclear; // reset RGB bits
|
||||||
p[x_coord] |= RGB_output_bits; // set new RGB bits
|
p[x_coord] |= RGB_output_bits; // set new RGB bits
|
||||||
|
|
||||||
} while(color_depth_idx); // end of color depth loop (8)
|
} while(colour_depth_idx); // end of colour depth loop (8)
|
||||||
} // updateMatrixDMABuffer (specific co-ords change)
|
} // updateMatrixDMABuffer (specific co-ords change)
|
||||||
|
|
||||||
|
|
||||||
|
@ -416,15 +331,15 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
|
||||||
blue = lumConvTab[blue];
|
blue = lumConvTab[blue];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(uint8_t color_depth_idx=0; color_depth_idx<PIXEL_COLOR_DEPTH_BITS; color_depth_idx++) // color depth - 8 iterations
|
for(uint8_t colour_depth_idx=0; colour_depth_idx<PIXEL_COLOUR_DEPTH_BITS; colour_depth_idx++) // color depth - 8 iterations
|
||||||
{
|
{
|
||||||
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
// uint8_t mask = (1 << color_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST); // 24 bit color
|
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST); // 24 bit colour
|
||||||
#if PIXEL_COLOR_DEPTH_BITS < 8
|
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (color_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#else
|
#else
|
||||||
uint8_t mask = (1 << (color_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Per the .h file, the order of the output RGB bits is:
|
/* Per the .h file, the order of the output RGB bits is:
|
||||||
|
@ -446,15 +361,15 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
|
||||||
--matrix_frame_parallel_row;
|
--matrix_frame_parallel_row;
|
||||||
|
|
||||||
// The destination for the pixel row bitstream
|
// The destination for the pixel row bitstream
|
||||||
//ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(matrix_frame_parallel_row, color_depth_idx, back_buffer_id);
|
//ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(matrix_frame_parallel_row, colour_depth_idx, back_buffer_id);
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[matrix_frame_parallel_row]->getDataPtr(color_depth_idx, back_buffer_id);
|
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[matrix_frame_parallel_row]->getDataPtr(colour_depth_idx, back_buffer_id);
|
||||||
|
|
||||||
// iterate pixels in a row
|
// iterate pixels in a row
|
||||||
int x_coord=dma_buff.rowBits[matrix_frame_parallel_row]->width;
|
int x_coord=dma_buff.rowBits[matrix_frame_parallel_row]->width;
|
||||||
do {
|
do {
|
||||||
--x_coord;
|
--x_coord;
|
||||||
p[x_coord] &= BITMASK_RGB12_CLEAR; // reset color bits
|
p[x_coord] &= BITMASK_RGB12_CLEAR; // reset colour bits
|
||||||
p[x_coord] |= RGB_output_bits; // set new color bits
|
p[x_coord] |= RGB_output_bits; // set new colour bits
|
||||||
} while(x_coord);
|
} while(x_coord);
|
||||||
|
|
||||||
} while(matrix_frame_parallel_row); // end row iteration
|
} while(matrix_frame_parallel_row); // end row iteration
|
||||||
|
@ -462,9 +377,9 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
|
||||||
} // updateMatrixDMABuffer (full frame paint)
|
} // updateMatrixDMABuffer (full frame paint)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - clears and reinitializes color/control data in DMA buffs
|
* @brief - clears and reinitializes colour/control data in DMA buffs
|
||||||
* When allocated, DMA buffs might be dirty, so we need to blank it and initialize ABCDE,LAT,OE control bits.
|
* When allocated, DMA buffs might be dirty, so we need to blank it and initialize ABCDE,LAT,OE control bits.
|
||||||
* Those control bits are constants during the entire DMA sweep and never changed when updating just pixel color data
|
* Those control bits are constants during the entire DMA sweep and never changed when updating just pixel colour data
|
||||||
* so we could set it once on DMA buffs initialization and forget.
|
* so we could set it once on DMA buffs initialization and forget.
|
||||||
* This effectively clears buffers to blank BLACK and makes it ready to display output.
|
* This effectively clears buffers to blank BLACK and makes it ready to display output.
|
||||||
* (Brightness control via OE bit manipulation is another case)
|
* (Brightness control via OE bit manipulation is another case)
|
||||||
|
@ -483,11 +398,11 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE abcde = (ESP32_I2S_DMA_STORAGE_TYPE)row_idx;
|
ESP32_I2S_DMA_STORAGE_TYPE abcde = (ESP32_I2S_DMA_STORAGE_TYPE)row_idx;
|
||||||
abcde <<= BITS_ADDR_OFFSET; // shift row y-coord to match ABCDE bits in vector from 8 to 12
|
abcde <<= BITS_ADDR_OFFSET; // shift row y-coord to match ABCDE bits in vector from 8 to 12
|
||||||
|
|
||||||
// get last pixel index in a row of all colordepths
|
// get last pixel index in a row of all colourdepths
|
||||||
int x_pixel = dma_buff.rowBits[row_idx]->width * dma_buff.rowBits[row_idx]->color_depth;
|
int x_pixel = dma_buff.rowBits[row_idx]->width * dma_buff.rowBits[row_idx]->colour_depth;
|
||||||
//Serial.printf(" from pixel %d, ", x_pixel);
|
//Serial.printf(" from pixel %d, ", x_pixel);
|
||||||
|
|
||||||
// fill all x_pixels except color_index[0] (LSB) ones, this also clears all color data to 0's black
|
// fill all x_pixels except colour_index[0] (LSB) ones, this also clears all colour data to 0's black
|
||||||
do {
|
do {
|
||||||
--x_pixel;
|
--x_pixel;
|
||||||
|
|
||||||
|
@ -501,7 +416,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
||||||
|
|
||||||
} while(x_pixel!=dma_buff.rowBits[row_idx]->width);
|
} while(x_pixel!=dma_buff.rowBits[row_idx]->width);
|
||||||
|
|
||||||
// color_index[0] (LSB) x_pixels must be "marked" with a previous's row address, 'cause it is used to display
|
// colour_index[0] (LSB) x_pixels must be "marked" with a previous's row address, 'cause it is used to display
|
||||||
// previous row while we pump in LSB's for a new row
|
// previous row while we pump in LSB's for a new row
|
||||||
abcde = ((ESP32_I2S_DMA_STORAGE_TYPE)row_idx-1) << BITS_ADDR_OFFSET;
|
abcde = ((ESP32_I2S_DMA_STORAGE_TYPE)row_idx-1) << BITS_ADDR_OFFSET;
|
||||||
do {
|
do {
|
||||||
|
@ -536,12 +451,12 @@ 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...
|
// 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 colouridx = dma_buff.rowBits[row_idx]->colour_depth;
|
||||||
do {
|
do {
|
||||||
--coloridx;
|
--colouridx;
|
||||||
|
|
||||||
// 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(colouridx, _buff_id);
|
||||||
|
|
||||||
#if defined(ESP32_THE_ORIG)
|
#if defined(ESP32_THE_ORIG)
|
||||||
// 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
|
||||||
|
@ -575,7 +490,7 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
|
||||||
|
|
||||||
} while (_blank);
|
} while (_blank);
|
||||||
|
|
||||||
} while(coloridx);
|
} while(colouridx);
|
||||||
|
|
||||||
} while(row_idx);
|
} while(row_idx);
|
||||||
}
|
}
|
||||||
|
@ -601,12 +516,12 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
||||||
--row_idx;
|
--row_idx;
|
||||||
|
|
||||||
// let's set OE control bits for specific pixels in each color_index subrows
|
// let's set OE control bits for specific pixels in each color_index subrows
|
||||||
uint8_t coloridx = dma_buff.rowBits[row_idx]->color_depth;
|
uint8_t colouridx = dma_buff.rowBits[row_idx]->colour_depth;
|
||||||
do {
|
do {
|
||||||
--coloridx;
|
--colouridx;
|
||||||
|
|
||||||
// switch pointer to a row for a specific color index
|
// switch pointer to a row for a specific color index
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE* row = dma_buff.rowBits[row_idx]->getDataPtr(coloridx, _buff_id);
|
ESP32_I2S_DMA_STORAGE_TYPE* row = dma_buff.rowBits[row_idx]->getDataPtr(colouridx, _buff_id);
|
||||||
|
|
||||||
int x_coord = dma_buff.rowBits[row_idx]->width;
|
int x_coord = dma_buff.rowBits[row_idx]->width;
|
||||||
do {
|
do {
|
||||||
|
@ -616,14 +531,14 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
||||||
row[x_coord] &= BITMASK_OE_CLEAR;
|
row[x_coord] &= BITMASK_OE_CLEAR;
|
||||||
|
|
||||||
// Brightness control via OE toggle - disable matrix output at specified x_coord
|
// Brightness control via OE toggle - disable matrix output at specified x_coord
|
||||||
if((coloridx > lsbMsbTransitionBit || !coloridx) && ((x_coord) >= brt)){
|
if((colouridx > lsbMsbTransitionBit || !colouridx) && ((x_coord) >= brt)){
|
||||||
row[x_coord] |= BIT_OE; // Disable output after this point.
|
row[x_coord] |= BIT_OE; // Disable output after this point.
|
||||||
continue;
|
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
|
// special case for the bits *after* LSB through (lsbMsbTransitionBit) - OE is output after data is shifted, so need to set OE to fractional brightness
|
||||||
if(coloridx && coloridx <= lsbMsbTransitionBit) {
|
if(colouridx && colouridx <= lsbMsbTransitionBit) {
|
||||||
// divide brightness in half for each bit below lsbMsbTransitionBit
|
// divide brightness in half for each bit below lsbMsbTransitionBit
|
||||||
int lsbBrightness = brt >> (lsbMsbTransitionBit - coloridx + 1);
|
int lsbBrightness = brt >> (lsbMsbTransitionBit - colouridx + 1);
|
||||||
if((x_coord) >= lsbBrightness) {
|
if((x_coord) >= lsbBrightness) {
|
||||||
row[x_coord] |= BIT_OE; // Disable output after this point.
|
row[x_coord] |= BIT_OE; // Disable output after this point.
|
||||||
continue;
|
continue;
|
||||||
|
@ -653,7 +568,7 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
|
||||||
//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);
|
||||||
|
|
||||||
} while(coloridx);
|
} while(colouridx);
|
||||||
} while(row_idx);
|
} while(row_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,26 +642,26 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
blue = lumConvTab[blue];
|
blue = lumConvTab[blue];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t _colorbitclear = BITMASK_RGB1_CLEAR, _colorbitoffset = 0;
|
uint16_t _colourbitclear = BITMASK_RGB1_CLEAR, _colourbitoffset = 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
|
||||||
_colorbitoffset = BITS_RGB2_OFFSET;
|
_colourbitoffset = BITS_RGB2_OFFSET;
|
||||||
_colorbitclear = BITMASK_RGB2_CLEAR;
|
_colourbitclear = BITMASK_RGB2_CLEAR;
|
||||||
y_coord -= ROWS_PER_FRAME;
|
y_coord -= ROWS_PER_FRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterating through color depth bits (8 iterations)
|
// Iterating through color depth bits (8 iterations)
|
||||||
uint8_t color_depth_idx = PIXEL_COLOR_DEPTH_BITS;
|
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
||||||
do {
|
do {
|
||||||
--color_depth_idx;
|
--colour_depth_idx;
|
||||||
|
|
||||||
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
// uint8_t mask = (1 << color_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
||||||
#if PIXEL_COLOR_DEPTH_BITS < 8
|
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (color_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#else
|
#else
|
||||||
uint8_t mask = (1 << (color_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Per the .h file, the order of the output RGB bits is:
|
/* Per the .h file, the order of the output RGB bits is:
|
||||||
|
@ -756,13 +671,13 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
RGB_output_bits |= (bool)(green & mask); // -BG
|
RGB_output_bits |= (bool)(green & mask); // -BG
|
||||||
RGB_output_bits <<= 1;
|
RGB_output_bits <<= 1;
|
||||||
RGB_output_bits |= (bool)(red & mask); // BGR
|
RGB_output_bits |= (bool)(red & mask); // BGR
|
||||||
RGB_output_bits <<= _colorbitoffset; // shift color bits to the required position
|
RGB_output_bits <<= _colourbitoffset; // shift color bits to the required position
|
||||||
|
|
||||||
// Get the contents at this address,
|
// Get the contents at this address,
|
||||||
// it would represent a vector pointing to the full row of pixels for the specified color depth bit at Y coordinate
|
// it would represent a vector pointing to the full row of pixels for the specified color depth bit at Y coordinate
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[y_coord]->getDataPtr(color_depth_idx, back_buffer_id);
|
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[y_coord]->getDataPtr(colour_depth_idx, back_buffer_id);
|
||||||
// inlined version works slower here, dunno why :(
|
// inlined version works slower here, dunno why :(
|
||||||
// ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(y_coord, color_depth_idx, back_buffer_id);
|
// ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(y_coord, colour_depth_idx, back_buffer_id);
|
||||||
|
|
||||||
int16_t _l = l;
|
int16_t _l = l;
|
||||||
do { // iterate pixels in a row
|
do { // iterate pixels in a row
|
||||||
|
@ -776,10 +691,10 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
uint16_t &v = p[_x];
|
uint16_t &v = p[_x];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v &= _colorbitclear; // reset color bits
|
v &= _colourbitclear; // reset color bits
|
||||||
v |= RGB_output_bits; // set new color bits
|
v |= RGB_output_bits; // set new color bits
|
||||||
} while(_l); // iterate pixels in a row
|
} while(_l); // iterate pixels in a row
|
||||||
} while(color_depth_idx); // end of color depth loop (8)
|
} while(colour_depth_idx); // end of color depth loop (8)
|
||||||
} // hlineDMA()
|
} // hlineDMA()
|
||||||
|
|
||||||
|
|
||||||
|
@ -814,16 +729,16 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
x_coord & 1U ? --x_coord : ++x_coord;
|
x_coord & 1U ? --x_coord : ++x_coord;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t color_depth_idx = PIXEL_COLOR_DEPTH_BITS;
|
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
||||||
do { // Iterating through color depth bits (8 iterations)
|
do { // Iterating through color depth bits (8 iterations)
|
||||||
--color_depth_idx;
|
--colour_depth_idx;
|
||||||
|
|
||||||
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
||||||
// uint8_t mask = (1 << color_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
||||||
#if PIXEL_COLOR_DEPTH_BITS < 8
|
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (color_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#else
|
#else
|
||||||
uint8_t mask = (1 << (color_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#endif
|
#endif
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
|
|
||||||
|
@ -836,25 +751,25 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
RGB_output_bits |= (bool)(red & mask); // BGR
|
RGB_output_bits |= (bool)(red & mask); // BGR
|
||||||
|
|
||||||
int16_t _l = 0, _y = y_coord;
|
int16_t _l = 0, _y = y_coord;
|
||||||
uint16_t _colorbitclear = BITMASK_RGB1_CLEAR;
|
uint16_t _colourbitclear = BITMASK_RGB1_CLEAR;
|
||||||
do { // iterate pixels in a column
|
do { // iterate pixels in a column
|
||||||
|
|
||||||
if (_y >= ROWS_PER_FRAME){ // if y-coord overlapped bottom-half panel
|
if (_y >= ROWS_PER_FRAME){ // if y-coord overlapped bottom-half panel
|
||||||
_y -= ROWS_PER_FRAME;
|
_y -= ROWS_PER_FRAME;
|
||||||
_colorbitclear = BITMASK_RGB2_CLEAR;
|
_colourbitclear = BITMASK_RGB2_CLEAR;
|
||||||
RGB_output_bits <<= BITS_RGB2_OFFSET;
|
RGB_output_bits <<= BITS_RGB2_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the contents at this address,
|
// Get the contents at this address,
|
||||||
// it would represent a vector pointing to the full row of pixels for the specified color depth bit at Y coordinate
|
// it would represent a vector pointing to the full row of pixels for the specified color depth bit at Y coordinate
|
||||||
//ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(_y, color_depth_idx, back_buffer_id);
|
//ESP32_I2S_DMA_STORAGE_TYPE *p = getRowDataPtr(_y, colour_depth_idx, back_buffer_id);
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[_y]->getDataPtr(color_depth_idx, back_buffer_id);
|
ESP32_I2S_DMA_STORAGE_TYPE *p = dma_buff.rowBits[_y]->getDataPtr(colour_depth_idx, back_buffer_id);
|
||||||
|
|
||||||
p[x_coord] &= _colorbitclear; // reset RGB bits
|
p[x_coord] &= _colourbitclear; // reset RGB bits
|
||||||
p[x_coord] |= RGB_output_bits; // set new RGB bits
|
p[x_coord] |= RGB_output_bits; // set new RGB bits
|
||||||
++_y;
|
++_y;
|
||||||
} while(++_l!=l); // iterate pixels in a col
|
} while(++_l!=l); // iterate pixels in a col
|
||||||
} while(color_depth_idx); // end of color depth loop (8)
|
} while(colour_depth_idx); // end of color depth loop (8)
|
||||||
} // vlineDMA()
|
} // vlineDMA()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,15 +71,14 @@
|
||||||
|
|
||||||
// 8bit per RGB color = 24 bit/per pixel,
|
// 8bit per RGB color = 24 bit/per pixel,
|
||||||
// might be reduced to save DMA RAM
|
// might be reduced to save DMA RAM
|
||||||
#ifndef PIXEL_COLOR_DEPTH_BITS
|
#ifndef PIXEL_COLOUR_DEPTH_BITS
|
||||||
#define PIXEL_COLOR_DEPTH_BITS 8
|
#define PIXEL_COLOUR_DEPTH_BITS 8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COLOR_CHANNELS_PER_PIXEL 3
|
#define COLOUR_CHANNELS_PER_PIXEL 3
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
/* 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 16 // From esp32_i2s_parallel_v2.h = 16 bits in parallel
|
|
||||||
#define ESP32_I2S_DMA_STORAGE_TYPE uint16_t // DMA output of one uint16_t at a time.
|
#define ESP32_I2S_DMA_STORAGE_TYPE uint16_t // DMA output of one uint16_t at a time.
|
||||||
#define CLKS_DURING_LATCH 0 // Not (yet) used.
|
#define CLKS_DURING_LATCH 0 // Not (yet) used.
|
||||||
|
|
||||||
|
@ -116,24 +115,25 @@
|
||||||
|
|
||||||
// How many clock cycles to blank OE before/after LAT signal change, default is 1 clock
|
// How many clock cycles to blank OE before/after LAT signal change, default is 1 clock
|
||||||
#define DEFAULT_LAT_BLANKING 1
|
#define DEFAULT_LAT_BLANKING 1
|
||||||
|
|
||||||
// Max clock cycles to blank OE before/after LAT signal change
|
// Max clock cycles to blank OE before/after LAT signal change
|
||||||
#define MAX_LAT_BLANKING 4
|
#define MAX_LAT_BLANKING 4
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
// Check compile-time only options
|
// Check compile-time only options
|
||||||
#if PIXEL_COLOR_DEPTH_BITS > 8
|
#if PIXEL_COLOUR_DEPTH_BITS > 8
|
||||||
#error "Pixel color depth bits cannot be greater than 8."
|
#error "Pixel color depth bits cannot be greater than 8."
|
||||||
#elif PIXEL_COLOR_DEPTH_BITS < 2
|
#elif PIXEL_COLOUR_DEPTH_BITS < 2
|
||||||
#error "Pixel color depth bits cannot be less than 2."
|
#error "Pixel color depth bits cannot be less than 2."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This library is designed to take an 8 bit / 1 byte value (0-255) for each R G B colour sub-pixel.
|
/* This library is designed to take an 8 bit / 1 byte value (0-255) for each R G B colour sub-pixel.
|
||||||
* The PIXEL_COLOR_DEPTH_BITS should always be '8' as a result.
|
* The PIXEL_COLOUR_DEPTH_BITS should always be '8' as a result.
|
||||||
* However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking
|
* However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking
|
||||||
* is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up.
|
* is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up.
|
||||||
*/
|
*/
|
||||||
#if PIXEL_COLOR_DEPTH_BITS != 8
|
#if PIXEL_COLOUR_DEPTH_BITS != 8
|
||||||
static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOR_DEPTH_BITS;
|
static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOUR_DEPTH_BITS;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
|
@ -143,7 +143,7 @@ static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOR_DEPTH_BITS;
|
||||||
*/
|
*/
|
||||||
struct rowBitStruct {
|
struct rowBitStruct {
|
||||||
const size_t width;
|
const size_t width;
|
||||||
const uint8_t color_depth;
|
const uint8_t colour_depth;
|
||||||
const bool double_buff;
|
const bool double_buff;
|
||||||
ESP32_I2S_DMA_STORAGE_TYPE *data;
|
ESP32_I2S_DMA_STORAGE_TYPE *data;
|
||||||
|
|
||||||
|
@ -155,17 +155,17 @@ struct rowBitStruct {
|
||||||
* default - returns full data vector size for a SINGLE buff
|
* default - returns full data vector size for a SINGLE buff
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
size_t size(uint8_t _dpth=0 ) { if (!_dpth) _dpth = color_depth; return width * _dpth * sizeof(ESP32_I2S_DMA_STORAGE_TYPE); };
|
size_t size(uint8_t _dpth=0 ) { if (!_dpth) _dpth = colour_depth; return width * _dpth * sizeof(ESP32_I2S_DMA_STORAGE_TYPE); };
|
||||||
|
|
||||||
/** @brief - returns pointer to the row's data vector beginning at pixel[0] for _dpth color bit
|
/** @brief - returns pointer to the row's data vector beginning at pixel[0] for _dpth color bit
|
||||||
* default - returns pointer to the data vector's head
|
* default - returns pointer to the data vector's head
|
||||||
* NOTE: this call might be very slow in loops. Due to poor instruction caching in esp32 it might be required a reread from flash
|
* NOTE: this call might be very slow in loops. Due to poor instruction caching in esp32 it might be required a reread from flash
|
||||||
* every loop cycle, better use inlined #define instead in such cases
|
* every loop cycle, better use inlined #define instead in such cases
|
||||||
*/
|
*/
|
||||||
inline ESP32_I2S_DMA_STORAGE_TYPE* getDataPtr(const uint8_t _dpth=0, const bool buff_id=0) { return &(data[_dpth*width + buff_id*(width*color_depth)]); };
|
inline ESP32_I2S_DMA_STORAGE_TYPE* getDataPtr(const uint8_t _dpth=0, const bool buff_id=0) { return &(data[_dpth*width + buff_id*(width*colour_depth)]); };
|
||||||
|
|
||||||
// constructor - allocates DMA-capable memory to hold the struct data
|
// constructor - allocates DMA-capable memory to hold the struct data
|
||||||
rowBitStruct(const size_t _width, const uint8_t _depth, const bool _dbuff) : width(_width), color_depth(_depth), double_buff(_dbuff) {
|
rowBitStruct(const size_t _width, const uint8_t _depth, const bool _dbuff) : width(_width), colour_depth(_depth), double_buff(_dbuff) {
|
||||||
|
|
||||||
#if defined(SPIRAM_FRAMEBUFFER)
|
#if defined(SPIRAM_FRAMEBUFFER)
|
||||||
#pragma message "Enabling PSRAM / SPIRAM for frame buffer."
|
#pragma message "Enabling PSRAM / SPIRAM for frame buffer."
|
||||||
|
@ -335,23 +335,22 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
if (initialized) return true; // we don't do this twice or more!
|
if (initialized) return true; // we don't do this twice or more!
|
||||||
|
|
||||||
// Change 'if' to '1' to enable, 0 to not include this Serial output in compiled program
|
|
||||||
#if SERIAL_DEBUG
|
ESP_LOGI("begin()", "Using GPIO %d for R1_PIN", m_cfg.gpio.r1);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the R1_PIN\n"), m_cfg.gpio.r1);
|
ESP_LOGI("begin()", "Using GPIO %d for G1_PIN", m_cfg.gpio.g1);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the G1_PIN\n"), m_cfg.gpio.g1);
|
ESP_LOGI("begin()", "Using GPIO %d for B1_PIN", m_cfg.gpio.b1);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the B1_PIN\n"), m_cfg.gpio.b1);
|
ESP_LOGI("begin()", "Using GPIO %d for R2_PIN", m_cfg.gpio.r2);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the R2_PIN\n"), m_cfg.gpio.r2);
|
ESP_LOGI("begin()", "Using GPIO %d for G2_PIN", m_cfg.gpio.g2);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the G2_PIN\n"), m_cfg.gpio.g2);
|
ESP_LOGI("begin()", "Using GPIO %d for B2_PIN", m_cfg.gpio.b2);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the B2_PIN\n"), m_cfg.gpio.b2);
|
ESP_LOGI("begin()", "Using GPIO %d for A_PIN", m_cfg.gpio.a);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the A_PIN\n"), m_cfg.gpio.a);
|
ESP_LOGI("begin()", "Using GPIO %d for B_PIN", m_cfg.gpio.b);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the B_PIN\n"), m_cfg.gpio.b);
|
ESP_LOGI("begin()", "Using GPIO %d for C_PIN", m_cfg.gpio.c);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the C_PIN\n"), m_cfg.gpio.c);
|
ESP_LOGI("begin()", "Using GPIO %d for D_PIN", m_cfg.gpio.d);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the D_PIN\n"), m_cfg.gpio.d);
|
ESP_LOGI("begin()", "Using GPIO %d for E_PIN", m_cfg.gpio.e);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the E_PIN\n"), m_cfg.gpio.e);
|
ESP_LOGI("begin()", "Using GPIO %d for LAT_PIN", m_cfg.gpio.lat);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the LAT_PIN\n"), m_cfg.gpio.lat);
|
ESP_LOGI("begin()", "Using GPIO %d for OE_PIN", m_cfg.gpio.oe);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the OE_PIN\n"), m_cfg.gpio.oe);
|
ESP_LOGI("begin()", "Using GPIO %d for CLK_PIN", m_cfg.gpio.clk);
|
||||||
Serial.printf_P(PSTR("Using pin %d for the CLK_PIN\n"), m_cfg.gpio.clk);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// initialize some specific panel drivers
|
// initialize some specific panel drivers
|
||||||
if (m_cfg.driver)
|
if (m_cfg.driver)
|
||||||
|
@ -372,10 +371,9 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
//showDMABuffer(); // show backbuf_id of 0
|
//showDMABuffer(); // show backbuf_id of 0
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
if (!initialized) {
|
||||||
if (!initialized)
|
ESP_LOGE("being()", "MatrixPanel_I2S_DMA::begin() failed!");
|
||||||
Serial.println(F("MatrixPanel_I2S_DMA::begin() failed."));
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return initialized;
|
return initialized;
|
||||||
|
|
||||||
|
@ -474,11 +472,16 @@ class MatrixPanel_I2S_DMA {
|
||||||
{
|
{
|
||||||
if ( !m_cfg.double_buff) return;
|
if ( !m_cfg.double_buff) return;
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
//ESP_LOGI("flipDMABuffer()", "Set back buffer to: %d", back_buffer_id);
|
||||||
Serial.printf_P(PSTR("Set back buffer to: %d\n"), back_buffer_id);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
dma_bus.flip_dma_output_buffer();
|
if (back_buffer_id == 0)
|
||||||
|
{
|
||||||
|
dma_bus.set_dma_output_buffer( false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dma_bus.set_dma_output_buffer( true );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
i2s_parallel_set_previous_buffer_not_free();
|
i2s_parallel_set_previous_buffer_not_free();
|
||||||
|
@ -497,9 +500,6 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
back_buffer_id ^= 1;
|
back_buffer_id ^= 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setPanelBrightness(int b)
|
inline void setPanelBrightness(int b)
|
||||||
|
|
|
@ -35,10 +35,10 @@ void MatrixPanel_I2S_DMA::shiftDriver(const HUB75_I2S_CFG& _cfg){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MatrixPanel_I2S_DMA::fm6124init(const HUB75_I2S_CFG& _cfg){
|
void MatrixPanel_I2S_DMA::fm6124init(const HUB75_I2S_CFG& _cfg) {
|
||||||
#if SERIAL_DEBUG
|
|
||||||
Serial.println( F("MatrixPanel_I2S_DMA - initializing FM6124 driver..."));
|
ESP_LOGI("LEDdrivers", "MatrixPanel_I2S_DMA - initializing FM6124 driver...");
|
||||||
#endif
|
|
||||||
bool REG1[16] = {0,0,0,0,0, 1,1,1,1,1,1, 0,0,0,0,0}; // this sets global matrix brightness power
|
bool REG1[16] = {0,0,0,0,0, 1,1,1,1,1,1, 0,0,0,0,0}; // this sets global matrix brightness power
|
||||||
bool REG2[16] = {0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,0,0}; // a single bit enables the matrix output
|
bool REG2[16] = {0,0,0,0,0, 0,0,0,0,1,0, 0,0,0,0,0}; // a single bit enables the matrix output
|
||||||
|
|
||||||
|
|
|
@ -465,9 +465,12 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
ESP_LOGW(TAG, "Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!");
|
ESP_LOGW(TAG, "Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (_dmadesc_a_idx+1) > _dmadesc_count) {
|
if ( !dmadesc_b )
|
||||||
ESP_LOGE(TAG, "Attempted to create more DMA descriptors than allocated memory for. Expecting a maximum of %d DMA descriptors", _dmadesc_count);
|
{
|
||||||
return;
|
if ( (_dmadesc_a_idx+1) > _dmadesc_count) {
|
||||||
|
ESP_LOGE(TAG, "Attempted to create more DMA descriptors than allocated memory for. Expecting a maximum of %d DMA descriptors", _dmadesc_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
volatile lldesc_t *dmadesc;
|
volatile lldesc_t *dmadesc;
|
||||||
|
@ -550,11 +553,11 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
} // end
|
} // end
|
||||||
|
|
||||||
|
|
||||||
void Bus_Parallel16::flip_dma_output_buffer()
|
void Bus_Parallel16::set_dma_output_buffer(bool dmadesc_b)
|
||||||
{
|
{
|
||||||
if ( _double_dma_buffer == false) return;
|
if ( _double_dma_buffer == false) return;
|
||||||
|
|
||||||
if ( _dmadesc_a_active == true) // change across to everything 'b''
|
if ( dmadesc_b == true) // change across to everything 'b''
|
||||||
{
|
{
|
||||||
_dmadesc_a[_dmadesc_count-1].qe.stqe_next = &_dmadesc_b[0];
|
_dmadesc_a[_dmadesc_count-1].qe.stqe_next = &_dmadesc_b[0];
|
||||||
_dmadesc_b[_dmadesc_count-1].qe.stqe_next = &_dmadesc_b[0];
|
_dmadesc_b[_dmadesc_count-1].qe.stqe_next = &_dmadesc_b[0];
|
||||||
|
@ -565,7 +568,7 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
_dmadesc_b[_dmadesc_count-1].qe.stqe_next = &_dmadesc_a[0];
|
_dmadesc_b[_dmadesc_count-1].qe.stqe_next = &_dmadesc_a[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
_dmadesc_a_active ^= _dmadesc_a_active;
|
//_dmadesc_a_active ^= _dmadesc_a_active;
|
||||||
|
|
||||||
} // end flip
|
} // end flip
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ Contributors:
|
||||||
void dma_transfer_start();
|
void dma_transfer_start();
|
||||||
void dma_transfer_stop();
|
void dma_transfer_stop();
|
||||||
|
|
||||||
void flip_dma_output_buffer();
|
void set_dma_output_buffer(bool dmadesc_b = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ Contributors:
|
||||||
config_t _cfg;
|
config_t _cfg;
|
||||||
|
|
||||||
bool _double_dma_buffer = false;
|
bool _double_dma_buffer = false;
|
||||||
bool _dmadesc_a_active = true;
|
//bool _dmadesc_a_active = true;
|
||||||
|
|
||||||
uint32_t _dmadesc_count = 0; // number of dma decriptors
|
uint32_t _dmadesc_count = 0; // number of dma decriptors
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,17 @@
|
||||||
PLEASE SUPPORT THEM!
|
PLEASE SUPPORT THEM!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
#if __has_include (<hal/lcd_ll.h>)
|
||||||
|
// Stop compile errors: /src/platforms/esp32s3/gdma_lcd_parallel16.hpp:64:10: fatal error: hal/lcd_ll.h: No such file or directory
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "gdma_lcd_parallel16.hpp"
|
#include "gdma_lcd_parallel16.hpp"
|
||||||
|
|
||||||
static const char* TAG = "gdma_lcd_parallel16";
|
static const char* TAG = "gdma_lcd_parallel16";
|
||||||
|
|
||||||
|
static int _dmadesc_a_idx = 0;
|
||||||
|
static int _dmadesc_b_idx = 0;
|
||||||
|
|
||||||
|
|
||||||
dma_descriptor_t desc; // DMA descriptor for testing
|
dma_descriptor_t desc; // DMA descriptor for testing
|
||||||
/*
|
/*
|
||||||
|
@ -73,7 +79,7 @@
|
||||||
LCD_CAM.lcd_user.lcd_reset = 1;
|
LCD_CAM.lcd_user.lcd_reset = 1;
|
||||||
esp_rom_delay_us(100);
|
esp_rom_delay_us(100);
|
||||||
|
|
||||||
auto lcd_clkm_div_num = 160000000 / _cfg.bus_freq;
|
uint32_t lcd_clkm_div_num = ((160000000 + 1) / _cfg.bus_freq) / 2;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Clock divider is %d", lcd_clkm_div_num);
|
ESP_LOGI(TAG, "Clock divider is %d", lcd_clkm_div_num);
|
||||||
|
|
||||||
|
@ -279,7 +285,8 @@
|
||||||
|
|
||||||
void Bus_Parallel16::enable_double_dma_desc(void)
|
void Bus_Parallel16::enable_double_dma_desc(void)
|
||||||
{
|
{
|
||||||
_double_dma_buffer = true;
|
ESP_LOGI(TAG, "Enabled support for secondary DMA buffer.");
|
||||||
|
_double_dma_buffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need this to work for double buffers etc.
|
// Need this to work for double buffers etc.
|
||||||
|
@ -309,9 +316,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// override static
|
||||||
_dmadesc_a_idx = 0;
|
_dmadesc_a_idx = 0;
|
||||||
_dmadesc_b_idx = 0;
|
_dmadesc_b_idx = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -321,20 +328,15 @@
|
||||||
{
|
{
|
||||||
static constexpr size_t MAX_DMA_LEN = (4096-4);
|
static constexpr size_t MAX_DMA_LEN = (4096-4);
|
||||||
|
|
||||||
if (size > MAX_DMA_LEN)
|
if (size > MAX_DMA_LEN) {
|
||||||
{
|
|
||||||
size = MAX_DMA_LEN;
|
size = MAX_DMA_LEN;
|
||||||
ESP_LOGW(TAG, "Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!");
|
ESP_LOGW(TAG, "Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _dmadesc_a_idx >= _dmadesc_count)
|
if ( dmadesc_b == true)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "Attempted to create more DMA descriptors than allocated memory for. Expecting a maximum of %d DMA descriptors", _dmadesc_count);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_double_dma_buffer == true && dmadesc_b == true)
|
// ESP_LOGI(TAG, "Creating dma desc B %d", _dmadesc_b_idx);
|
||||||
{
|
|
||||||
|
|
||||||
_dmadesc_b[_dmadesc_b_idx].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
_dmadesc_b[_dmadesc_b_idx].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||||
_dmadesc_b[_dmadesc_b_idx].dw0.suc_eof = 0;
|
_dmadesc_b[_dmadesc_b_idx].dw0.suc_eof = 0;
|
||||||
|
@ -351,10 +353,16 @@
|
||||||
_dmadesc_b_idx++;
|
_dmadesc_b_idx++;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// ESP_LOGI(TAG, "Creating dma desc A %d", _dmadesc_a_idx);
|
||||||
|
|
||||||
|
if ( _dmadesc_a_idx >= _dmadesc_count)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "Attempted to create more DMA descriptors than allocated. Expecting max %d descriptors.", _dmadesc_count);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_dmadesc_a[_dmadesc_a_idx].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
_dmadesc_a[_dmadesc_a_idx].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
|
||||||
_dmadesc_a[_dmadesc_a_idx].dw0.suc_eof = 0;
|
_dmadesc_a[_dmadesc_a_idx].dw0.suc_eof = 0;
|
||||||
|
@ -394,12 +402,12 @@
|
||||||
} // end
|
} // end
|
||||||
|
|
||||||
|
|
||||||
void Bus_Parallel16::flip_dma_output_buffer()
|
void Bus_Parallel16::set_dma_output_buffer(bool dmadesc_b)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( _double_dma_buffer == false) return;
|
if ( _double_dma_buffer == false) return;
|
||||||
|
|
||||||
if ( _dmadesc_a_active == true) // change across to everything 'b''
|
if ( dmadesc_b == true) // change across to everything 'b''
|
||||||
{
|
{
|
||||||
_dmadesc_a[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
_dmadesc_a[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
||||||
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
||||||
|
@ -410,10 +418,8 @@
|
||||||
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_a[0];
|
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_a[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
_dmadesc_a_active ^= _dmadesc_a_active;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end flip
|
} // end flip
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if __has_include (<esp_lcd_panel_io.h>)
|
#if __has_include (<hal/lcd_ll.h>)
|
||||||
|
|
||||||
#include <sdkconfig.h>
|
#include <sdkconfig.h>
|
||||||
#include <esp_lcd_panel_io.h>
|
#include <esp_lcd_panel_io.h>
|
||||||
|
@ -55,13 +55,16 @@
|
||||||
#else
|
#else
|
||||||
#include <driver/periph_ctrl.h>
|
#include <driver/periph_ctrl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <esp_private/gdma.h>
|
#include <esp_private/gdma.h>
|
||||||
#include <esp_rom_gpio.h>
|
#include <esp_rom_gpio.h>
|
||||||
#include <hal/dma_types.h>
|
#include <hal/dma_types.h>
|
||||||
#include <hal/gpio_hal.h>
|
#include <hal/gpio_hal.h>
|
||||||
|
|
||||||
#include <hal/lcd_ll.h>
|
#include <hal/lcd_ll.h>
|
||||||
#include <soc/lcd_cam_reg.h>
|
#include <soc/lcd_cam_reg.h>
|
||||||
#include <soc/lcd_cam_struct.h>
|
#include <soc/lcd_cam_struct.h>
|
||||||
|
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
#include <esp_heap_caps_init.h>
|
#include <esp_heap_caps_init.h>
|
||||||
|
|
||||||
|
@ -143,7 +146,7 @@
|
||||||
void dma_transfer_start();
|
void dma_transfer_start();
|
||||||
void dma_transfer_stop();
|
void dma_transfer_stop();
|
||||||
|
|
||||||
void flip_dma_output_buffer();
|
void set_dma_output_buffer(bool dmadesc_b = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -153,15 +156,14 @@
|
||||||
gdma_channel_handle_t dma_chan;
|
gdma_channel_handle_t dma_chan;
|
||||||
|
|
||||||
uint32_t _dmadesc_count = 0; // number of dma decriptors
|
uint32_t _dmadesc_count = 0; // number of dma decriptors
|
||||||
uint32_t _dmadesc_a_idx = 0;
|
// uint32_t _dmadesc_a_idx = 0;
|
||||||
|
//uint32_t _dmadesc_b_idx = 0;
|
||||||
|
|
||||||
HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
|
HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
|
||||||
|
HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
|
||||||
|
|
||||||
bool _double_dma_buffer = false;
|
bool _double_dma_buffer = false;
|
||||||
bool _dmadesc_a_active = true;
|
//bool _dmadesc_a_active = true;
|
||||||
uint32_t _dmadesc_b_idx = 0;
|
|
||||||
|
|
||||||
HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
|
|
||||||
|
|
||||||
esp_lcd_i80_bus_handle_t _i80_bus;
|
esp_lcd_i80_bus_handle_t _i80_bus;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
#include "esp32s3/gdma_lcd_parallel16.hpp"
|
#include "esp32s3/gdma_lcd_parallel16.hpp"
|
||||||
#include "esp32s3/esp32s3-default-pins.hpp"
|
#include "esp32s3/esp32s3-default-pins.hpp"
|
||||||
|
|
||||||
#else
|
#elif defined (CONFIG_IDF_TARGET_ESP32)
|
||||||
|
|
||||||
// Assume an ESP32 (the original 2015 version)
|
// Assume an ESP32 (the original 2015 version)
|
||||||
// Same include as ESP32S3
|
// Same include as ESP32S3
|
||||||
|
|
Loading…
Reference in a new issue