1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! Basic LCD DSI example for ESP32-P4
//!
//! This example shows how to:
//! - Configure the LCD peripheral for a DSI panel
//! - Create a vendor-specific control panel (ILI9881C over DBI)
//! - Initialize the panel
//! - Create a DPI panel for frame updates
//! - Draw a simple bitmap
//!
//! Requirements:
//! - Target: ESP32-P4 (`ESP_IDF_TARGET=esp32p4`)
//! - ESP-IDF must have the ILI9881C DSI panel component enabled
//! - A compatible 1024×600 MIPI-DSI display connected to the LCD peripheral
#![allow(unknown_lints)]
#![allow(unexpected_cfgs)]
#[cfg(esp32p4)]
mod example {
use std::time::Duration;
use esp_idf_hal::lcd::*;
use esp_idf_hal::ldo::*;
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_sys::*;
#[allow(unused_variables)]
#[allow(unused_assignments)]
#[allow(unused_mut)]
pub fn run() -> anyhow::Result<()> {
// Link ESP-IDF patches (required for examples)
esp_idf_hal::sys::link_patches();
let peripherals = Peripherals::take()?;
// Configure LDO3 for MIPI D-PHY supply (typically 2.5 V).
//
// NOTE: Adjust the voltage to match your board's design and panel
// requirements. 2.5 V is a common value for the DSI PHY supply.
let ldo_cfg = LdoChannelConfig::new(2500);
let _ldo3 = LdoChannel::new(peripherals.ldo3, &ldo_cfg)?;
// Give the LDO some time to stabilize before enabling the panel.
std::thread::sleep(Duration::from_millis(20));
// Configure video timing for a 1024×600 panel.
// Adjust these values to match your panel's datasheet.
let video_timing = VideoTiming::new(1024, 600)
.hsync_back_porch(100)
.hsync_pulse_width(100)
.hsync_front_porch(100)
.vsync_back_porch(10)
.vsync_pulse_width(10)
.vsync_front_porch(10);
// High-level LCD configuration:
// - 2 DSI data lanes at 1250 Mbps
// - RGB888 pixel format
// - DPI clock at 48 MHz
let config = LcdConfig::new(
video_timing,
2, // num_data_lanes
1250, // lane_bit_rate_mbps
48, // dpi_clock_freq_mhz
PixelFormat::Rgb888,
);
// Create driver with DSI bus and DBI IO
let mut lcd = LcdDriver::new(peripherals.dsi, &config)?;
// Create vendor control panel (e.g., ILI9881C) over DBI.
//
// Note: This requires the corresponding ESP-IDF component
// (e.g., ILI9881C DSI panel driver) to be enabled.
let mut dev_config: esp_lcd_panel_dev_config_t = lcd.config().into();
// Configure reset GPIO if your panel uses one (adjust as needed).
// Use -1 for no reset GPIO.
dev_config.reset_gpio_num = -1;
let mut control_panel: PanelHandle = core::ptr::null_mut();
// Replace `esp_lcd_new_panel_ili9881c` with the appropriate
// vendor-specific constructor for your panel if needed.
//
// Note that you DO need to include the ESP-IDf custom component
// corresponding to your panel (e.g., ILI9881C DSI panel) in your project for this to work.
//
// unsafe {
// esp!(esp_lcd_new_panel_ili9881c(
// lcd.dbi_io_handle(),
// &dev_config,
// &mut control_panel
// ))?;
// }
lcd.set_control_panel(control_panel)?;
// Initialize the control panel
lcd.reset()?;
lcd.init()?;
lcd.set_display_on(true)?;
// Create the DPI panel for pixel data transfers.
// This consumes the NoDpiPanel driver and returns a WithDpiPanel driver.
let lcd = lcd.create_dpi_panel()?;
// Simple test bitmap: clear screen to black.
//
// NOTE:
// - draw_bitmap uses half-open intervals [x1, x2) × [y1, y2)
// - For a 1024×600 display, use x2=1024, y2=600 (NOT 1023, 599)
// - For RGB888, 3 bytes per pixel
let bitmap = vec![0u8; 1024 * 600 * 3];
lcd.draw_bitmap(0, 0, 1024, 600, &bitmap)?;
// Keep the application alive so the display remains on
loop {
std::thread::sleep(Duration::from_secs(1));
}
}
}
#[cfg(not(esp32p4))]
mod example {
pub fn run() -> anyhow::Result<()> {
println!("This example is not supported on this target");
Ok(())
}
}
fn main() -> anyhow::Result<()> {
example::run()
}