Skip to content

ESP32P4 LCD_COM module issue #12426

@O2S-C

Description

@O2S-C

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions