diff --git a/src/platforms/esp32s3/gdma_lcd_parallel16.cpp b/src/platforms/esp32s3/gdma_lcd_parallel16.cpp index ddd9243..d064210 100644 --- a/src/platforms/esp32s3/gdma_lcd_parallel16.cpp +++ b/src/platforms/esp32s3/gdma_lcd_parallel16.cpp @@ -38,7 +38,7 @@ // End-of-DMA-transfer callback IRAM_ATTR bool gdma_on_trans_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data) { - + // This DMA callback seems to trigger a moment before the last data has // issued (buffering between DMA & LCD peripheral?), so pause a moment // before stopping LCD data out. The ideal delay may depend on the LCD @@ -51,9 +51,9 @@ // the next transfer. //LCD_CAM.lcd_user.lcd_start = 0; - - previousBufferFree = true; - + + previousBufferFree = true; + return true; } @@ -99,47 +99,47 @@ // 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 = 3; // Use 160Mhz Clock Source - + 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_clkcnt_n = 1; // Should never be zero - - //LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 0; // PCLK = CLK / (CLKCNT_N+1) - LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 1; // PCLK = CLK / 1 (... so 160Mhz still) + + LCD_CAM.lcd_clock.lcd_clkcnt_n = 1; // Should never be zero + + //LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 0; // PCLK = CLK / (CLKCNT_N+1) + LCD_CAM.lcd_clock.lcd_clk_equ_sysclk = 1; // PCLK = CLK / 1 (... so 160Mhz still) - // https://esp32.com/viewtopic.php?f=5&t=24459&start=80#p94487 - /* Re: ESP32-S3 LCD and I2S FULL documentation - * by ESP_Sprite » Fri Mar 25, 2022 2:06 am + // https://esp32.com/viewtopic.php?f=5&t=24459&start=80#p94487 + /* Re: ESP32-S3 LCD and I2S FULL documentation + * by ESP_Sprite » Fri Mar 25, 2022 2:06 am * * Are you sure you are staying within the limits of the psram throughput? If GDMA can't fetch data fast - * enough it leads to corruption. Also keep in mind that worst case scenario, the gdma can only use half of - * the bandwidth of the psram peripheral (as it's round-robin shared with the CPUs). - */ - - // Fastest speed I can get with Octoal PSRAM to work before nothing shows. Based on manual testing. - // If using an ESP32-S3 with slower (half the bandwidth) Q-SPI (Quad), then the divisor will need to be '20' (8Mhz) which wil be flickery! + * enough it leads to corruption. Also keep in mind that worst case scenario, the gdma can only use half of + * the bandwidth of the psram peripheral (as it's round-robin shared with the CPUs). + */ + + // Fastest speed I can get with Octoal PSRAM to work before nothing shows. Based on manual testing. + // If using an ESP32-S3 with slower (half the bandwidth) Q-SPI (Quad), then the divisor will need to be '20' (8Mhz) which wil be flickery! if (_cfg.psram_clk_override) { ESP_LOGI("S3", "DMA buffer is on PSRAM. Limiting clockspeed...."); //LCD_CAM.lcd_clock.lcd_clkm_div_num = 10; //16mhz is the fasted the Octal PSRAM can support it seems from faptastic's testing using an N8R8 variant (Octal SPI PSRAM). - - // https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/issues/441#issuecomment-1513631890 - LCD_CAM.lcd_clock.lcd_clkm_div_num = 12; // 13Mhz is the fastest when the DMA memory is needed to service other peripherals as well. + + // https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/issues/441#issuecomment-1513631890 + LCD_CAM.lcd_clock.lcd_clkm_div_num = 12; // 13Mhz is the fastest when the DMA memory is needed to service other peripherals as well. } else { - auto freq = (_cfg.bus_freq); + auto freq = (_cfg.bus_freq); - auto _div_num = 8; // 20Mhz - if (freq < 20000000L) { - _div_num = 12; // 13Mhz - } - else if (freq > 20000000L) { - _div_num = 6; // 26Mhz --- likely to have noise without a good connection - } + auto _div_num = 8; // 20Mhz + if (freq < 20000000L) { + _div_num = 12; // 13Mhz + } + else if (freq > 20000000L) { + _div_num = 6; // 26Mhz --- likely to have noise without a good connection + } //LCD_CAM.lcd_clock.lcd_clkm_div_num = lcd_clkm_div_num; LCD_CAM.lcd_clock.lcd_clkm_div_num = _div_num; //3; @@ -163,8 +163,8 @@ LCD_CAM.lcd_rgb_yuv.lcd_conv_bypass = 0; // Disable RGB/YUV converter LCD_CAM.lcd_misc.lcd_next_frame_en = 0; // Do NOT auto-frame - LCD_CAM.lcd_misc.lcd_bk_en = 1; // https://esp32.com/viewtopic.php?t=24459&start=60#p91835 - + LCD_CAM.lcd_misc.lcd_bk_en = 1; // https://esp32.com/viewtopic.php?t=24459&start=60#p91835 + LCD_CAM.lcd_data_dout_mode.val = 0; // No data delays LCD_CAM.lcd_user.lcd_always_out_en = 1; // Enable 'always out' mode LCD_CAM.lcd_user.lcd_8bits_order = 0; // Do not swap bytes @@ -259,7 +259,7 @@ // Enable DMA transfer callback static gdma_tx_event_callbacks_t tx_cbs = { - // .on_trans_eof is literally the only gdma tx event type available + // .on_trans_eof is literally the only gdma tx event type available .on_trans_eof = gdma_on_trans_eof_callback }; gdma_register_tx_event_callbacks(dma_chan, &tx_cbs, NULL); @@ -274,9 +274,9 @@ // a clean start on the next LCD transfer: gdma_reset(dma_chan); // Reset DMA to known state esp_rom_delay_us(1000); - - LCD_CAM.lcd_user.lcd_dout = 1; // Enable data out - LCD_CAM.lcd_user.lcd_update = 1; // Update registers + + LCD_CAM.lcd_user.lcd_dout = 1; // Enable data out + LCD_CAM.lcd_user.lcd_update = 1; // Update registers LCD_CAM.lcd_misc.lcd_afifo_reset = 1; // Reset LCD TX FIFO @@ -353,8 +353,8 @@ { _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 = (_dmadesc_b_idx == (_dmadesc_count-1)); + //_dmadesc_b[_dmadesc_b_idx].dw0.suc_eof = 0; + _dmadesc_b[_dmadesc_b_idx].dw0.suc_eof = (_dmadesc_b_idx == (_dmadesc_count-1)); _dmadesc_b[_dmadesc_b_idx].dw0.size = _dmadesc_b[_dmadesc_b_idx].dw0.length = size; //sizeof(data); _dmadesc_b[_dmadesc_b_idx].buffer = data; //data; @@ -371,7 +371,7 @@ } else { - + if ( _dmadesc_a_idx >= _dmadesc_count) { ESP_LOGE("S3", "Attempted to create more DMA descriptors than allocated. Expecting max %" PRIu32 " descriptors.", _dmadesc_count); @@ -380,7 +380,7 @@ _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 = (_dmadesc_a_idx == (_dmadesc_count-1)); + _dmadesc_a[_dmadesc_a_idx].dw0.suc_eof = (_dmadesc_a_idx == (_dmadesc_count-1)); _dmadesc_a[_dmadesc_a_idx].dw0.size = _dmadesc_a[_dmadesc_a_idx].dw0.length = size; //sizeof(data); _dmadesc_a[_dmadesc_a_idx].buffer = data; //data; @@ -434,13 +434,13 @@ } //current_back_buffer_id ^= 1; - + previousBufferFree = false; - + //while (i2s_parallel_is_previous_buffer_free() == false) {} while (!previousBufferFree); - + } // end flip