roo_display
API Documentation for roo_display
Loading...
Searching...
No Matches
parallel_lcd_8bit.h
Go to the documentation of this file.
1#pragma once
2
4
5#if !defined(ESP_PLATFORM) || !(CONFIG_IDF_TARGET_ESP32S3)
6#warning Compilation target must be ESP32_S3 for this device.
7#else
8
9#include <algorithm>
10#include <cinttypes>
11#include <cmath>
12#include <utility>
13
14#include "esp_lcd_panel_io.h"
17#include "roo_io/data/byte_order.h"
18#include "soc/lcd_cam_reg.h"
19#include "soc/lcd_cam_struct.h"
20
21namespace roo_display {
22namespace esp32s3 {
23
24class ParallelLcd8Bit {
25 public:
26 struct DataBus {
27 int8_t pinD0;
28 int8_t pinD1;
29 int8_t pinD2;
30 int8_t pinD3;
31 int8_t pinD4;
32 int8_t pinD5;
33 int8_t pinD6;
34 int8_t pinD7;
35 };
36
37 ParallelLcd8Bit(int8_t pinCs, int8_t pinDc, int pinRst, int8_t pinWr,
38 int8_t pinRd, DataBus data)
39 : ParallelLcd8Bit(pinCs, pinDc, pinRst, pinWr, pinRd, std::move(data),
40 24000000) {}
41
42 ParallelLcd8Bit(int8_t pinCs, int8_t pinDc, int pinRst, int8_t pinWr,
43 int8_t pinRd, DataBus data, int32_t speed)
44 : pinCs_(pinCs),
45 pinDc_(pinDc),
46 pinRst_(pinRst),
47 pinWr_(pinWr),
48 pinRd_(pinRd),
49 data_(std::move(data)),
50 speed_(speed) {}
51
52 void init() {
53 if (pinCs_ >= 0) {
54 DefaultGpio::setOutput(pinCs_);
55 DefaultGpio::setHigh(pinCs_);
56 }
57
58 DefaultGpio::setOutput(pinDc_);
59 DefaultGpio::setHigh(pinDc_);
60
61 if (pinRst_ >= 0) {
62 DefaultGpio::setOutput(pinRst_);
63 DefaultGpio::setHigh(pinRst_);
64 }
65
66 DefaultGpio::setOutput(pinWr_);
67 DefaultGpio::setHigh(pinWr_);
68
69 if (pinRd_ >= 0) {
70 DefaultGpio::setOutput(pinRd_);
71 DefaultGpio::setHigh(pinRd_);
72 }
73
74 esp_lcd_i80_bus_handle_t i80_bus = nullptr;
75
76 esp_lcd_i80_bus_config_t bus_config = {
77 .dc_gpio_num = pinDc_,
78 .wr_gpio_num = pinWr_,
79 .clk_src = LCD_CLK_SRC_PLL160M,
80 .data_gpio_nums = {data_.pinD0, data_.pinD1, data_.pinD2, data_.pinD3,
81 data_.pinD4, data_.pinD5, data_.pinD6, data_.pinD7},
82 .bus_width = 8,
83 .max_transfer_bytes = 2};
84 esp_lcd_new_i80_bus(&bus_config, &i80_bus);
85
86 uint32_t diff = INT32_MAX;
87 uint32_t div_n = 256;
88 uint32_t div_a = 63;
89 uint32_t div_b = 62;
90 uint32_t clkcnt = 64;
91 uint32_t start_cnt = std::min<uint32_t>(64u, (F_CPU / (speed_ * 2) + 1));
92 uint32_t end_cnt = std::max<uint32_t>(2u, F_CPU / 256u / speed_);
93 if (start_cnt <= 2) {
94 end_cnt = 1;
95 }
96 for (uint32_t cnt = start_cnt; diff && cnt >= end_cnt; --cnt) {
97 float fdiv = (float)F_CPU / cnt / speed_;
98 uint32_t n = std::max<uint32_t>(2u, (uint32_t)fdiv);
99 fdiv -= n;
100
101 for (uint32_t a = 63; diff && a > 0; --a) {
102 uint32_t b = roundf(fdiv * a);
103 if (a == b && n == 256) {
104 break;
105 }
106 uint32_t freq = F_CPU / ((n * cnt) + (float)(b * cnt) / (float)a);
107 uint32_t d = abs(speed_ - (int)freq);
108 if (diff <= d) {
109 continue;
110 }
111 diff = d;
112 clkcnt = cnt;
113 div_n = n;
114 div_b = b;
115 div_a = a;
116 if (b == 0 || a == b) {
117 break;
118 }
119 }
120 }
121 if (div_a == div_b) {
122 div_b = 0;
123 div_n += 1;
124 }
125
126 lcd_cam_lcd_clock_reg_t lcd_clock;
127 lcd_clock.lcd_clkcnt_n = std::max(1ul, clkcnt - 1);
128 lcd_clock.lcd_clk_equ_sysclk = (clkcnt == 1);
129 lcd_clock.lcd_ck_idle_edge = true;
130 lcd_clock.lcd_ck_out_edge = false;
131 lcd_clock.lcd_clkm_div_num = div_n;
132 lcd_clock.lcd_clkm_div_b = div_b;
133 lcd_clock.lcd_clkm_div_a = div_a;
134 lcd_clock.lcd_clk_sel =
135 2; // clock_select: 1=XTAL CLOCK / 2=240MHz / 3=160MHz
136 lcd_clock.clk_en = true;
137
138 LCD_CAM.lcd_clock.val = lcd_clock.val;
139 }
140
141 void beginTransaction() {}
142 void beginWriteOnlyTransaction() {}
143 void endTransaction() {}
144
145 void begin() {
146 DefaultGpio::setLow(pinCs_);
147 LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE;
148 LCD_CAM.lcd_user.val = 0;
149 LCD_CAM.lcd_user.val = LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE;
150 }
151
152 void flush() {}
153
154 void end() {
155 while (LCD_CAM.lcd_user.val & LCD_CAM_LCD_START) {
156 }
157 DefaultGpio::setHigh(pinCs_);
158 }
159
160 void cmdBegin() {
161 LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
162 }
163
164 void cmdEnd() { LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE; }
165
166 void writeBytes(const roo::byte* data, uint32_t len) {
167 while (len-- > 0) write(static_cast<uint8_t>(*data++));
168 }
169
170 void write(uint8_t data) {
171 LCD_CAM.lcd_cmd_val.lcd_cmd_value = data;
172 while (LCD_CAM.lcd_user.val & LCD_CAM_LCD_START) {
173 }
174 LCD_CAM.lcd_user.val =
175 LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE | LCD_CAM_LCD_START;
176 }
177
178 void write16(uint16_t data) {
179 write(data >> 8);
180 write(data & 0xFF);
181 }
182
183 void write16x2(uint16_t a, uint16_t b) {
184 write(a >> 8);
185 write(a & 0xFF);
186 write(b >> 8);
187 write(b & 0xFF);
188 }
189
190 void write32(uint32_t data) {
191 write((data >> 24) & 0xFF);
192 write((data >> 16) & 0xFF);
193 write((data >> 8) & 0xFF);
194 write(data & 0xFF);
195 }
196
197 void fill16(const roo::byte* data, uint32_t repetitions) {
198 while (repetitions-- > 0) {
199 writeBytes(data, 2);
200 }
201 }
202
203 private:
204 int8_t pinCs_;
205 int8_t pinDc_;
206 int8_t pinRst_;
207 int8_t pinWr_;
208 int8_t pinRd_;
209 DataBus data_;
210 int32_t speed_;
211};
212
213} // namespace esp32s3
214} // namespace roo_display
215
216#endif // defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
Defines 140 opaque HTML named colors.