TinyGPU
Loading...
Searching...
No Matches
src
TinyGPU
Abstractions
DSIBusESP32.h
Go to the documentation of this file.
1
#
pragma
once
2
#
include
<
stdint
.
h
>
3
4
#
include
"TinyGPU/Abstractions/IDSIBus.h"
5
6
// esp_lcd_mipi_dsi.h only exists in the ESP32-P4 variant of arduino-esp32's
7
// bundled ESP-IDF (MIPI-DSI is a P4-only peripheral) - __has_include lets
8
// this file compile as an empty no-op on every other target instead of
9
// hard-erroring.
10
#
if
__has_include
(
"esp_lcd_mipi_dsi.h"
)
11
#
include
"driver/gpio.h"
12
#
include
"esp_lcd_mipi_dsi.h"
13
#
include
"esp_lcd_panel_io.h"
14
#
include
"esp_lcd_panel_ops.h"
15
#
include
"esp_ldo_regulator.h"
16
#
define
TINYGPU_HAS_ESP_LCD_DSI
1
17
#
endif
18
19
namespace
tinygpu
{
20
21
#
ifdef
TINYGPU_HAS_ESP_LCD_DSI
22
23
/**
24
* @brief IDSIBus backend for ESP32-P4, built on ESP-IDF's DBI (command
25
* channel) + DPI (video-timing channel) split - the interface ESP32-P4
26
* exposes for DSI LCDs. A DPI panel has no address-window/RAMWR concept:
27
* `esp_lcd_new_panel_dpi()` allocates a screen-sized, DMA-scanned
28
* framebuffer up front, and `esp_lcd_panel_draw_bitmap()` writes straight
29
* into a rect of it - the continuously-running DPI bridge just scans
30
* whatever's currently there.
31
*
32
* Only a single frame buffer (`num_fbs = 1`) is used, so a write landing
33
* while that region happens to be mid-scan can tear - this driver doesn't
34
* attempt the double-buffer-plus-dirty-rect scheme some vendor BSPs use to
35
* avoid that; same tradeoff DisplayDriverSPI/QSPI already accept for a
36
* torn/partial transfer landing mid-refresh.
37
*
38
* This is a straight extraction of what used to live directly in
39
* DisplayDriverDSI before the IDSIBus split - behavior is unchanged.
40
*/
41
class
DSIBusESP32
:
public
IDSIBus
{
42
public
:
43
/**
44
* @param rst panel reset GPIO, -1 if unused
45
* @param width/height panel resolution in pixels
46
* @param laneNum number of DSI data lanes
47
* @param laneMbps per-lane bit rate in Mbps
48
* @param dpiClockMhz DPI (pixel) clock frequency in MHz
49
* @param phyLdoChan on-chip LDO channel powering the DSI PHY, -1 if the
50
* board supplies that rail some other way (no LDO acquire is done)
51
* @param phyLdoMv LDO output voltage in mV, only used if phyLdoChan >= 0
52
*/
53
DSIBusESP32
(
int8_t
rst
,
size_t
width
,
size_t
height
,
uint8_t
laneNum
,
54
uint32_t
laneMbps
,
uint32_t
dpiClockMhz
,
int8_t
phyLdoChan
,
55
uint16_t
phyLdoMv
)
56
:
rst_
(
rst
),
57
width_
(
width
),
58
height_
(
height
),
59
laneNum_
(
laneNum
),
60
laneMbps_
(
laneMbps
),
61
dpiClockMhz_
(
dpiClockMhz
),
62
phyLdoChan_
(
phyLdoChan
),
63
phyLdoMv_
(
phyLdoMv
) {}
64
65
~
DSIBusESP32
()
override
{
end
(); }
66
67
/// Sets the panel's DSI video timing (porches/sync widths, in pixels/
68
/// lines). Must be called before begin(); every panel documents its own
69
/// values, there is no cross-panel default worth assuming.
70
void
setVideoTiming
(
uint16_t
hsyncPulseWidth
,
uint16_t
hsyncBackPorch
,
71
uint16_t
hsyncFrontPorch
,
uint16_t
vsyncPulseWidth
,
72
uint16_t
vsyncBackPorch
,
uint16_t
vsyncFrontPorch
) {
73
hsyncPulseWidth_
=
hsyncPulseWidth
;
74
hsyncBackPorch_
=
hsyncBackPorch
;
75
hsyncFrontPorch_
=
hsyncFrontPorch
;
76
vsyncPulseWidth_
=
vsyncPulseWidth
;
77
vsyncBackPorch_
=
vsyncBackPorch
;
78
vsyncFrontPorch_
=
vsyncFrontPorch
;
79
}
80
81
bool
begin
()
override
{
82
if
(
phyLdoChan_
>= 0) {
83
esp_ldo_channel_config_t
ldoCfg
= {};
84
ldoCfg
.
chan_id
=
phyLdoChan_
;
85
ldoCfg
.
voltage_mv
=
phyLdoMv_
;
86
if
(
esp_ldo_acquire_channel
(&
ldoCfg
, &
ldoHandle_
) !=
ESP_OK
) {
87
return
false
;
88
}
89
}
90
91
esp_lcd_dsi_bus_config_t
busCfg
= {};
92
busCfg
.
bus_id
= 0;
93
busCfg
.
num_data_lanes
=
laneNum_
;
94
busCfg
.
phy_clk_src
=
MIPI_DSI_PHY_CLK_SRC_DEFAULT
;
95
busCfg
.
lane_bit_rate_mbps
=
static_cast
<
float
>(
laneMbps_
);
96
if
(
esp_lcd_new_dsi_bus
(&
busCfg
, &
dsiBus_
) !=
ESP_OK
)
return
false
;
97
98
esp_lcd_dbi_io_config_t
dbiCfg
= {};
99
dbiCfg
.
virtual_channel
= 0;
100
dbiCfg
.
lcd_cmd_bits
= 8;
101
dbiCfg
.
lcd_param_bits
= 8;
102
if
(
esp_lcd_new_panel_io_dbi
(
dsiBus_
, &
dbiCfg
, &
dbiIo_
) !=
ESP_OK
) {
103
return
false
;
104
}
105
106
esp_lcd_dpi_panel_config_t
dpiCfg
= {};
107
dpiCfg
.
virtual_channel
= 0;
108
dpiCfg
.
dpi_clk_src
=
MIPI_DSI_DPI_CLK_SRC_DEFAULT
;
109
dpiCfg
.
dpi_clock_freq_mhz
=
static_cast
<
float
>(
dpiClockMhz_
);
110
dpiCfg
.
pixel_format
=
LCD_COLOR_PIXEL_FORMAT_RGB565
;
111
dpiCfg
.
in_color_format
=
LCD_COLOR_FMT_RGB565
;
112
dpiCfg
.
out_color_format
=
LCD_COLOR_FMT_RGB565
;
113
dpiCfg
.
num_fbs
= 1;
114
dpiCfg
.
video_timing
.
h_size
=
width_
;
115
dpiCfg
.
video_timing
.
v_size
=
height_
;
116
dpiCfg
.
video_timing
.
hsync_pulse_width
=
hsyncPulseWidth_
;
117
dpiCfg
.
video_timing
.
hsync_back_porch
=
hsyncBackPorch_
;
118
dpiCfg
.
video_timing
.
hsync_front_porch
=
hsyncFrontPorch_
;
119
dpiCfg
.
video_timing
.
vsync_pulse_width
=
vsyncPulseWidth_
;
120
dpiCfg
.
video_timing
.
vsync_back_porch
=
vsyncBackPorch_
;
121
dpiCfg
.
video_timing
.
vsync_front_porch
=
vsyncFrontPorch_
;
122
dpiCfg
.
flags
.
use_dma2d
= 1;
123
if
(
esp_lcd_new_panel_dpi
(
dsiBus_
, &
dpiCfg
, &
panel_
) !=
ESP_OK
) {
124
return
false
;
125
}
126
127
resetPanel
();
128
return
true
;
129
}
130
131
void
end
()
override
{
132
if
(
panel_
!=
nullptr
) {
133
esp_lcd_panel_del
(
panel_
);
134
panel_
=
nullptr
;
135
}
136
if
(
dbiIo_
!=
nullptr
) {
137
esp_lcd_panel_io_del
(
dbiIo_
);
138
dbiIo_
=
nullptr
;
139
}
140
if
(
dsiBus_
!=
nullptr
) {
141
esp_lcd_del_dsi_bus
(
dsiBus_
);
142
dsiBus_
=
nullptr
;
143
}
144
if
(
ldoHandle_
!=
nullptr
) {
145
esp_ldo_release_channel
(
ldoHandle_
);
146
ldoHandle_
=
nullptr
;
147
}
148
}
149
150
bool
writeCommand
(
uint8_t
cmd
,
const
uint8_t
*
param
,
size_t
len
)
override
{
151
return
esp_lcd_panel_io_tx_param
(
dbiIo_
,
cmd
,
param
,
len
) ==
ESP_OK
;
152
}
153
154
/// esp_lcd's DPI backend starts scanning out once this returns.
155
bool
finishInit
()
override
{
return
esp_lcd_panel_init
(
panel_
) ==
ESP_OK
; }
156
157
bool
drawBitmap
(
size_t
x0
,
size_t
y0
,
size_t
x1
,
size_t
y1
,
158
const
uint8_t
*
rgb565
)
override
{
159
if
(
panel_
==
nullptr
)
return
false
;
160
return
esp_lcd_panel_draw_bitmap
(
panel_
,
x0
,
y0
,
x1
,
y1
,
161
rgb565
) ==
ESP_OK
;
162
}
163
164
private
:
165
void
resetPanel
() {
166
if
(
rst_
< 0)
return
;
167
pinMode
(
rst_
,
OUTPUT
);
168
digitalWrite
(
rst_
,
LOW
);
169
delay
(20);
170
digitalWrite
(
rst_
,
HIGH
);
171
delay
(120);
172
}
173
174
int8_t
rst_
;
175
size_t
width_
,
height_
;
176
uint8_t
laneNum_
;
177
uint32_t
laneMbps_
;
178
uint32_t
dpiClockMhz_
;
179
int8_t
phyLdoChan_
;
180
uint16_t
phyLdoMv_
;
181
uint16_t
hsyncPulseWidth_
= 10,
hsyncBackPorch_
= 10,
hsyncFrontPorch_
= 10;
182
uint16_t
vsyncPulseWidth_
= 2,
vsyncBackPorch_
= 10,
vsyncFrontPorch_
= 10;
183
esp_ldo_channel_handle_t
ldoHandle_
=
nullptr
;
184
esp_lcd_dsi_bus_handle_t
dsiBus_
=
nullptr
;
185
esp_lcd_panel_io_handle_t
dbiIo_
=
nullptr
;
186
esp_lcd_panel_handle_t
panel_
=
nullptr
;
187
};
188
189
#
endif
// TINYGPU_HAS_ESP_LCD_DSI
190
191
}
// namespace tinygpu
tinygpu
Definition:
DSIBusESP32.h:19
Generated by
1.9.6