Improvement to ensure DMA payload limit not hit.
This commit is contained in:
parent
80d5ddff4c
commit
3159202ccf
5 changed files with 216 additions and 20 deletions
|
@ -156,7 +156,7 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
int ramrequired = numDMAdescriptorsPerRow * ROWS_PER_FRAME * _num_frame_buffers * sizeof(lldesc_t);
|
int ramrequired = numDMAdescriptorsPerRow * ROWS_PER_FRAME * _num_frame_buffers * sizeof(lldesc_t);
|
||||||
int largestblockfree = heap_caps_get_largest_free_block(MALLOC_CAP_DMA);
|
int largestblockfree = heap_caps_get_largest_free_block(MALLOC_CAP_DMA);
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.printf("numdesciptors per row %d, lsbMsbTransitionBit of %d requires %d RAM, %d available, leaving %d free: \r\n", numDMAdescriptorsPerRow, lsbMsbTransitionBit, ramrequired, largestblockfree, largestblockfree - ramrequired);
|
Serial.printf("lsbMsbTransitionBit of %d with %d DMA descriptors per frame row, requires %d bytes RAM, %d available, leaving %d free: \r\n", lsbMsbTransitionBit, numDMAdescriptorsPerRow, ramrequired, largestblockfree, largestblockfree - ramrequired);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(ramrequired < largestblockfree)
|
if(ramrequired < largestblockfree)
|
||||||
|
@ -187,8 +187,8 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
calculated_refresh_rate = actualRefreshRate;
|
calculated_refresh_rate = actualRefreshRate;
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.printf("lsbMsbTransitionBit of %d gives %d Hz refresh: \r\n", lsbMsbTransitionBit, actualRefreshRate);
|
Serial.printf("lsbMsbTransitionBit of %d gives %d Hz refresh: \r\n", lsbMsbTransitionBit, actualRefreshRate);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (actualRefreshRate > min_refresh_rate) // HACK Hard Coded: 100
|
if (actualRefreshRate > min_refresh_rate) // HACK Hard Coded: 100
|
||||||
break;
|
break;
|
||||||
|
@ -201,19 +201,41 @@ bool RGB64x32MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
|
|
||||||
Serial.printf("Raised lsbMsbTransitionBit to %d/%d to meet minimum refresh rate\r\n", lsbMsbTransitionBit, PIXEL_COLOR_DEPTH_BITS - 1);
|
Serial.printf("Raised lsbMsbTransitionBit to %d/%d to meet minimum refresh rate\r\n", lsbMsbTransitionBit, PIXEL_COLOR_DEPTH_BITS - 1);
|
||||||
|
|
||||||
// lsbMsbTransition Bit is now finalized - recalcuate descriptor count in case it changed to hit min refresh rate
|
/***
|
||||||
|
* Step 2a: lsbMsbTransition bit is now finalised - recalculate the DMA descriptor count required, which is used for
|
||||||
|
* memory allocation of the DMA linked list memory structure.
|
||||||
|
*/
|
||||||
numDMAdescriptorsPerRow = 1;
|
numDMAdescriptorsPerRow = 1;
|
||||||
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_DEPTH_BITS; i++) {
|
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_DEPTH_BITS; i++) {
|
||||||
numDMAdescriptorsPerRow += 1<<(i - lsbMsbTransitionBit - 1);
|
numDMAdescriptorsPerRow += 1<<(i - lsbMsbTransitionBit - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Serial.printf("Size of (sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS): %d.\r\n", (sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS));
|
||||||
|
//Serial.printf("Size of sizeof(rowColorDepthStruct): %d.\r\n", sizeof(rowColorDepthStruct));
|
||||||
|
|
||||||
|
|
||||||
|
// Going to need a little more DMA LL memory structure RAM.
|
||||||
|
// Refer to 'DMA_LL_PAYLOAD_SPLIT' code in configureDMA() below to understand why this exists.
|
||||||
|
// numDMAdescriptorsPerRow is also used to calcaulte descount which is super important in i2s_parallel_config_t SoC DMA setup.
|
||||||
|
if ( sizeof(rowColorDepthStruct) > DMA_MAX ) {
|
||||||
|
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.println("Split DMA payload enabled. Increasing DMA descriptor count per frame row by one.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//numDMAdescriptorsPerRow += 1;
|
||||||
|
numDMAdescriptorsPerRow += PIXEL_COLOR_DEPTH_BITS-1;
|
||||||
|
// Not if numDMAdescriptorsPerRow is even just one descriptor too large, DMA linked list will not correctly loop.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Step 3: Allocate memory for DMA linked list, linking up each framebuffer row in sequence for GPIO output.
|
* Step 3: Allocate memory for DMA linked list, linking up each framebuffer row in sequence for GPIO output.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
_dma_linked_list_memory_required = numDMAdescriptorsPerRow * ROWS_PER_FRAME * _num_frame_buffers * sizeof(lldesc_t);
|
_dma_linked_list_memory_required = numDMAdescriptorsPerRow * ROWS_PER_FRAME * _num_frame_buffers * sizeof(lldesc_t);
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.printf("Descriptors for lsbMsbTransitionBit %d/%d with %d rows require %d bytes of DMA RAM\r\n", lsbMsbTransitionBit, PIXEL_COLOR_DEPTH_BITS - 1, ROWS_PER_FRAME, _dma_linked_list_memory_required);
|
Serial.printf("Descriptors for lsbMsbTransitionBit of %d/%d with %d frame rows require %d bytes of DMA RAM with %d numDMAdescriptorsPerRow.\r\n", lsbMsbTransitionBit, PIXEL_COLOR_DEPTH_BITS - 1, ROWS_PER_FRAME, _dma_linked_list_memory_required, numDMAdescriptorsPerRow);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_total_dma_capable_memory_reserved += _dma_linked_list_memory_required;
|
_total_dma_capable_memory_reserved += _dma_linked_list_memory_required;
|
||||||
|
@ -279,11 +301,18 @@ void RGB64x32MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_
|
||||||
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.
|
||||||
|
// We also declare a ridiculously long variable as well... row_bit_struct_color_depth_dma_payload_break_point
|
||||||
|
int num_dma_payload_color_depths = PIXEL_COLOR_DEPTH_BITS;
|
||||||
|
if ( sizeof(rowColorDepthStruct) > DMA_MAX ) {
|
||||||
|
num_dma_payload_color_depths = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill DMA linked lists for both frames (as in, halves of the HUB75 panel)
|
/* 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.
|
* .. and if double buffering is enabled, link it up for both buffers.
|
||||||
*/
|
*/
|
||||||
for(int j = 0; j < ROWS_PER_FRAME; j++)
|
for(int j = 0; j < ROWS_PER_FRAME; j++) {
|
||||||
{
|
|
||||||
// Split framebuffer malloc hack 'improvement'
|
// Split framebuffer malloc hack 'improvement'
|
||||||
frameStruct *fb_malloc_ptr = matrix_framebuffer_malloc_1;
|
frameStruct *fb_malloc_ptr = matrix_framebuffer_malloc_1;
|
||||||
int fb_malloc_j = j;
|
int fb_malloc_j = j;
|
||||||
|
@ -298,25 +327,55 @@ void RGB64x32MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// first set of data is LSB through MSB, single pass - all color bits are displayed once, which takes care of everything below and inlcluding LSBMSB_TRANSITION_BIT
|
#if SERIAL_DEBUG
|
||||||
// TODO: size must be less than DMA_MAX - worst case for SmartMatrix Library: 16-bpp with 256 pixels per row would exceed this, need to break into two
|
Serial.printf("DMA payload of %d bytes. DMA_MAX is %d.\r\n", sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS, DMA_MAX);
|
||||||
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, &(fb_malloc_ptr[0].rowdata[fb_malloc_j].rowbits[0].data), sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS);
|
#endif
|
||||||
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
|
||||||
|
|
||||||
|
// 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 inlcluding 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
|
||||||
|
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, &(fb_malloc_ptr[0].rowdata[fb_malloc_j].rowbits[0].data), sizeof(rowBitStruct) * num_dma_payload_color_depths);
|
||||||
|
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
||||||
|
|
||||||
if (double_buffering_enabled) {
|
if (double_buffering_enabled) {
|
||||||
link_dma_desc(&dmadesc_b[current_dmadescriptor_offset], previous_dmadesc_b, &(fb_malloc_ptr[1].rowdata[fb_malloc_j].rowbits[0].data), sizeof(rowBitStruct) * PIXEL_COLOR_DEPTH_BITS);
|
link_dma_desc(&dmadesc_b[current_dmadescriptor_offset], previous_dmadesc_b, &(fb_malloc_ptr[1].rowdata[fb_malloc_j].rowbits[0].data), sizeof(rowBitStruct) * num_dma_payload_color_depths);
|
||||||
previous_dmadesc_b = &dmadesc_b[current_dmadescriptor_offset]; }
|
previous_dmadesc_b = &dmadesc_b[current_dmadescriptor_offset]; }
|
||||||
|
|
||||||
current_dmadescriptor_offset++;
|
current_dmadescriptor_offset++;
|
||||||
|
|
||||||
|
// If the number of pixels per row is to great for the size of a single payload, so we need to split what we were going to send above.
|
||||||
|
if ( sizeof(rowColorDepthStruct) > DMA_MAX ) {
|
||||||
|
|
||||||
|
#if SERIAL_DEBUG
|
||||||
|
Serial.printf("Spliting DMA payload for %d color depths into %d byte payloads.\r\n", PIXEL_COLOR_DEPTH_BITS-1, sizeof(rowBitStruct) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int cd = 1; cd < PIXEL_COLOR_DEPTH_BITS; cd++) {
|
||||||
|
|
||||||
|
// first set of data is LSB through MSB, single pass - all color bits are displayed once, which takes care of everything below and inlcluding LSBMSB_TRANSITION_BIT
|
||||||
|
// TODO: 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, &(fb_malloc_ptr[0].rowdata[fb_malloc_j].rowbits[cd].data), sizeof(rowBitStruct) );
|
||||||
|
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
||||||
|
|
||||||
|
if (double_buffering_enabled) {
|
||||||
|
link_dma_desc(&dmadesc_b[current_dmadescriptor_offset], previous_dmadesc_b, &(fb_malloc_ptr[1].rowdata[fb_malloc_j].rowbits[cd].data), sizeof(rowBitStruct) );
|
||||||
|
previous_dmadesc_b = &dmadesc_b[current_dmadescriptor_offset]; }
|
||||||
|
|
||||||
|
current_dmadescriptor_offset++;
|
||||||
|
} // additional linked list items
|
||||||
|
|
||||||
|
} // row depth struct
|
||||||
|
|
||||||
|
|
||||||
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_DEPTH_BITS; i++) {
|
for(int i=lsbMsbTransitionBit + 1; i<PIXEL_COLOR_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
|
||||||
//Serial.printf("buffer %d: repeat %d times, size: %d, from %d - %d\r\n", current_dmadescriptor_offset, 1<<(i - lsbMsbTransitionBit - 1), (PIXEL_COLOR_DEPTH_BITS - i), i, PIXEL_COLOR_DEPTH_BITS-1);
|
//Serial.printf("buffer %d: repeat %d times, size: %d, from %d - %d\r\n", current_dmadescriptor_offset, 1<<(i - lsbMsbTransitionBit - 1), (PIXEL_COLOR_DEPTH_BITS - i), i, PIXEL_COLOR_DEPTH_BITS-1);
|
||||||
|
|
||||||
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, &(fb_malloc_ptr[0].rowdata[fb_malloc_j].rowbits[i].data), sizeof(rowBitStruct) * (PIXEL_COLOR_DEPTH_BITS - i));
|
link_dma_desc(&dmadesc_a[current_dmadescriptor_offset], previous_dmadesc_a, &(fb_malloc_ptr[0].rowdata[fb_malloc_j].rowbits[i].data), sizeof(rowBitStruct) * (PIXEL_COLOR_DEPTH_BITS - i));
|
||||||
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
previous_dmadesc_a = &dmadesc_a[current_dmadescriptor_offset];
|
||||||
|
|
||||||
|
@ -328,10 +387,11 @@ void RGB64x32MatrixPanel_I2S_DMA::configureDMA(int r1_pin, int g1_pin, int b1_
|
||||||
|
|
||||||
} // end color depth ^ 2 linked list
|
} // end color depth ^ 2 linked list
|
||||||
} // end color depth loop
|
} // end color depth loop
|
||||||
|
|
||||||
} // end frame rows
|
} // end frame rows
|
||||||
|
|
||||||
#if SERIAL_DEBUG
|
#if SERIAL_DEBUG
|
||||||
Serial.println("configureDMA(): Configured LL structure.\r\n");
|
Serial.printf("configureDMA(): Configured LL structure. %d DMA Linked List descriptors populated.\r\n", current_dmadescriptor_offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
dmadesc_a[desccount-1].eof = 1;
|
dmadesc_a[desccount-1].eof = 1;
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#define SPLIT_MEMORY_MODE 1
|
#define SPLIT_MEMORY_MODE 1
|
||||||
|
|
||||||
/* Use GFX_Root (https://github.com/mrfaptastic/GFX_Root) instead of
|
/* Use GFX_Root (https://github.com/mrfaptastic/GFX_Root) instead of
|
||||||
* Adafruit_GFX library. No real benefit unless you don't want Bus_IO library.
|
* Adafruit_GFX library. No real benefit unless you don't want Bus_IO & Wire.h library dependencies.
|
||||||
*/
|
*/
|
||||||
//#define USE_GFX_ROOT 1
|
//#define USE_GFX_ROOT 1
|
||||||
|
|
||||||
|
|
134
ESP32-VirtualMatrixPanel-I2S-DMA.h
Normal file
134
ESP32-VirtualMatrixPanel-I2S-DMA.h
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
#ifndef _ESP32_VIRTUAL_MATRIX_PANEL_I2S_DMA
|
||||||
|
#define _ESP32_VIRTUAL_MATRIX_PANEL_I2S_DMA
|
||||||
|
|
||||||
|
/*******************************************************************
|
||||||
|
Contributed by Brian Lough
|
||||||
|
YouTube: https://www.youtube.com/brianlough
|
||||||
|
Tindie: https://www.tindie.com/stores/brianlough/
|
||||||
|
Twitter: https://twitter.com/witnessmenow
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
#include "ESP32-RGB64x32MatrixPanel-I2S-DMA.h"
|
||||||
|
|
||||||
|
struct VirtualCoords {
|
||||||
|
int16_t x;
|
||||||
|
int16_t y;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_GFX_ROOT
|
||||||
|
class VirtualMatrixPanel : public GFX
|
||||||
|
#else
|
||||||
|
class VirtualMatrixPanel : public Adafruit_GFX
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
int16_t virtualResX;
|
||||||
|
int16_t virtualResY;
|
||||||
|
|
||||||
|
int16_t module_rows;
|
||||||
|
int16_t module_cols;
|
||||||
|
|
||||||
|
int16_t screenResX;
|
||||||
|
int16_t screenResY;
|
||||||
|
|
||||||
|
RGB64x32MatrixPanel_I2S_DMA *display;
|
||||||
|
|
||||||
|
#ifdef USE_GFX_ROOT
|
||||||
|
VirtualMatrixPanel(RGB64x32MatrixPanel_I2S_DMA &disp, int vmodule_rows, int vmodule_cols, int screenX, int screenY)
|
||||||
|
: GFX(vmodule_cols*screenX, vmodule_rows*screenY)
|
||||||
|
#else
|
||||||
|
VirtualMatrixPanel(RGB64x32MatrixPanel_I2S_DMA &disp, int vmodule_rows, int vmodule_cols, int screenX, int screenY)
|
||||||
|
: Adafruit_GFX(vmodule_cols*screenX, vmodule_rows*screenY)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
this->display = &disp;
|
||||||
|
module_rows = vmodule_rows;
|
||||||
|
module_cols = vmodule_cols;
|
||||||
|
screenResX = screenX;
|
||||||
|
screenResY = screenY;
|
||||||
|
|
||||||
|
virtualResX = vmodule_rows*screenY;
|
||||||
|
virtualResY = vmodule_cols*screenX;
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualCoords getCoords(int16_t x, int16_t y);
|
||||||
|
|
||||||
|
// equivalent methods of the matrix library so it can be just swapped out.
|
||||||
|
virtual void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||||
|
virtual void fillScreen(uint16_t color); // overwrite adafruit implementation
|
||||||
|
void clearScreen() {
|
||||||
|
fillScreen(0);
|
||||||
|
}
|
||||||
|
void drawPixelRGB565(int16_t x, int16_t y, uint16_t color);
|
||||||
|
void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
void drawPixelRGB24(int16_t x, int16_t y, rgb_24 color);
|
||||||
|
void drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows);
|
||||||
|
|
||||||
|
uint16_t color444(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
return display->color444(r, g, b);
|
||||||
|
}
|
||||||
|
uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
return display->color565(r, g, b);
|
||||||
|
}
|
||||||
|
uint16_t Color333(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
return display->Color333(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VirtualCoords coords;
|
||||||
|
|
||||||
|
}; // end Class header
|
||||||
|
|
||||||
|
inline VirtualCoords VirtualMatrixPanel::getCoords(int16_t x, int16_t y) {
|
||||||
|
int16_t xOffset = (y / screenResY) * (module_cols * screenResX);
|
||||||
|
coords.x = x + xOffset;
|
||||||
|
coords.y = y % screenResY;
|
||||||
|
return coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VirtualMatrixPanel::drawPixel(int16_t x, int16_t y, uint16_t color)
|
||||||
|
{
|
||||||
|
VirtualCoords coords = getCoords(x, y);
|
||||||
|
this->display->drawPixel(coords.x, coords.y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VirtualMatrixPanel::fillScreen(uint16_t color) // adafruit virtual void override
|
||||||
|
{
|
||||||
|
// No need to map this.
|
||||||
|
this->display->fillScreen(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VirtualMatrixPanel::drawPixelRGB565(int16_t x, int16_t y, uint16_t color)
|
||||||
|
{
|
||||||
|
VirtualCoords coords = getCoords(x, y);
|
||||||
|
this->display->drawPixelRGB565( coords.x, coords.y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void VirtualMatrixPanel::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
{
|
||||||
|
VirtualCoords coords = getCoords(x, y);
|
||||||
|
this->display->drawPixelRGB888( coords.x, coords.y, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void VirtualMatrixPanel::drawPixelRGB24(int16_t x, int16_t y, rgb_24 color)
|
||||||
|
{
|
||||||
|
VirtualCoords coords = getCoords(x, y);
|
||||||
|
this->display->drawPixelRGB24(coords.x, coords.y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to recreate this one, as it wouldnt work to just map where it starts.
|
||||||
|
inline void VirtualMatrixPanel::drawIcon (int *ico, int16_t x, int16_t y, int16_t module_cols, int16_t module_rows) {
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < module_rows; i++) {
|
||||||
|
for (j = 0; j < module_cols; j++) {
|
||||||
|
// This is a call to this libraries version of drawPixel
|
||||||
|
// which will map each pixel, which is what we want.
|
||||||
|
drawPixelRGB565 (x + j, y + i, ico[i * module_cols + j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -32,8 +32,6 @@
|
||||||
//#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;
|
||||||
|
@ -106,7 +104,8 @@ static void fill_dma_desc(volatile lldesc_t *dmadesc, i2s_parallel_buffer_desc_t
|
||||||
|
|
||||||
// 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
|
// 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;
|
||||||
|
|
||||||
dmadesc->size = size;
|
dmadesc->size = size;
|
||||||
|
|
|
@ -12,6 +12,9 @@ extern "C" {
|
||||||
#include "soc/i2s_struct.h"
|
#include "soc/i2s_struct.h"
|
||||||
#include "rom/lldesc.h"
|
#include "rom/lldesc.h"
|
||||||
|
|
||||||
|
#define DMA_MAX (4096-4)
|
||||||
|
//#define DMA_MAX (512)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2S_PARALLEL_BITS_8=8,
|
I2S_PARALLEL_BITS_8=8,
|
||||||
I2S_PARALLEL_BITS_16=16,
|
I2S_PARALLEL_BITS_16=16,
|
||||||
|
|
Loading…
Reference in a new issue