TinyGPU
Loading...
Searching...
No Matches
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
19namespace 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 */
41class 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 */
56 : rst_(rst),
64
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.
79 }
80
81 bool begin() override {
82 if (phyLdoChan_ >= 0) {
87 return false;
88 }
89 }
90
92 busCfg.bus_id = 0;
95 busCfg.lane_bit_rate_mbps = static_cast<float>(laneMbps_);
96 if (esp_lcd_new_dsi_bus(&busCfg, &dsiBus_) != ESP_OK) return false;
97
103 return false;
104 }
105
109 dpiCfg.dpi_clock_freq_mhz = static_cast<float>(dpiClockMhz_);
113 dpiCfg.num_fbs = 1;
124 return false;
125 }
126
127 resetPanel();
128 return true;
129 }
130
131 void end() override {
132 if (panel_ != nullptr) {
134 panel_ = nullptr;
135 }
136 if (dbiIo_ != nullptr) {
138 dbiIo_ = nullptr;
139 }
140 if (dsiBus_ != nullptr) {
142 dsiBus_ = nullptr;
143 }
144 if (ldoHandle_ != nullptr) {
146 ldoHandle_ = nullptr;
147 }
148 }
149
152 }
153
154 /// esp_lcd's DPI backend starts scanning out once this returns.
156
158 const uint8_t* rgb565) override {
159 if (panel_ == nullptr) return false;
161 rgb565) == ESP_OK;
162 }
163
164 private:
165 void resetPanel() {
166 if (rst_ < 0) return;
169 delay(20);
171 delay(120);
172 }
173
174 int8_t rst_;
187};
188
189#endif // TINYGPU_HAS_ESP_LCD_DSI
190
191} // namespace tinygpu
Definition: DSIBusESP32.h:19