TinyGPU
Loading...
Searching...
No Matches
QSPIBusESP32.h
Go to the documentation of this file.
1#pragma once
2#include <stdint.h>
3#include <string.h>
4
5#include "TinyGPU/Abstractions/IQSPIBus.h"
6
7#if defined(ESP32)
8#include "driver/spi_master.h"
9#include "esp_lcd_io_spi.h"
10#include "esp_lcd_panel_io.h"
11#define TINYGPU_HAS_ESP_LCD_QSPI 1
12#endif
13
14namespace tinygpu {
15
16#ifdef TINYGPU_HAS_ESP_LCD_QSPI
17
18/**
19 * @brief Hardware-accelerated IQSPIBus backend for ESP32, built on top of
20 * ESP-IDF's esp_lcd_new_panel_io_spi(quad_mode=1) - DMA-driven, with a
21 * persistent scratch buffer and completion callback for writeColor() (see
22 * that method's doc comment for why: esp_lcd_panel_io_tx_color() is
23 * asynchronous). This is a straight extraction of what used to live
24 * directly in DisplayDriverQSPI before the IQSPIBus split - behavior is
25 * unchanged from before.
26 */
27class QSPIBusESP32 : public IQSPIBus {
28 public:
32 : cs_(cs),
33 sclk_(sclk),
34 d0_(d0),
35 d1_(d1),
36 d2_(d2),
37 d3_(d3),
40 host_(host) {}
41
43 end();
44 delete[] scratch_;
45 }
46
47 bool begin() override {
54 busCfg.max_transfer_sz = static_cast<int>(maxTransferBytes_);
55
57 return false;
58 }
59
62 ioCfg.dc_gpio_num = -1;
63 ioCfg.spi_mode = 0;
70 ioCfg.user_ctx = this;
71
73 &ioCfg, &io_) == ESP_OK;
74 }
75
76 void end() override {
77 if (io_ != nullptr) {
79 io_ = nullptr;
80 }
81 }
82
84 if (io_ == nullptr) return false;
86 len) == ESP_OK;
87 }
88
90 if (io_ == nullptr) return false;
91
92 // Copied into a scratch buffer because esp_lcd_panel_io_tx_color() is
93 // asynchronous (trans_queue_depth > 1 above): the caller's buffer
94 // could be reused/freed before DMA finishes reading it. Blocking (via
95 // on_color_trans_done) until the transfer completes turns this back
96 // into the synchronous call IQSPIBus::writeColor() promises.
97 if (scratchCapacity_ < len) {
98 delete[] scratch_;
99 scratch_ = new uint8_t[len];
101 }
103
104 colorTransPending_ = true;
106 len) != ESP_OK) {
107 colorTransPending_ = false;
108 return false;
109 }
110 while (colorTransPending_) {
111 // busy-wait for the DMA transfer to finish
112 }
113 return true;
114 }
115
116 private:
117 static constexpr uint8_t kOpcodeParam = 0x02;
118 static constexpr uint8_t kOpcodeColor = 0x32;
119
120 static int qspiCmd(uint8_t opcode, uint8_t cmd) {
121 return (static_cast<int>(opcode) << 24) | (static_cast<int>(cmd) << 8);
122 }
123
124 // Runs in ISR context (per esp_lcd_panel_io_color_trans_done_cb_t's
125 // contract) - keep this fast.
126 static bool onColorTransDone(esp_lcd_panel_io_handle_t /*panel_io*/,
128 void* userCtx) {
129 static_cast<QSPIBusESP32*>(userCtx)->colorTransPending_ = false;
130 return false; // no higher-priority task woken
131 }
132
138 uint8_t* scratch_ = nullptr;
140 volatile bool colorTransPending_ = false;
141};
142
143#endif // TINYGPU_HAS_ESP_LCD_QSPI
144
145} // namespace tinygpu
Definition: DSIBusESP32.h:19