Improved memory checks
This commit is contained in:
parent
75136c59e1
commit
9a5ed4db9e
5 changed files with 187 additions and 173 deletions
|
@ -76,10 +76,10 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
if (double_buffering_enabled) {
|
if (double_buffering_enabled) {
|
||||||
Serial.println("DOUBLE FRAME BUFFERS / DOUBLE BUFFERING IS ENABLED. DOUBLE THE RAM REQUIRED!");
|
Serial.println("DOUBLE FRAME BUFFERS / DOUBLE BUFFERING IS ENABLED. DOUBLE THE RAM REQUIRED!");
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Serial.println("DMA memory blocks available before any malloc's: ");
|
Serial.println("DMA memory blocks available before any malloc's: ");
|
||||||
heap_caps_print_heap_info(MALLOC_CAP_DMA);
|
heap_caps_print_heap_info(MALLOC_CAP_DMA);
|
||||||
*/
|
|
||||||
|
|
||||||
Serial.printf("FYI: Size of an ESP32 DMA linked list descriptor (lldesc_t) is %d bytes\r\n", sizeof(lldesc_t));
|
Serial.printf("FYI: Size of an ESP32 DMA linked list descriptor (lldesc_t) is %d bytes\r\n", sizeof(lldesc_t));
|
||||||
Serial.printf("We're going to need %d bytes of SRAM just for the frame buffer(s).\r\n", _frame_buffer_memory_required);
|
Serial.printf("We're going to need %d bytes of SRAM just for the frame buffer(s).\r\n", _frame_buffer_memory_required);
|
||||||
|
@ -87,11 +87,19 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Can we fit the framebuffer into the single DMA capable memory block available?
|
// Can we fit the framebuffer into the single DMA capable memory block available?
|
||||||
if ( heap_caps_get_largest_free_block(MALLOC_CAP_DMA) >= _frame_buffer_memory_required ) { // YES - SIMPLE
|
if ( heap_caps_get_largest_free_block(MALLOC_CAP_DMA) < _frame_buffer_memory_required ) {
|
||||||
|
|
||||||
// Allocate the framebuffer memory, fail if we can even do this
|
#if SERIAL_DEBUG
|
||||||
|
Serial.printf("######### Insufficent memory for requested resolution. Reduce MATRIX_COLOR_DEPTH and try again.\r\n\tAdditional %d bytes of memory required.\r\n\r\n", (_frame_buffer_memory_required-heap_caps_get_largest_free_block(MALLOC_CAP_DMA)) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Allocate the framebuffer 1 memory, fail if we can even do this
|
||||||
matrix_framebuffer_malloc_1 = (frameStruct *)heap_caps_malloc(_frame_buffer_memory_required, MALLOC_CAP_DMA);
|
matrix_framebuffer_malloc_1 = (frameStruct *)heap_caps_malloc(_frame_buffer_memory_required, MALLOC_CAP_DMA);
|
||||||
if ( !matrix_framebuffer_malloc_1 ) {
|
if ( matrix_framebuffer_malloc_1 == NULL ) {
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.println("ERROR: Couldn't malloc matrix_framebuffer_malloc_1! Critical fail.\r\n");
|
Serial.println("ERROR: Couldn't malloc matrix_framebuffer_malloc_1! Critical fail.\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -100,8 +108,8 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
}
|
}
|
||||||
|
|
||||||
_total_dma_capable_memory_reserved += _frame_buffer_memory_required;
|
_total_dma_capable_memory_reserved += _frame_buffer_memory_required;
|
||||||
}
|
|
||||||
|
|
||||||
|
// SPLIT MEMORY MODE
|
||||||
#ifdef SPLIT_MEMORY_MODE
|
#ifdef SPLIT_MEMORY_MODE
|
||||||
|
|
||||||
Serial.println("SPLIT MEMORY MODE ENABLED!");
|
Serial.println("SPLIT MEMORY MODE ENABLED!");
|
||||||
|
@ -113,11 +121,19 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
|
|
||||||
|
|
||||||
// Can we fit the framebuffer into the single DMA capable memory block available?
|
// Can we fit the framebuffer into the single DMA capable memory block available?
|
||||||
if ( heap_caps_get_largest_free_block(MALLOC_CAP_DMA) >= _frame_buffer_memory_required ) { // YES - SIMPLE
|
// Can we fit the framebuffer into the single DMA capable memory block available?
|
||||||
|
if ( heap_caps_get_largest_free_block(MALLOC_CAP_DMA) < _frame_buffer_memory_required ) {
|
||||||
|
|
||||||
// Allocate the framebuffer memory, fail if we can even do this
|
#if SERIAL_DEBUG
|
||||||
|
Serial.printf("######### Insufficent memory for second framebuffer for requested resolution. Reduce MATRIX_COLOR_DEPTH and try again.\r\n\tAdditional %d bytes of memory required.\r\n\r\n", (_frame_buffer_memory_required-heap_caps_get_largest_free_block(MALLOC_CAP_DMA)) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the framebuffer 2 memory, fail if we can even do this
|
||||||
matrix_framebuffer_malloc_2 = (frameStruct *)heap_caps_malloc(_frame_buffer_memory_required, MALLOC_CAP_DMA);
|
matrix_framebuffer_malloc_2 = (frameStruct *)heap_caps_malloc(_frame_buffer_memory_required, MALLOC_CAP_DMA);
|
||||||
if ( !matrix_framebuffer_malloc_2 ) {
|
if ( matrix_framebuffer_malloc_2 == NULL ) {
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.println("ERROR: Couldn't malloc matrix_framebuffer_malloc_2! Critical fail.\r\n");
|
Serial.println("ERROR: Couldn't malloc matrix_framebuffer_malloc_2! Critical fail.\r\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -126,7 +142,7 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
}
|
}
|
||||||
|
|
||||||
_total_dma_capable_memory_reserved += _frame_buffer_memory_required;
|
_total_dma_capable_memory_reserved += _frame_buffer_memory_required;
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -245,6 +261,15 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
Serial.printf("DMA Memory Available: %d bytes total. Largest free block: %d bytes.\r\n", heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
|
Serial.printf("DMA Memory Available: %d bytes total. Largest free block: %d bytes.\r\n", heap_caps_get_free_size(MALLOC_CAP_DMA), heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
|
||||||
Serial.printf("General RAM Available: %d bytes total. Largest free block: %d bytes.\r\n", heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT));
|
Serial.printf("General RAM Available: %d bytes total. Largest free block: %d bytes.\r\n", heap_caps_get_free_size(MALLOC_CAP_DEFAULT), heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT));
|
||||||
|
|
||||||
|
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.println("DMA memory blocks available after malloc's: ");
|
||||||
|
heap_caps_print_heap_info(MALLOC_CAP_DMA);
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} // end initMatrixDMABuffer()
|
} // end initMatrixDMABuffer()
|
||||||
|
@ -359,8 +384,10 @@ void RGB64x32MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.println("DMA Memory Map after allocations: ");
|
Serial.println("DMA Memory Map after DMA LL allocations: ");
|
||||||
heap_caps_print_heap_info(MALLOC_CAP_DMA);
|
heap_caps_print_heap_info(MALLOC_CAP_DMA);
|
||||||
|
|
||||||
|
delay(1000);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Just os we know
|
// Just os we know
|
||||||
|
@ -375,11 +402,20 @@ void RGB64x32MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_
|
||||||
/* Update a specific co-ordinate in the DMA buffer */
|
/* Update a specific co-ordinate in the DMA buffer */
|
||||||
void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t y_coord, uint8_t red, uint8_t green, uint8_t blue)
|
void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t y_coord, uint8_t red, uint8_t green, uint8_t blue)
|
||||||
{
|
{
|
||||||
|
if ( !everything_OK ) {
|
||||||
|
|
||||||
if ( !everything_OK )
|
#if SERIAL_DEBUG
|
||||||
assert("DMA configuration in begin() not performed or completed successfully.");
|
Serial.println("Cannot updateMatrixDMABuffer as setup failed!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SPLIT_MEMORY_MODE
|
||||||
|
#ifdef SERIAL_DEBUG
|
||||||
int tmp_y_coord = y_coord;
|
int tmp_y_coord = y_coord;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 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)
|
||||||
|
@ -410,11 +446,11 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t
|
||||||
#ifdef SPLIT_MEMORY_MODE
|
#ifdef SPLIT_MEMORY_MODE
|
||||||
if (y_coord >= SPLIT_MEMORY_ROWS_PER_FRAME ) {
|
if (y_coord >= SPLIT_MEMORY_ROWS_PER_FRAME ) {
|
||||||
p = &matrix_framebuffer_malloc_2[back_buffer_id].rowdata[(y_coord-SPLIT_MEMORY_ROWS_PER_FRAME)].rowbits[color_depth_idx]; //matrixUpdateFrames location to write to uint16_t's
|
p = &matrix_framebuffer_malloc_2[back_buffer_id].rowdata[(y_coord-SPLIT_MEMORY_ROWS_PER_FRAME)].rowbits[color_depth_idx]; //matrixUpdateFrames location to write to uint16_t's
|
||||||
}
|
|
||||||
#ifdef SERIAL_DEBUG
|
|
||||||
// Serial.printf("Using framebuffer_malloc_2. y-coord: %d, matrix row offset: %d \r\n", tmp_y_coord, (y_coord-SPLIT_MEMORY_ROWS_PER_FRAME) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#ifdef SERIAL_DEBUG
|
||||||
|
// Serial.printf("fb_malloc_2. y-coord: %d, calc. offset: %d \r\n", tmp_y_coord, (y_coord-SPLIT_MEMORY_ROWS_PER_FRAME) );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -467,19 +503,18 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t
|
||||||
if((x_coord) >= lsbBrightness) v|=BIT_OE; // For Brightness
|
if((x_coord) >= lsbBrightness) v|=BIT_OE; // For Brightness
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* When using the drawPixel, we are obviously only changing the value of one x,y position,
|
||||||
|
* however, the HUB75 is wired up such that it is always painting TWO lines at the same time
|
||||||
|
* and this reflects the parallel in-DMA-memory data structure of uint16_t's that are getting
|
||||||
/* When using the Adafruit drawPixel, we only have one pixel co-ordinate and colour to draw (duh)
|
* pumped out at high speed.
|
||||||
* so we can't paint a top and bottom half (or whatever row split the panel is) at the same time.
|
*
|
||||||
* Need to be smart and check the DMA buffer to see what the other half thinks (pun intended)
|
* So we need to ensure we persist the bits (8 of them) of the uint16_t for the row we aren't changing.
|
||||||
* and persist this when we refresh.
|
|
||||||
*
|
*
|
||||||
* The DMA buffer order has also been reversed (refer to the last code in this function)
|
* The DMA buffer order has also been reversed (refer to the last code in this function)
|
||||||
* so we have to check for this and check the correct position of the MATRIX_DATA_STORAGE_TYPE
|
* so we have to check for this and check the correct position of the MATRIX_DATA_STORAGE_TYPE
|
||||||
* data.
|
* data.
|
||||||
*/
|
*/
|
||||||
int16_t tmp_x_coord = x_coord;
|
int tmp_x_coord = x_coord;
|
||||||
if(x_coord%2)
|
if(x_coord%2)
|
||||||
{
|
{
|
||||||
tmp_x_coord -= 1;
|
tmp_x_coord -= 1;
|
||||||
|
@ -491,12 +526,9 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t
|
||||||
{ // Need to copy what the RGB status is for the bottom pixels
|
{ // Need to copy what the RGB status is for the bottom pixels
|
||||||
|
|
||||||
// Set the color of the pixel of interest
|
// Set the color of the pixel of interest
|
||||||
if (green & mask)
|
if (green & mask) { v|=BIT_G1; }
|
||||||
v|=BIT_G1;
|
if (blue & mask) { v|=BIT_B1; }
|
||||||
if (blue & mask)
|
if (red & mask) { v|=BIT_R1; }
|
||||||
v|=BIT_B1;
|
|
||||||
if (red & mask)
|
|
||||||
v|=BIT_R1;
|
|
||||||
|
|
||||||
// Persist what was painted to the other half of the frame equiv. pixel
|
// Persist what was painted to the other half of the frame equiv. pixel
|
||||||
if (p->data[tmp_x_coord] & BIT_R2)
|
if (p->data[tmp_x_coord] & BIT_R2)
|
||||||
|
@ -512,12 +544,9 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t
|
||||||
{ // Do it the other way around
|
{ // Do it the other way around
|
||||||
|
|
||||||
// Color to set
|
// Color to set
|
||||||
if (red & mask)
|
if (red & mask) { v|=BIT_R2; }
|
||||||
v|=BIT_R2;
|
if (green & mask) { v|=BIT_G2; }
|
||||||
if (green & mask)
|
if (blue & mask) { v|=BIT_B2; }
|
||||||
v|=BIT_G2;
|
|
||||||
if (blue & mask)
|
|
||||||
v|=BIT_B2;
|
|
||||||
|
|
||||||
// Copy
|
// Copy
|
||||||
if (p->data[tmp_x_coord] & BIT_R1)
|
if (p->data[tmp_x_coord] & BIT_R1)
|
||||||
|
@ -531,10 +560,6 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t
|
||||||
|
|
||||||
} // paint
|
} // paint
|
||||||
|
|
||||||
//Serial.printf("x: %d, y: %d ", x_coord, y_coord );
|
|
||||||
//Serial.println(v, BIN);
|
|
||||||
|
|
||||||
|
|
||||||
// 16 bit parallel mode
|
// 16 bit parallel mode
|
||||||
//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
|
||||||
if(x_coord%2){
|
if(x_coord%2){
|
||||||
|
@ -545,19 +570,14 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(int16_t x_coord, int16_t
|
||||||
|
|
||||||
} // color depth loop (8)
|
} // color depth loop (8)
|
||||||
|
|
||||||
//Show our work!
|
} // updateMatrixDMABuffer (specific co-ords change)
|
||||||
//i2s_parallel_flip_to_buffer(&I2S1, backbuf_id);
|
|
||||||
|
|
||||||
// If we've linked the DMA output to the same backbuf_id that this function is
|
|
||||||
// currently writing too, then the output will be immediate. Else: flipDMABuffer(), then showDMABuffer()
|
|
||||||
|
|
||||||
|
|
||||||
} // updateDMABuffer
|
|
||||||
|
|
||||||
|
|
||||||
/* Update the entire buffer with a single specific colour - quicker */
|
/* Update the entire buffer with a single specific colour - quicker */
|
||||||
void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint8_t blue)
|
void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint8_t blue)
|
||||||
{
|
{
|
||||||
|
if ( !everything_OK ) return;
|
||||||
|
|
||||||
for (unsigned int matrix_frame_parallel_row = 0; matrix_frame_parallel_row < ROWS_PER_FRAME; matrix_frame_parallel_row++) // half height - 16 iterations
|
for (unsigned int matrix_frame_parallel_row = 0; matrix_frame_parallel_row < ROWS_PER_FRAME; matrix_frame_parallel_row++) // half height - 16 iterations
|
||||||
{
|
{
|
||||||
for(int color_depth_idx=0; color_depth_idx<PIXEL_COLOR_DEPTH_BITS; color_depth_idx++) // color depth - 8 iterations
|
for(int color_depth_idx=0; color_depth_idx<PIXEL_COLOR_DEPTH_BITS; color_depth_idx++) // color depth - 8 iterations
|
||||||
|
@ -575,8 +595,15 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t gre
|
||||||
//Serial.printf("Using framebuffer_malloc_2. Row %d = Offset %d\r\n", matrix_frame_parallel_row, (matrix_frame_parallel_row-SPLIT_MEMORY_ROWS_PER_FRAME) );
|
//Serial.printf("Using framebuffer_malloc_2. Row %d = Offset %d\r\n", matrix_frame_parallel_row, (matrix_frame_parallel_row-SPLIT_MEMORY_ROWS_PER_FRAME) );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef SERIAL_DEBUG
|
||||||
|
// Serial.printf("Using framebuffer_malloc_1. Row %d\r\n", matrix_frame_parallel_row );
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for(int x_coord=0; x_coord < MATRIX_WIDTH; x_coord++) // row pixel width 64 iterations
|
for(int x_coord=0; x_coord < MATRIX_WIDTH; x_coord++) // row pixel width 64 iterations
|
||||||
{
|
{
|
||||||
|
@ -630,28 +657,14 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t gre
|
||||||
if((x_coord) >= lsbBrightness) v|=BIT_OE; // For Brightness
|
if((x_coord) >= lsbBrightness) v|=BIT_OE; // For Brightness
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Top and bottom matrix MATRIX_ROWS_IN_PARALLEL half colours
|
||||||
// Top half colours
|
if (green & mask) { v|=BIT_G1; v|=BIT_R2; }
|
||||||
if (green & mask)
|
if (blue & mask) { v|=BIT_B1; v|=BIT_G2; }
|
||||||
v|=BIT_G1;
|
if (red & mask) { v|=BIT_R1; v|=BIT_B2; }
|
||||||
if (blue & mask)
|
|
||||||
v|=BIT_B1;
|
|
||||||
if (red & mask)
|
|
||||||
v|=BIT_R1;
|
|
||||||
|
|
||||||
// Bottom half colours
|
|
||||||
if (red & mask)
|
|
||||||
v|=BIT_R2;
|
|
||||||
if (green & mask)
|
|
||||||
v|=BIT_G2;
|
|
||||||
if (blue & mask)
|
|
||||||
v|=BIT_B2;
|
|
||||||
|
|
||||||
|
|
||||||
// 16 bit parallel mode
|
// 16 bit parallel mode
|
||||||
//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
|
||||||
if(x_coord%2)
|
if(x_coord%2) {
|
||||||
{
|
|
||||||
p->data[(x_coord)-1] = v;
|
p->data[(x_coord)-1] = v;
|
||||||
} else {
|
} else {
|
||||||
p->data[(x_coord)+1] = v;
|
p->data[(x_coord)+1] = v;
|
||||||
|
@ -661,12 +674,4 @@ void RGB64x32MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t gre
|
||||||
} // colour depth loop (8)
|
} // colour depth loop (8)
|
||||||
} // end row iteration
|
} // end row iteration
|
||||||
|
|
||||||
|
} // updateMatrixDMABuffer (full frame paint)
|
||||||
|
|
||||||
//Show our work!
|
|
||||||
//i2s_parallel_flip_to_buffer(&I2S1, backbuf_id);
|
|
||||||
|
|
||||||
// If we've linked the DMA output to the same backbuf_id that this function is
|
|
||||||
// currently writing too, then the output will be immediate. Else: flipDMABuffer(), then showDMABuffer()
|
|
||||||
|
|
||||||
} // updateDMABuffer
|
|
|
@ -35,7 +35,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef MATRIX_HEIGHT
|
#ifndef MATRIX_HEIGHT
|
||||||
#define MATRIX_HEIGHT 32 //64
|
#define MATRIX_HEIGHT 32
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MATRIX_WIDTH
|
#ifndef MATRIX_WIDTH
|
||||||
|
@ -210,6 +210,11 @@ class RGB64x32MatrixPanel_I2S_DMA : public GFX {
|
||||||
|
|
||||||
showDMABuffer(); // show backbuf_id of 0
|
showDMABuffer(); // show backbuf_id of 0
|
||||||
|
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
if (!everything_OK)
|
||||||
|
Serial.println("RGB64x32MatrixPanel_I2S_DMA::begin() failed.");
|
||||||
|
#endif
|
||||||
|
|
||||||
return everything_OK;
|
return everything_OK;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ A [typical RGB panel available for purchase](https://www.aliexpress.com/item/256
|
||||||
|
|
||||||
## Can I chain panels or use with larger panels?
|
## Can I chain panels or use with larger panels?
|
||||||
|
|
||||||
Yes you can. If you want to use with a 64x64 pixel panel you MUST configure a valid *E_PIN* to your ESP32 and connect it to the E pin of the HUB75 panel!
|
Yes you can. If you want to use with a 64x64 pixel panel (typically a HUB75*E* panel) you MUST configure a valid *E_PIN* to your ESP32 and connect it to the E pin of the HUB75 panel! Hence the 'E' in 'HUB75E'
|
||||||
|
|
||||||
This library has only been tested with a 64 pixel (wide) and 32 (high) RGB panel. Theoretically, if you want to chain two of these horizontally to make a 128x32 panel you can do so with the cable and then set the MATRIX_WIDTH to '128'.
|
This library has only been tested with a 64 pixel (wide) and 32 (high) RGB panel. Theoretically, if you want to chain two of these horizontally to make a 128x32 panel you can do so with the cable and then set the MATRIX_WIDTH to '128'.
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,11 @@
|
||||||
#include "driver/periph_ctrl.h"
|
#include "driver/periph_ctrl.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
#include "rom/lldesc.h"
|
#include "rom/lldesc.h"
|
||||||
#include "esp_heap_caps.h"
|
//#include "esp_heap_caps.h"
|
||||||
#include "esp32_i2s_parallel.h"
|
#include "esp32_i2s_parallel.h"
|
||||||
|
|
||||||
|
#define DMA_MAX (4096-4)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile lldesc_t *dmadesc_a, *dmadesc_b;
|
volatile lldesc_t *dmadesc_a, *dmadesc_b;
|
||||||
int desccount_a, desccount_b;
|
int desccount_a, desccount_b;
|
||||||
|
@ -61,9 +63,7 @@ static void IRAM_ATTR i2s_isr(void* arg) {
|
||||||
if(shiftCompleteCallback)
|
if(shiftCompleteCallback)
|
||||||
shiftCompleteCallback();
|
shiftCompleteCallback();
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
#define DMA_MAX (4096-4)
|
|
||||||
|
|
||||||
//Calculate the amount of dma descs needed for a buffer desc
|
//Calculate the amount of dma descs needed for a buffer desc
|
||||||
static int calc_needed_dma_descs_for(i2s_parallel_buffer_desc_t *desc) {
|
static int calc_needed_dma_descs_for(i2s_parallel_buffer_desc_t *desc) {
|
||||||
int ret=0;
|
int ret=0;
|
||||||
|
@ -102,8 +102,10 @@ static void fill_dma_desc(volatile lldesc_t *dmadesc, i2s_parallel_buffer_desc_t
|
||||||
|
|
||||||
printf("fill_dma_desc: filled %d descriptors\n", n);
|
printf("fill_dma_desc: filled %d descriptors\n", n);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// size must be less than DMA_MAX - need to handle breaking long transfer into two descriptors before call
|
// size must be less than DMA_MAX - need to handle breaking long transfer into two descriptors before call
|
||||||
|
// DMA_MAX by the way is the maximum data packet size you can hold in one chunk
|
||||||
void link_dma_desc(volatile lldesc_t *dmadesc, volatile lldesc_t *prevdmadesc, void *memory, size_t size) {
|
void link_dma_desc(volatile lldesc_t *dmadesc, volatile lldesc_t *prevdmadesc, void *memory, size_t size) {
|
||||||
if(size > DMA_MAX) size = DMA_MAX;
|
if(size > DMA_MAX) size = DMA_MAX;
|
||||||
|
|
||||||
|
@ -128,7 +130,6 @@ static void gpio_setup_out(int gpio, int sig) {
|
||||||
gpio_matrix_out(gpio, sig, false, false);
|
gpio_matrix_out(gpio, sig, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dma_reset(i2s_dev_t *dev) {
|
static void dma_reset(i2s_dev_t *dev) {
|
||||||
dev->lc_conf.in_rst=1; dev->lc_conf.in_rst=0;
|
dev->lc_conf.in_rst=1; dev->lc_conf.in_rst=0;
|
||||||
dev->lc_conf.out_rst=1; dev->lc_conf.out_rst=0;
|
dev->lc_conf.out_rst=1; dev->lc_conf.out_rst=0;
|
||||||
|
@ -147,14 +148,14 @@ void i2s_parallel_setup_without_malloc(i2s_dev_t *dev, const i2s_parallel_config
|
||||||
sig_data_base=I2S0O_DATA_OUT0_IDX;
|
sig_data_base=I2S0O_DATA_OUT0_IDX;
|
||||||
sig_clk=I2S0O_WS_OUT_IDX;
|
sig_clk=I2S0O_WS_OUT_IDX;
|
||||||
} else {
|
} else {
|
||||||
|
printf("Setting up i2s parallel mode in %d bit mode!\n", cfg->bits);
|
||||||
if (cfg->bits==I2S_PARALLEL_BITS_32) {
|
if (cfg->bits==I2S_PARALLEL_BITS_32) {
|
||||||
sig_data_base=I2S1O_DATA_OUT0_IDX;
|
sig_data_base=I2S1O_DATA_OUT0_IDX;
|
||||||
} else if (cfg->bits==I2S_PARALLEL_BITS_16) {
|
} else if (cfg->bits==I2S_PARALLEL_BITS_16) {
|
||||||
//Because of... reasons... the 16-bit values for i2s1 appear on d8...d23
|
//Because of... reasons... the 16-bit values for i2s1 appear on d8...d23
|
||||||
printf("Setting up i2s parallel mode in 16 bit mode!");
|
|
||||||
sig_data_base=I2S1O_DATA_OUT8_IDX;
|
sig_data_base=I2S1O_DATA_OUT8_IDX;
|
||||||
} else { // I2S_PARALLEL_BITS_8
|
} else { // I2S_PARALLEL_BITS_8
|
||||||
printf("Setting up i2s parallel mode in 8 bit mode -> https://www.esp32.com/viewtopic.php?f=17&t=3188 | https://www.esp32.com/viewtopic.php?f=13&t=3256");
|
//printf("Setting up i2s parallel mode in %d bit mode -> https://www.esp32.com/viewtopic.php?f=17&t=3188 | https://www.esp32.com/viewtopic.php?f=13&t=3256", 8);
|
||||||
sig_data_base=I2S1O_DATA_OUT0_IDX;
|
sig_data_base=I2S1O_DATA_OUT0_IDX;
|
||||||
}
|
}
|
||||||
sig_clk=I2S1O_WS_OUT_IDX;
|
sig_clk=I2S1O_WS_OUT_IDX;
|
||||||
|
@ -251,7 +252,7 @@ void i2s_parallel_setup_without_malloc(i2s_dev_t *dev, const i2s_parallel_config
|
||||||
// allocate a level 1 intterupt: lowest priority, as ISR isn't urgent and may take a long time to complete
|
// allocate a level 1 intterupt: lowest priority, as ISR isn't urgent and may take a long time to complete
|
||||||
esp_intr_alloc(ETS_I2S1_INTR_SOURCE, (int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1), i2s_isr, NULL, NULL);
|
esp_intr_alloc(ETS_I2S1_INTR_SOURCE, (int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1), i2s_isr, NULL, NULL);
|
||||||
|
|
||||||
//Start dma on front buffer
|
//Start dma on front buffer (buffer a)
|
||||||
dev->lc_conf.val=I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN;
|
dev->lc_conf.val=I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN;
|
||||||
dev->out_link.addr=((uint32_t)(&st->dmadesc_a[0]));
|
dev->out_link.addr=((uint32_t)(&st->dmadesc_a[0]));
|
||||||
dev->out_link.start=1;
|
dev->out_link.start=1;
|
||||||
|
@ -281,4 +282,5 @@ bool i2s_parallel_is_previous_buffer_free() {
|
||||||
return previousBufferFree;
|
return previousBufferFree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,7 +13,7 @@ extern "C" {
|
||||||
#include "rom/lldesc.h"
|
#include "rom/lldesc.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2S_PARALLEL_BITS_8=8, // BUG: Doesn't work.
|
I2S_PARALLEL_BITS_8=8,
|
||||||
I2S_PARALLEL_BITS_16=16,
|
I2S_PARALLEL_BITS_16=16,
|
||||||
I2S_PARALLEL_BITS_32=32,
|
I2S_PARALLEL_BITS_32=32,
|
||||||
} i2s_parallel_cfg_bits_t;
|
} i2s_parallel_cfg_bits_t;
|
||||||
|
@ -29,18 +29,20 @@ typedef struct {
|
||||||
int clkspeed_hz;
|
int clkspeed_hz;
|
||||||
i2s_parallel_cfg_bits_t bits;
|
i2s_parallel_cfg_bits_t bits;
|
||||||
i2s_parallel_buffer_desc_t *bufa;
|
i2s_parallel_buffer_desc_t *bufa;
|
||||||
i2s_parallel_buffer_desc_t *bufb;
|
i2s_parallel_buffer_desc_t *bufb; // only used with double buffering
|
||||||
int desccount_a;
|
int desccount_a;
|
||||||
int desccount_b;
|
int desccount_b; // only used with double buffering
|
||||||
lldesc_t * lldesc_a;
|
lldesc_t * lldesc_a;
|
||||||
lldesc_t * lldesc_b;
|
lldesc_t * lldesc_b; // only used with double buffering
|
||||||
} i2s_parallel_config_t;
|
} i2s_parallel_config_t;
|
||||||
|
|
||||||
void i2s_parallel_setup(i2s_dev_t *dev, const i2s_parallel_config_t *cfg);
|
|
||||||
void i2s_parallel_setup_without_malloc(i2s_dev_t *dev, const i2s_parallel_config_t *cfg);
|
void i2s_parallel_setup_without_malloc(i2s_dev_t *dev, const i2s_parallel_config_t *cfg);
|
||||||
|
void link_dma_desc(volatile lldesc_t *dmadesc, volatile lldesc_t *prevdmadesc, void *memory, size_t size);
|
||||||
|
|
||||||
void i2s_parallel_flip_to_buffer(i2s_dev_t *dev, int bufid);
|
void i2s_parallel_flip_to_buffer(i2s_dev_t *dev, int bufid);
|
||||||
bool i2s_parallel_is_previous_buffer_free();
|
bool i2s_parallel_is_previous_buffer_free();
|
||||||
void link_dma_desc(volatile lldesc_t *dmadesc, volatile lldesc_t *prevdmadesc, void *memory, size_t size);
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*callback)(void);
|
typedef void (*callback)(void);
|
||||||
void setShiftCompleteCallback(callback f);
|
void setShiftCompleteCallback(callback f);
|
||||||
|
|
Loading…
Reference in a new issue