TinyGPU
Loading...
Searching...
No Matches
src
TinyGPU
Abstractions
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
14
namespace
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
*/
27
class
QSPIBusESP32
:
public
IQSPIBus
{
28
public
:
29
QSPIBusESP32
(
int8_t
cs
,
int8_t
sclk
,
int8_t
d0
,
int8_t
d1
,
int8_t
d2
,
30
int8_t
d3
,
size_t
maxTransferBytes
,
uint32_t
pclkHz
,
31
spi_host_device_t
host
)
32
:
cs_
(
cs
),
33
sclk_
(
sclk
),
34
d0_
(
d0
),
35
d1_
(
d1
),
36
d2_
(
d2
),
37
d3_
(
d3
),
38
maxTransferBytes_
(
maxTransferBytes
),
39
pclkHz_
(
pclkHz
),
40
host_
(
host
) {}
41
42
~
QSPIBusESP32
()
override
{
43
end
();
44
delete
[]
scratch_
;
45
}
46
47
bool
begin
()
override
{
48
spi_bus_config_t
busCfg
= {};
49
busCfg
.
data0_io_num
=
d0_
;
50
busCfg
.
data1_io_num
=
d1_
;
51
busCfg
.
sclk_io_num
=
sclk_
;
52
busCfg
.
data2_io_num
=
d2_
;
53
busCfg
.
data3_io_num
=
d3_
;
54
busCfg
.
max_transfer_sz
=
static_cast
<
int
>(
maxTransferBytes_
);
55
56
if
(
spi_bus_initialize
(
host_
, &
busCfg
,
SPI_DMA_CH_AUTO
) !=
ESP_OK
) {
57
return
false
;
58
}
59
60
esp_lcd_panel_io_spi_config_t
ioCfg
= {};
61
ioCfg
.
cs_gpio_num
=
cs_
;
62
ioCfg
.
dc_gpio_num
= -1;
63
ioCfg
.
spi_mode
= 0;
64
ioCfg
.
pclk_hz
=
pclkHz_
;
65
ioCfg
.
trans_queue_depth
= 10;
66
ioCfg
.
lcd_cmd_bits
= 32;
67
ioCfg
.
lcd_param_bits
= 8;
68
ioCfg
.
flags
.
quad_mode
= 1;
69
ioCfg
.
on_color_trans_done
= &
QSPIBusESP32
::
onColorTransDone
;
70
ioCfg
.
user_ctx
=
this
;
71
72
return
esp_lcd_new_panel_io_spi
(
static_cast
<
esp_lcd_spi_bus_handle_t
>(
host_
),
73
&
ioCfg
, &
io_
) ==
ESP_OK
;
74
}
75
76
void
end
()
override
{
77
if
(
io_
!=
nullptr
) {
78
esp_lcd_panel_io_del
(
io_
);
79
io_
=
nullptr
;
80
}
81
}
82
83
bool
writeCommand
(
uint8_t
cmd
,
const
uint8_t
*
param
,
size_t
len
)
override
{
84
if
(
io_
==
nullptr
)
return
false
;
85
return
esp_lcd_panel_io_tx_param
(
io_
,
qspiCmd
(
kOpcodeParam
,
cmd
),
param
,
86
len
) ==
ESP_OK
;
87
}
88
89
bool
writeColor
(
uint8_t
cmd
,
const
uint8_t
*
data
,
size_t
len
)
override
{
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
];
100
scratchCapacity_
=
len
;
101
}
102
memcpy
(
scratch_
,
data
,
len
);
103
104
colorTransPending_
=
true
;
105
if
(
esp_lcd_panel_io_tx_color
(
io_
,
qspiCmd
(
kOpcodeColor
,
cmd
),
scratch_
,
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*/
,
127
esp_lcd_panel_io_event_data_t
*
/*edata*/
,
128
void
*
userCtx
) {
129
static_cast
<
QSPIBusESP32
*>(
userCtx
)->
colorTransPending_
=
false
;
130
return
false
;
// no higher-priority task woken
131
}
132
133
int8_t
cs_
,
sclk_
,
d0_
,
d1_
,
d2_
,
d3_
;
134
size_t
maxTransferBytes_
;
135
uint32_t
pclkHz_
;
136
spi_host_device_t
host_
;
137
esp_lcd_panel_io_handle_t
io_
=
nullptr
;
138
uint8_t
*
scratch_
=
nullptr
;
139
size_t
scratchCapacity_
= 0;
140
volatile
bool
colorTransPending_
=
false
;
141
};
142
143
#
endif
// TINYGPU_HAS_ESP_LCD_QSPI
144
145
}
// namespace tinygpu
tinygpu
Definition:
DSIBusESP32.h:19
Generated by
1.9.6