-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Description
Board
WaveShare ESP32-P4-WIFI6-DEV-KIT
Device Description
Plain board as in LINK
Hardware Configuration
Home made hat on IO headers pins with a ladder converter to connect a VGA monitor
(see LINK)
EasyEDA pro file : LINK
Version
v3.3.7
Type
Bug
IDE Name
Arduino IDE 2.3.8
Operating System
macOS 26.3
Flash frequency
80 MHz
PSRAM enabled
yes
Upload speed
921600
Description
Framebuffer not displayed correctly (see LINK for detailled explanation)
It seems that the LCD_DE signal is not in sync with the LCD_Data_out[15:0] and start 8 LCD_PCLK after the beginning of the the PixelValidData window (see fig 36.3-5 of the esp32-p4-chip-revision-v1.3_technical_reference_manual_en.pdf)
The bug can also come from a DMA synchronization problem as the firsts 8 pixels of the first line displayed are not random ... see pictures at LINK
(top half got the defect as the frame buffer address is computer as it should be..., bottom half is ok, by adding an offset of -8 pixels when computing the frame buffer address)
Incidently there is also a banding effect on the red channel ... but this perhaps a bug in my hat
Sketch
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_rgb.h"
#include "driver/gpio.h"
#include <esp_cache.h>
#define SCREEN_WIDTH 800
#if SCREEN_WIDTH == 800
#define SCREEN_HEIGHT 600
// good for SAMSUNG 213T 800x600 @ 56Hz
#define VIDEO_LCD_PIXEL_CLOCK_HZ (36000000)
#define VIDEO_CLK_SRC LCD_CLK_SRC_APLL
#define VIDEO_LCD_H_RES 800
#define VIDEO_LCD_V_RES 600
#define VIDEO_LCD_HFP 32
#define VIDEO_LCD_HSYNC 96
#define VIDEO_LCD_HBP 96
#define VIDEO_LCD_VFP 1
#define VIDEO_LCD_VSYNC 4
#define VIDEO_LCD_VBP 19
#define VIDEO_LCD_HSP true
#define VIDEO_LCD_VSP false
#define LCD_NUM_FB 1
#endif
#if SCREEN_WIDTH == 640
#define SCREEN_HEIGHT 480
// good one
#define VIDEO_LCD_PIXEL_CLOCK_HZ (26666666)
#define VIDEO_CLK_SRC LCD_CLK_SRC_PLL160M
#define VIDEO_LCD_H_RES 640
#define VIDEO_LCD_V_RES 480
#define VIDEO_LCD_HFP 24
#define VIDEO_LCD_HSYNC 40
#define VIDEO_LCD_HBP 128
#define VIDEO_LCD_VFP 11
#define VIDEO_LCD_VSYNC 3
#define VIDEO_LCD_VBP 25
#define VIDEO_LCD_HSP false
#define VIDEO_LCD_VSP false
#define LCD_NUM_FB 1
#endif
#define PIN_NUM_HSYNC 27
#define PIN_NUM_VSYNC 23
#define PIN_NUM_DE -1
#define PIN_NUM_PCLK -1
// RED 7 to 3
#define PIN_NUM_DATA0 33
#define PIN_NUM_DATA1 26
#define PIN_NUM_DATA2 48
#define PIN_NUM_DATA3 47
#define PIN_NUM_DATA4 46
// GREEN 7 to 2
#define PIN_NUM_DATA5 1
#define PIN_NUM_DATA6 36
#define PIN_NUM_DATA7 32
#define PIN_NUM_DATA8 0
#define PIN_NUM_DATA9 2
#define PIN_NUM_DATA10 3
// BLUE 7 to 3
#define PIN_NUM_DATA11 22
#define PIN_NUM_DATA12 5
#define PIN_NUM_DATA13 4
#define PIN_NUM_DATA14 20
#define PIN_NUM_DATA15 21
#undef COL16
#define COL16
#ifdef COL16
#define VIDEO_DATA_BUS_WIDTH 16
#define VIDEO_PIXEL_SIZE 2
#define VIDEO_LCD_DATA_LINES 16
#undef VIDEO_LCD_DATA_LINES_24
#define VIDEO_LCD_DATA_LINES_16
#undef VIDEO_LCD_DATA_LINES_24
#else
#define VIDEO_DATA_BUS_WIDTH 8
#define VIDEO_PIXEL_SIZE 1
#define VIDEO_LCD_DATA_LINES 8
#define VIDEO_LCD_DATA_LINES_8
#undef VIDEO_LCD_DATA_LINES_16
#undef VIDEO_LCD_DATA_LINES_24
#endif
#include "esp_clk_tree.h"
#include "hal/clk_tree_ll.h"
uint8_t charmap[] = {
0b00000000,
0b01111100,
0b10000110,
0b10001010,
0b10010010,
0b10100010,
0b11000010,
0b01111100,
0b00000000,
0b00000000,
0b00000000,
0b00010000,
0b00110000,
0b01010000,
0b10010000,
0b00010000,
0b00010000,
0b11111110,
0b00000000,
0b00000000,
0b00000000,
0b01111100,
0b10000010,
0b00000100,
0b00001000,
0b00010000,
0b00100000,
0b11111110,
0b00000000,
0b00000000,
0b00000000,
0b01111100,
0b10000010,
0b00000010,
0b00001100,
0b00000010,
0b10000010,
0b01111100,
0b00000000,
0b00000000,
0b00000000,
0b10001000,
0b10001000,
0b10001000,
0b11111110,
0b00001000,
0b00001000,
0b00001000,
0b00000000,
0b00000000,
0b00000000,
0b11111110,
0b10000000,
0b10000000,
0b01111100,
0b00000010,
0b00000010,
0b11111100,
0b00000000,
0b00000000,
0b00000000,
0b01111110,
0b10000000,
0b10000000,
0b11111100,
0b10000010,
0b10000010,
0b01111100,
0b00000000,
0b00000000,
0b00000000,
0b11111110,
0b00000010,
0b00000100,
0b00001000,
0b00010000,
0b00010000,
0b00010000,
0b00000000,
0b00000000,
0b00000000,
0b01111100,
0b10000010,
0b10000010,
0b01111100,
0b10000010,
0b10000010,
0b01111100,
0b00000000,
0b00000000,
0b00000000,
0b01111100,
0b10000010,
0b10000010,
0b01111110,
0b00000010,
0b00000010,
0b11111100,
0b00000000,
0b00000000,
};
void *p4_frame_buffer = NULL;
bool videoInitWaveP4(void) {
esp_err_t err;
printf("Install RGB LCD panel driver\n");
esp_lcd_panel_handle_t panel_handle = NULL;
esp_lcd_rgb_panel_config_t panel_config = {
.clk_src = VIDEO_CLK_SRC,
// LCD_CLK_SRC_APLL
// LCD_CLK_SRC_DEFAULT
// LCD_CLK_SRC_PLL160M
.timings = {
.pclk_hz = VIDEO_LCD_PIXEL_CLOCK_HZ,
.h_res = VIDEO_LCD_H_RES,
.v_res = VIDEO_LCD_V_RES,
.hsync_pulse_width = VIDEO_LCD_HSYNC,
.hsync_back_porch = VIDEO_LCD_HBP,
.hsync_front_porch = VIDEO_LCD_HFP,
.vsync_pulse_width = VIDEO_LCD_VSYNC,
.vsync_back_porch = VIDEO_LCD_VBP,
.vsync_front_porch = VIDEO_LCD_VFP,
.flags = {
.hsync_idle_low = VIDEO_LCD_HSP,
.vsync_idle_low = VIDEO_LCD_VSP,
.de_idle_high = false,
.pclk_active_neg = true,
.pclk_idle_high = false,
},
},
.data_width = VIDEO_DATA_BUS_WIDTH,
.bits_per_pixel = 0,
.num_fbs = LCD_NUM_FB,
.bounce_buffer_size_px = 0,
.dma_burst_size = 64,
.hsync_gpio_num = PIN_NUM_HSYNC,
.vsync_gpio_num = PIN_NUM_VSYNC,
.de_gpio_num = PIN_NUM_DE,
.pclk_gpio_num = PIN_NUM_PCLK,
.disp_gpio_num = -1,
.data_gpio_nums = {
#ifdef COL16
// high byte
PIN_NUM_DATA6, // GREEN 6 bit 0
PIN_NUM_DATA5, // GREEN 7 bit 1
PIN_NUM_DATA4, // RED 3 bit 2
PIN_NUM_DATA3, // RED 4 bit 3
PIN_NUM_DATA2, // RED 5 bit 4
PIN_NUM_DATA1, // RED 6 bit 5
PIN_NUM_DATA0, // RED 7 bit 6
PIN_NUM_DATA10, // GREEN2 DO NOT SET in framebuffer, needed to avoid banding in red ? not sure, perhaps hat is deficient
// low byte
PIN_NUM_DATA15, // BLUE 3 bit 0
PIN_NUM_DATA14, // BLUE 4 bit 1
PIN_NUM_DATA13, // BLUE 5 bit 2
PIN_NUM_DATA12, // BLUE 6 bit 3
PIN_NUM_DATA11, // BLUE 7 bit 4
PIN_NUM_DATA9, // GREEN 3 bit 5
PIN_NUM_DATA8, // GREEN 4 bit 6
PIN_NUM_DATA7, // GREEN 5 bit 7
#else
PIN_NUM_DATA12, // BLUE6
PIN_NUM_DATA11, // BLUE7
PIN_NUM_DATA7, // GREEN5
PIN_NUM_DATA6, // GREEN6
PIN_NUM_DATA5, // GREEN7
PIN_NUM_DATA2, // RED5
PIN_NUM_DATA1, // RED6
PIN_NUM_DATA0 // RED7
#endif
},
.flags = {
.disp_active_low = false,
.refresh_on_demand = false,
.fb_in_psram = true, // allocate frame buffer in PSRAM
.double_fb = false,
.no_fb = false,
.bb_invalidate_cache = true,
},
};
#if VIDEO_CLK_SRC == LCD_CLK_SRC_APLL
uint32_t freq = 0;
clk_ll_apll_enable();
err = esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_APLL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &freq);
printf("Get APLL freq %d Hz\n", freq);
// apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2)
// apll_freq = 40MHz * (4+4+0+0)/(0+2)*2 = 80 MHz
uint32_t o_div; // Frequency divider, 0..31
uint32_t sdm0; // Frequency adjustment parameter, 0..255
uint32_t sdm1; // Frequency adjustment parameter, 0..255
uint32_t sdm2; // Frequency adjustment parameter, 0..63
clk_ll_apll_get_config(&o_div, &sdm0, &sdm1, &sdm2);
printf("Got APLL config div: %d sdm0: %d sdm1: %d sdm2: %d\n", o_div, sdm0, sdm1, sdm2);
o_div = 3;
sdm0 = 0;
sdm1 = 0;
sdm2 = 14;
printf("Set APLL config to div: %d sdm0: %d sdm1: %d sdm2: %d\n", o_div, sdm0, sdm1, sdm2);
clk_ll_apll_set_config(o_div, sdm0, sdm1, sdm2);
clk_ll_apll_get_config(&o_div, &sdm0, &sdm1, &sdm2);
printf("Got APLL config div: %d sdm0: %d sdm1: %d sdm2: %d\n", o_div, sdm0, sdm1, sdm2);
printf("APLL enabled\n");
// printf("APLL Calibration ...");
// clk_ll_apll_set_calibration();
// while (!clk_ll_apll_calibration_is_done()) {
// delay(100);
// };
// printf(" done!!\n");
err = esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_APLL, ESP_CLK_TREE_SRC_FREQ_PRECISION_EXACT, &freq);
printf("APLL freq now %d Hz\n", freq);
#endif
printf("Create RGB LCD panel ");
err = esp_lcd_new_rgb_panel(&panel_config, &panel_handle);
printf("%d\n", err);
printf("Reset RGB LCD panel ");
err = esp_lcd_panel_reset(panel_handle);
printf("%d\n", err);
delay(100);
printf("Init RGB LCD panel ");
err = esp_lcd_panel_init(panel_handle);
printf("%d\n", err);
printf("Get FB RGB LCD panel ");
err = esp_lcd_rgb_panel_get_frame_buffer(panel_handle, 1, (void **)&p4_frame_buffer);
printf("%d FB at %08X\n", err, p4_frame_buffer);
printf("Initialize RGB LCD panel Done\n");
memset(p4_frame_buffer, 0x00, VIDEO_LCD_H_RES*VIDEO_LCD_V_RES*VIDEO_PIXEL_SIZE);
// sync caches on vsync to ensure good display by the DMA
esp_cache_msync(p4_frame_buffer, (VIDEO_LCD_H_RES*VIDEO_LCD_V_RES*VIDEO_PIXEL_SIZE + 0x3F) & 0xFFFFC0, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
return true;
}
uint16_t rgb888_to_rgb565(uint16_t r, uint16_t g, uint16_t b) {
// uint16_t col = (uint16_t)(r & 0xF8) << 7;
// col += (uint16_t)(g >> 3) << 5;
// col += (uint16_t)(b >> 3) << 0;
// return (col >> 8) | ((col & 0xFF) << 8);
// return (b >> 3) | ((g >> 3) << 5) | ((r >> 3) << 10);
return (g >> 6) | ((r >> 3) << 2) | (((b >> 3) | (g >> 3) << 5) << 8);
// return (g >> 6) | ((r & 0xF8) >> 1) | (((b >> 3) | (g & 0x38) << 2) << 8);
}
void displayat(int x, int y, int v, uint16_t col0, uint16_t col1) {
uint16_t *pos1;
uint16_t *pos2;
if (y < (SCREEN_HEIGHT/2)) {
// logical start address to write -> display is shifted 8 pixels right
pos1 = (uint16_t*)(p4_frame_buffer) + y*SCREEN_WIDTH + x;
} else {
// corrected start address to write, offset of 8 pixels ... -> display is correcly aligned
pos1 = (uint16_t*)(p4_frame_buffer) - 8 + y*SCREEN_WIDTH + x;
}
pos2 = pos1 + SCREEN_WIDTH;
uint8_t *car = charmap+v*10;
for (int y = 0; y < 10; y++) {
uint8_t d = *car++;
for (int x = 0; x < 8; x++) {
if (d & 0x80) {
*pos1++ = col1; *pos2++ = col1;
} else {
*pos1++ = col0; *pos2++ = col0;
}
d = d << 1;
}
pos1 += 2*SCREEN_WIDTH - 8;
pos2 += 2*SCREEN_WIDTH - 8;
}
esp_cache_msync(p4_frame_buffer, (VIDEO_LCD_H_RES*VIDEO_LCD_V_RES*VIDEO_PIXEL_SIZE + 0x3F) & 0xFFFFC0, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
}
void setup() {
videoInitWaveP4();
}
void loop() {
int loop = 0;
do {
uint8_t c = 255;
uint16_t color0 = 0;
uint16_t color1 = 0xFFFF; // rgb888_to_rgb565(255, 255, 255);
for (int y = 0; y < SCREEN_HEIGHT; y+=20) {
switch(loop % 3) {
case 0:
color0 = rgb888_to_rgb565(c, 0, 0); break;
case 1:
color0 = rgb888_to_rgb565(0, c, 0); break;
default:
color0 = rgb888_to_rgb565(0, 0, c); break;
}
int v = 0;
for (int x = 0; x < SCREEN_WIDTH; x+= 8 ) {
displayat(x, y, v, color0, color1);
v = (v+1) % 10;
}
c -= 8;
}
loop ++;
esp_cache_msync(p4_frame_buffer, (VIDEO_LCD_H_RES*VIDEO_LCD_V_RES*VIDEO_PIXEL_SIZE + 0x3F) & 0xFFFFC0, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
delay(2000);
} while (true);
}Debug Message
�ESP-ROM:esp32p4-eco2-20240710
Build:Jul 10 2024
rst:0x1 (POWERON),boot:0xb (SPI_FAST_FLASH_BOOT)
SPI mode:DIO, clock div:1
load:0x4ff33ce0,len:0x1174
load:0x4ff29ed0,len:0xccc
load:0x4ff2cbd0,len:0x3540
entry 0x4ff29ed0
[ 7][I][esp32-hal-psram.c:106] psramAddToHeap(): PSRAM added to the heap.
=========== Before Setup Start ===========
Chip Info:
------------------------------------------
Model : ESP32-P4
Package : 0
Revision : 1.03
Cores : 2
CPU Frequency : 360 MHz
XTAL Frequency : 40 MHz
Features Bitfield : 0000000000
Embedded Flash : No
Embedded PSRAM : No
2.4GHz WiFi : No
Classic BT : No
BT Low Energy : No
IEEE 802.15.4 : No
------------------------------------------
INTERNAL Memory Info:
------------------------------------------
Total Size : 604712 B ( 590.5 KB)
Free Bytes : 580184 B ( 566.6 KB)
Allocated Bytes : 18816 B ( 18.4 KB)
Minimum Free Bytes: 574916 B ( 561.4 KB)
Largest Free Block: 385012 B ( 376.0 KB)
------------------------------------------
SPIRAM Memory Info:
------------------------------------------
Total Size : 33554432 B (32768.0 KB)
Free Bytes : 33551856 B (32765.5 KB)
Allocated Bytes : 0 B ( 0.0 KB)
Minimum Free Bytes: 33551856 B (32765.5 KB)
Largest Free Block: 33030132 B (32256.0 KB)
Bus Mode : QSPI
------------------------------------------
Flash Info:
------------------------------------------
Chip Size : 16777216 B (16 MB)
Block Size : 65536 B ( 64.0 KB)
Sector Size : 4096 B ( 4.0 KB)
Page Size : 256 B ( 0.2 KB)
Bus Speed : 80 MHz
Flash Frequency : 80 MHz (source: 80 MHz, divider: 1)
Bus Mode : QIO
------------------------------------------
Partitions Info:
------------------------------------------
nvs : addr: 0x00009000, size: 20.0 KB, type: DATA, subtype: NVS
otadata : addr: 0x0000E000, size: 8.0 KB, type: DATA, subtype: OTA
app0 : addr: 0x00010000, size: 3072.0 KB, type: APP, subtype: OTA_0
app1 : addr: 0x00310000, size: 3072.0 KB, type: APP, subtype: OTA_1
ffat : addr: 0x00610000, size: 10112.0 KB, type: DATA, subtype: FAT
coredump : addr: 0x00FF0000, size: 64.0 KB, type: DATA, subtype: COREDUMP
------------------------------------------
Software Info:
------------------------------------------
Compile Date/Time : Feb 18 2026 17:22:52
Compile Host OS : macosx
ESP-IDF Version : v5.5.2-729-g87912cd291
Arduino Version : 3.3.7
------------------------------------------
Board Info:
------------------------------------------
Arduino Board : ESP32P4_DEV
Arduino Variant : esp32p4
Arduino FQBN : esp32:esp32:esp32p4:UploadSpeed=921600,USBMode=default,CDCOnBoot=default,MSCOnBoot=default,DFUOnBoot=default,UploadMode=default,FlashFreq=80,FlashMode=qio,FlashSize=16M,PartitionScheme=app3M_fat9M_16MB,DebugLevel=verbose,PSRAM=enabled,EraseFlash=none,JTAGAdapter=default,ChipVariant=prev3
============ Before Setup End ============
[ 377][V][esp32-hal-periman.c:251] perimanClearBusDeinit(): Deinit function for type UART_RX (2) cleared
[ 387][V][esp32-hal-periman.c:251] perimanClearBusDeinit(): Deinit function for type UART_TX (3) cleared
[ 396][V][esp32-hal-periman.c:251] perimanClearBusDeinit(): Deinit function for type UART_CTS (4) cleared
[ 406][V][esp32-hal-periman.c:251] perimanClearBusDeinit(): Deinit function for type UART_RTS (5) cleared
[ 415][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 38 successfully set to type UART_RX (2) with bus 0x4ff1040c
[ 426][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_RX (2) successfully set to 0x40002b44
[ 437][V][esp32-hal-periman.c:160] perimanSetPinBus(): Pin 37 successfully set to type UART_TX (3) with bus 0x4ff1040c
[ 448][V][esp32-hal-periman.c:235] perimanSetBusDeinit(): Deinit function for type UART_TX (3) successfully set to 0x40002906
Install RGB LCD panel driver
Get APLL freq 153846130 Hz
Got APLL config div: 1 sdm0: 177 sdm1: 19 sdm2: 19
Set APLL config to div: 3 sdm0: 0 sdm1: 0 sdm2: 14
Got APLL config div: 3 sdm0: 0 sdm1: 0 sdm2: 14
APLL enabled
APLL freq now 72000000 Hz
Create RGB LCD panel 0
Reset RGB LCD panel 0
Init RGB LCD panel 0
Get FB RGB LCD panel 0 FB at 48000A40
Initialize RGB LCD panel Done
=========== After Setup Start ============
INTERNAL Memory Info:
------------------------------------------
Total Size : 604712 B ( 590.5 KB)
Free Bytes : 575196 B ( 561.7 KB)
Allocated Bytes : 23564 B ( 23.0 KB)
Minimum Free Bytes: 569928 B ( 556.6 KB)
Largest Free Block: 385012 B ( 376.0 KB)
------------------------------------------
SPIRAM Memory Info:
------------------------------------------
Total Size : 33554432 B (32768.0 KB)
Free Bytes : 32591840 B (31828.0 KB)
Allocated Bytes : 960000 B ( 937.5 KB)
Minimum Free Bytes: 32591840 B (31828.0 KB)
Largest Free Block: 32505844 B (31744.0 KB)
------------------------------------------
GPIO Info:
------------------------------------------
GPIO : BUS_TYPE[bus/unit][chan]
--------------------------------------
37 : UART_TX[0]
38 : UART_RX[0]
============ After Setup End =============
Other Steps to Reproduce
No response
I have checked existing issues, online documentation and the Troubleshooting Guide
- I confirm I have checked existing issues, online documentation and Troubleshooting guide.