PSRAM works now on ESP32-S3

But it's pointless to use as the throughput can only be about 10Mhz.
This commit is contained in:
mrfaptastic 2022-11-17 00:45:40 +00:00
parent f47b7f5723
commit dd15dabf16
5 changed files with 78 additions and 11 deletions

View file

@ -1,5 +1,11 @@
#include "ESP32-HUB75-MatrixPanel-I2S-DMA.h" #include "ESP32-HUB75-MatrixPanel-I2S-DMA.h"
#if defined(SPIRAM_DMA_BUFFER)
// Sprite_TM saves the day again...
// https://www.esp32.com/viewtopic.php?f=2&t=30584
#include "rom/cache.h"
#endif
static const char* TAG = "MatrixPanel"; static const char* TAG = "MatrixPanel";
/* This replicates same function in rowBitStruct, but due to induced inlining it might be MUCH faster /* This replicates same function in rowBitStruct, but due to induced inlining it might be MUCH faster
@ -249,6 +255,10 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
bus_cfg.pin_d14 = -1; bus_cfg.pin_d14 = -1;
bus_cfg.pin_d15 = -1; bus_cfg.pin_d15 = -1;
#if defined(SPIRAM_DMA_BUFFER)
bus_cfg.psram_clk_hack = true;
#endif
dma_bus.config(bus_cfg); dma_bus.config(bus_cfg);
dma_bus.init(); dma_bus.init();
@ -368,6 +378,10 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint16_t x_coord, uint
p[x_coord] &= _colourbitclear; // 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
#if defined(SPIRAM_DMA_BUFFER)
Cache_WriteBack_Addr((uint32_t)&p[x_coord], sizeof(ESP32_I2S_DMA_STORAGE_TYPE)) ;
#endif
} while(colour_depth_idx); // end of colour depth loop (8) } while(colour_depth_idx); // end of colour depth loop (8)
} // updateMatrixDMABuffer (specific co-ords change) } // updateMatrixDMABuffer (specific co-ords change)
@ -424,6 +438,12 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
--x_coord; --x_coord;
p[x_coord] &= BITMASK_RGB12_CLEAR; // reset colour bits p[x_coord] &= BITMASK_RGB12_CLEAR; // reset colour bits
p[x_coord] |= RGB_output_bits; // set new colour bits p[x_coord] |= RGB_output_bits; // set new colour bits
#if defined(SPIRAM_DMA_BUFFER)
Cache_WriteBack_Addr((uint32_t)&p[x_coord], sizeof(ESP32_I2S_DMA_STORAGE_TYPE)) ;
#endif
} while(x_coord); } while(x_coord);
} while(matrix_frame_parallel_row); // end row iteration } while(matrix_frame_parallel_row); // end row iteration
@ -557,6 +577,13 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
} while(colouridx); } while(colouridx);
#if defined(SPIRAM_DMA_BUFFER)
Cache_WriteBack_Addr((uint32_t)row, sizeof(ESP32_I2S_DMA_STORAGE_TYPE) * ((dma_buff.rowBits[row_idx]->width * dma_buff.rowBits[row_idx]->colour_depth)-1)) ;
#endif
} while(row_idx); } while(row_idx);
} }
@ -630,6 +657,7 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
*/ */
row[ESP32_TX_FIFO_POSITION_ADJUST(0 + _blank)] |= BIT_OE; row[ESP32_TX_FIFO_POSITION_ADJUST(0 + _blank)] |= BIT_OE;
//row[0 + _blank] |= BIT_OE; //row[0 + _blank] |= BIT_OE;
@ -638,6 +666,14 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
} while (_blank); } while (_blank);
} while(colouridx); } while(colouridx);
// switch pointer to a row for a specific color index
#if defined(SPIRAM_DMA_BUFFER)
ESP32_I2S_DMA_STORAGE_TYPE* row_hack = dma_buff.rowBits[row_idx]->getDataPtr(colouridx, _buff_id);
Cache_WriteBack_Addr((uint32_t)row_hack, sizeof(ESP32_I2S_DMA_STORAGE_TYPE) * ((dma_buff.rowBits[row_idx]->width * dma_buff.rowBits[row_idx]->colour_depth)-1)) ;
#endif
} while(row_idx); } while(row_idx);
} }

View file

@ -142,9 +142,12 @@ struct rowBitStruct {
// 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), colour_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) && defined (CONFIG_IDF_TARGET_ESP32S3) //#if defined(SPIRAM_FRAMEBUFFER) && defined (CONFIG_IDF_TARGET_ESP32S3)
#pragma message "Enabling PSRAM / SPIRAM for frame buffer." #if defined(SPIRAM_DMA_BUFFER)
data = (ESP32_I2S_DMA_STORAGE_TYPE *)heap_caps_malloc( size()+size()*double_buff, MALLOC_CAP_SPIRAM); // #pragma message "Enabling PSRAM / SPIRAM for frame buffer."
// ESP_LOGI("rowBitStruct", "Allocated DMA BitBuffer from PSRAM (SPIRAM)");
//data = (ESP32_I2S_DMA_STORAGE_TYPE *)heap_caps_malloc( size()+size()*double_buff, MALLOC_CAP_SPIRAM);
data = (ESP32_I2S_DMA_STORAGE_TYPE *)heap_caps_aligned_alloc(64, size()+size()*double_buff, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
/* /*
if (!psramFound()) if (!psramFound())
{ {
@ -153,6 +156,7 @@ struct rowBitStruct {
*/ */
#else #else
data = (ESP32_I2S_DMA_STORAGE_TYPE *)heap_caps_malloc( size()+size()*double_buff, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA); data = (ESP32_I2S_DMA_STORAGE_TYPE *)heap_caps_malloc( size()+size()*double_buff, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
// ESP_LOGI("rowBitStruct", "Allocated DMA BitBuffer from regular (and limited) SRAM");
#endif #endif
} }

View file

@ -79,9 +79,12 @@
LCD_CAM.lcd_user.lcd_reset = 1; LCD_CAM.lcd_user.lcd_reset = 1;
esp_rom_delay_us(100); esp_rom_delay_us(100);
uint32_t lcd_clkm_div_num = ((160000000 + 1) / _cfg.bus_freq) / 2; // uint32_t lcd_clkm_div_num = ((160000000 + 1) / _cfg.bus_freq);
ESP_LOGI(TAG, "Cpu frequecny is %d", getCpuFrequencyMhz());
ESP_LOGI(TAG, "Clock divider is %d", lcd_clkm_div_num); uint32_t lcd_clkm_div_num = ( ((getCpuFrequencyMhz()*1000000)+1) / _cfg.bus_freq ) / 4;
//ESP_LOGI(TAG, "Clock divider is %d", lcd_clkm_div_num);
// Configure LCD clock. Since this program generates human-perceptible // Configure LCD clock. Since this program generates human-perceptible
// output and not data for LED matrices or NeoPixels, use almost the // output and not data for LED matrices or NeoPixels, use almost the
@ -90,12 +93,27 @@
// is applied (250*64), yielding 2,500 Hz. Still much too fast for // is applied (250*64), yielding 2,500 Hz. Still much too fast for
// human eyes, so later we set up the data to repeat each output byte // human eyes, so later we set up the data to repeat each output byte
// many times over. // many times over.
LCD_CAM.lcd_clock.clk_en = 1; // Enable peripheral clock //LCD_CAM.lcd_clock.clk_en = 0; // Enable peripheral clock
LCD_CAM.lcd_clock.lcd_clk_sel = 2; // 160mhz source
// LCD_CAM_LCD_CLK_SEL Select LCD module source clock. 0: clock source is disabled. 1: XTAL_CLK. 2: PLL_D2_CLK. 3: PLL_F160M_CLK. (R/W)
LCD_CAM.lcd_clock.lcd_clk_sel = 2;
LCD_CAM.lcd_clock.lcd_ck_out_edge = 0; // PCLK low in 1st half cycle LCD_CAM.lcd_clock.lcd_ck_out_edge = 0; // PCLK low in 1st half cycle
LCD_CAM.lcd_clock.lcd_ck_idle_edge = 0; // PCLK low idle LCD_CAM.lcd_clock.lcd_ck_idle_edge = 0; // PCLK low idle
LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 0; // PCLK = CLK / (CLKCNT_N+1) LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 0; // PCLK = CLK / (CLKCNT_N+1)
LCD_CAM.lcd_clock.lcd_clkm_div_num = lcd_clkm_div_num; // 1st stage 1:250 divide
if (_cfg.psram_clk_hack) // fastest speed I can get PSRAM to work before nothing shows
{
LCD_CAM.lcd_clock.lcd_clkm_div_num = 4;
}
else
{
//LCD_CAM.lcd_clock.lcd_clkm_div_num = lcd_clkm_div_num;
LCD_CAM.lcd_clock.lcd_clkm_div_num = 3;
}
ESP_LOGI(TAG, "Clock divider is %d", LCD_CAM.lcd_clock.lcd_clkm_div_num);
LCD_CAM.lcd_clock.lcd_clkm_div_a = 1; // 0/1 fractional divide LCD_CAM.lcd_clock.lcd_clkm_div_a = 1; // 0/1 fractional divide
LCD_CAM.lcd_clock.lcd_clkm_div_b = 0; LCD_CAM.lcd_clock.lcd_clkm_div_b = 0;
@ -194,8 +212,8 @@
gdma_apply_strategy(dma_chan, &strategy_config); gdma_apply_strategy(dma_chan, &strategy_config);
gdma_transfer_ability_t ability = { gdma_transfer_ability_t ability = {
.sram_trans_align = 0, .sram_trans_align = 4,
.psram_trans_align = 0, .psram_trans_align = 64,
}; };
gdma_set_transfer_ability(dma_chan, &ability); gdma_set_transfer_ability(dma_chan, &ability);

View file

@ -101,11 +101,12 @@
//int port = 0; //int port = 0;
// max 40MHz (when in 16 bit / 2 byte mode) // max 40MHz (when in 16 bit / 2 byte mode)
uint32_t bus_freq = 20000000; uint32_t bus_freq = 10000000;
int8_t pin_wr = -1; int8_t pin_wr = -1;
int8_t pin_rd = -1; int8_t pin_rd = -1;
int8_t pin_rs = -1; // D/C int8_t pin_rs = -1; // D/C
bool invert_pclk = false; bool invert_pclk = false;
bool psram_clk_hack = false;
union union
{ {
int8_t pin_data[16]; int8_t pin_data[16];

View file

@ -39,6 +39,14 @@ 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"
#if defined(SPIRAM_FRAMEBUFFER) && defined (CONFIG_IDF_TARGET_ESP32S3)
#pragma message "Enabling use of PSRAM/SPIRAM based DMA Buffer"
#define SPIRAM_DMA_BUFFER 1
// Disable fast functions because I don't understand the interaction with DMA PSRAM and the CPU->DMA->SPIRAM Cache implications..
#define NO_FAST_FUNCTIONS 1
#endif
#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2) #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32H2)
#error "ESP32 RISC-V devices do not have an LCD interface and are therefore not supported by this library." #error "ESP32 RISC-V devices do not have an LCD interface and are therefore not supported by this library."