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"
#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";
/* 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_d15 = -1;
#if defined(SPIRAM_DMA_BUFFER)
bus_cfg.psram_clk_hack = true;
#endif
dma_bus.config(bus_cfg);
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] |= 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)
} // updateMatrixDMABuffer (specific co-ords change)
@ -424,6 +438,12 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
--x_coord;
p[x_coord] &= BITMASK_RGB12_CLEAR; // reset 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(matrix_frame_parallel_row); // end row iteration
@ -557,6 +577,13 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
} 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);
}
@ -632,12 +659,21 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
row[ESP32_TX_FIFO_POSITION_ADJUST(0 + _blank)] |= BIT_OE;
//row[0 + _blank] |= BIT_OE;
// no need, has been done already
//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(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);
}

View file

@ -142,9 +142,12 @@ struct rowBitStruct {
// 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) {
#if defined(SPIRAM_FRAMEBUFFER) && defined (CONFIG_IDF_TARGET_ESP32S3)
#pragma message "Enabling PSRAM / SPIRAM for frame buffer."
data = (ESP32_I2S_DMA_STORAGE_TYPE *)heap_caps_malloc( size()+size()*double_buff, MALLOC_CAP_SPIRAM);
//#if defined(SPIRAM_FRAMEBUFFER) && defined (CONFIG_IDF_TARGET_ESP32S3)
#if defined(SPIRAM_DMA_BUFFER)
// #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())
{
@ -153,6 +156,7 @@ struct rowBitStruct {
*/
#else
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
}

View file

@ -79,9 +79,12 @@
LCD_CAM.lcd_user.lcd_reset = 1;
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
// 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
// human eyes, so later we set up the data to repeat each output byte
// many times over.
LCD_CAM.lcd_clock.clk_en = 1; // Enable peripheral clock
LCD_CAM.lcd_clock.lcd_clk_sel = 2; // 160mhz source
//LCD_CAM.lcd_clock.clk_en = 0; // Enable peripheral clock
// 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_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_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_b = 0;
@ -194,8 +212,8 @@
gdma_apply_strategy(dma_chan, &strategy_config);
gdma_transfer_ability_t ability = {
.sram_trans_align = 0,
.psram_trans_align = 0,
.sram_trans_align = 4,
.psram_trans_align = 64,
};
gdma_set_transfer_ability(dma_chan, &ability);

View file

@ -101,11 +101,12 @@
//int port = 0;
// 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_rd = -1;
int8_t pin_rs = -1; // D/C
bool invert_pclk = false;
bool psram_clk_hack = false;
union
{
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/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)
#error "ESP32 RISC-V devices do not have an LCD interface and are therefore not supported by this library."