5#if !defined(ESP_PLATFORM) || !(CONFIG_IDF_TARGET_ESP32S3)
6#warning Compilation target must be ESP32_S3 for this device.
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"
24class ParallelLcd8Bit {
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),
42 ParallelLcd8Bit(int8_t pinCs, int8_t pinDc,
int pinRst, int8_t pinWr,
43 int8_t pinRd, DataBus data, int32_t speed)
49 data_(std::move(data)),
54 DefaultGpio::setOutput(pinCs_);
55 DefaultGpio::setHigh(pinCs_);
58 DefaultGpio::setOutput(pinDc_);
59 DefaultGpio::setHigh(pinDc_);
62 DefaultGpio::setOutput(pinRst_);
63 DefaultGpio::setHigh(pinRst_);
66 DefaultGpio::setOutput(pinWr_);
67 DefaultGpio::setHigh(pinWr_);
70 DefaultGpio::setOutput(pinRd_);
71 DefaultGpio::setHigh(pinRd_);
74 esp_lcd_i80_bus_handle_t i80_bus =
nullptr;
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},
83 .max_transfer_bytes = 2};
84 esp_lcd_new_i80_bus(&bus_config, &i80_bus);
86 uint32_t diff = INT32_MAX;
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_);
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);
101 for (uint32_t a = 63; diff && a > 0; --a) {
102 uint32_t b = roundf(fdiv * a);
103 if (a == b && n == 256) {
106 uint32_t freq = F_CPU / ((n * cnt) + (
float)(b * cnt) / (
float)a);
107 uint32_t d = abs(speed_ - (
int)freq);
116 if (b == 0 || a == b) {
121 if (div_a == div_b) {
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 =
136 lcd_clock.clk_en =
true;
138 LCD_CAM.lcd_clock.val = lcd_clock.val;
141 void beginTransaction() {}
142 void beginWriteOnlyTransaction() {}
143 void endTransaction() {}
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;
155 while (LCD_CAM.lcd_user.val & LCD_CAM_LCD_START) {
157 DefaultGpio::setHigh(pinCs_);
161 LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE | LCD_CAM_LCD_CD_CMD_SET;
164 void cmdEnd() { LCD_CAM.lcd_misc.val = LCD_CAM_LCD_CD_IDLE_EDGE; }
166 void writeBytes(
const roo::byte* data, uint32_t len) {
167 while (len-- > 0) write(
static_cast<uint8_t
>(*data++));
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) {
174 LCD_CAM.lcd_user.val =
175 LCD_CAM_LCD_CMD | LCD_CAM_LCD_UPDATE | LCD_CAM_LCD_START;
178 void write16(uint16_t data) {
183 void write16x2(uint16_t a, uint16_t b) {
190 void write32(uint32_t data) {
191 write((data >> 24) & 0xFF);
192 write((data >> 16) & 0xFF);
193 write((data >> 8) & 0xFF);
197 void fill16(
const roo::byte* data, uint32_t repetitions) {
198 while (repetitions-- > 0) {
Defines 140 opaque HTML named colors.