Dieselbe Display-Firmware bedient jetzt wahlweise das bisherige 4,3-Zoll-Panel JC4880P443C-I-W (ST7701, 480x800) oder das neue 7-Zoll-Panel JC1060P470C-I-W (JD9165, 1024x600). Umgeschaltet wird über JC_PANEL_TYPE in config.h (JC_PANEL_43 / JC_PANEL_70) oder per Compiler-Flag -DJC_PANEL_TYPE=70. Vorgabe bleibt das 4,3-Zoll-Panel; dessen Verhalten ändert sich nicht. - src/lcd/esp_lcd_jd9165.c/.h aus dem Hersteller-Paket übernommen; board_bringup.c legt je nach Panel DSI-Bus, DPI-Zeitbasis und Herstellertreiber an. - pins_config.h liefert Auflösung, LCD-Reset (4,3": GPIO5, 7,0": GPIO27) und Ausrichtung panelabhängig. Das 7-Zoll-Panel ist nativ Querformat, deshalb entfallen dort die 270-Grad-Rotation und die PPA-Beschleunigung. - lvgl_port_v9.h bezieht LVGL_PORT_H/V_RES aus pins_config.h statt fest 480/800. - Der GT911 des 7-Zöllers meldet Rohkoordinaten im Raster 800x480 statt 1024x600. Die Umrechnung hängt am process_coordinates-Hook von esp_lcd_touch, damit die Herstellerdatei esp_lcd_touch_gt911.c unverändert bleibt. - ui.cpp rechnet nicht mehr mit fest verdrahteten 480 Pixeln Höhe, sondern mit DISP_VER_RES. Layout und Schriften bleiben sonst unverändert. - Hersteller-Paket des 7-Zöllers unter JC_Display_Firmware_7zoll/ abgelegt; Werkzeuge, Archive und mitgelieferte Fremdbibliotheken per .gitignore ausgeschlossen (587 MB im Original, 21 MB im Repo). Kompiliertest ESP32-P4, beide Varianten: 4,3": 1.173.768 B Flash (37 %), 322.880 B RAM (98 %) 7,0": 1.138.752 B Flash (36 %), 322.600 B RAM (98 %) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
256 lines
9.5 KiB
C
256 lines
9.5 KiB
C
// =====================================================================================
|
|
// board_bringup.c - ESP32-P4 / GT911 Hardware-Bringup
|
|
// JC_PANEL_43 = JC4880P443C-I-W (ST7701, 480x800)
|
|
// JC_PANEL_70 = JC1060P470C-I-W (JD9165, 1024x600)
|
|
// =====================================================================================
|
|
// BEWUSST eine .c-Datei (wird als C kompiliert): die esp_lcd-Init-Makros nutzen
|
|
// Compound-Literals und Out-of-Order-Designated-Initializer, die in C++ (Arduino .cpp)
|
|
// zu Fehlern fuehren. Der Ablauf ist 1:1 aus dem Hersteller-Beispiel
|
|
// arduino_examples/lvgl_v9_sw_rotation/lvgl_sw_rotation.c uebernommen - lediglich der
|
|
// Demo-Aufruf (lv_demo_widgets) entfaellt; das UI wird ueber display_hal.cpp aufgebaut.
|
|
//
|
|
// Nur aktiv bei JC_USE_REAL_PANEL == 1. Erwartet die Vendor-BSP-Dateien im Sketch:
|
|
// pins_config.h, lvgl_port_v9.h/.c, src/lcd/*, src/touch/*
|
|
// =====================================================================================
|
|
|
|
#include "config.h" // liefert JC_USE_REAL_PANEL (C-sicher)
|
|
|
|
#if JC_USE_REAL_PANEL
|
|
|
|
#include <string.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/gpio.h"
|
|
#include "driver/ledc.h"
|
|
#include "driver/i2c_master.h"
|
|
#include "esp_log.h"
|
|
#include "esp_cache.h"
|
|
#include "esp_ldo_regulator.h"
|
|
#include "esp_lcd_panel_io.h"
|
|
#include "esp_lcd_panel_ops.h"
|
|
#include "esp_lcd_mipi_dsi.h"
|
|
#include "src/touch/esp_lcd_touch_gt911.h"
|
|
#if JC_PANEL_TYPE == JC_PANEL_70
|
|
#include "src/lcd/esp_lcd_jd9165.h"
|
|
#else
|
|
#include "src/lcd/esp_lcd_st7701.h"
|
|
#endif
|
|
#include "pins_config.h"
|
|
#include "lvgl_port_v9.h"
|
|
|
|
#define BSP_MIPI_DSI_PHY_PWR_LDO_CHAN (3)
|
|
#define BSP_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500)
|
|
#define BSP_LCD_H_RES (LCD_H_RES) // native Panel-Aufloesung
|
|
#define BSP_LCD_V_RES (LCD_V_RES)
|
|
#define BSP_I2C_NUM (I2C_NUM_1)
|
|
#define BSP_I2C_SDA (GPIO_NUM_7)
|
|
#define BSP_I2C_SCL (GPIO_NUM_8)
|
|
#define BSP_LCD_TOUCH_RST (GPIO_NUM_NC)
|
|
#define BSP_LCD_TOUCH_INT (GPIO_NUM_NC)
|
|
#define BSP_LCD_RST ((gpio_num_t)LCD_RST)
|
|
#define BSP_LCD_BACKLIGHT ((gpio_num_t)LCD_LED)
|
|
#define LCD_LEDC_CH LEDC_CHANNEL_0
|
|
|
|
static i2c_master_bus_handle_t s_i2c_handle = NULL;
|
|
|
|
void jc_backlight_init(void)
|
|
{
|
|
const ledc_channel_config_t ch = {
|
|
.gpio_num = BSP_LCD_BACKLIGHT,
|
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
|
.channel = LCD_LEDC_CH,
|
|
.intr_type = LEDC_INTR_DISABLE,
|
|
.timer_sel = 1,
|
|
.duty = 0,
|
|
.hpoint = 0
|
|
};
|
|
const ledc_timer_config_t tm = {
|
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
|
.duty_resolution = LEDC_TIMER_10_BIT,
|
|
.timer_num = 1,
|
|
.freq_hz = 5000,
|
|
.clk_cfg = LEDC_AUTO_CLK
|
|
};
|
|
ledc_timer_config(&tm);
|
|
ledc_channel_config(&ch);
|
|
}
|
|
|
|
void jc_backlight_set(int percent)
|
|
{
|
|
if (percent > 100) percent = 100;
|
|
if (percent < 0) percent = 0;
|
|
uint32_t duty = (1023 * percent) / 100;
|
|
ledc_set_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH, duty);
|
|
ledc_update_duty(LEDC_LOW_SPEED_MODE, LCD_LEDC_CH);
|
|
}
|
|
|
|
IRAM_ATTR static bool on_vsync(esp_lcd_panel_handle_t panel,
|
|
esp_lcd_dpi_panel_event_data_t *edata, void *ctx)
|
|
{
|
|
return lvgl_port_notify_lcd_vsync();
|
|
}
|
|
|
|
#if JC_PANEL_TYPE == JC_PANEL_70
|
|
// Der GT911 des 7,0"-Panels liefert Rohkoordinaten im Raster 800x480 (nicht 1024x600).
|
|
// Ohne Umrechnung waere nur das linke obere Rechteck erreichbar. Das Hersteller-Beispiel
|
|
// skaliert dafuer im Touch-Treiber; hier ueber den vorgesehenen process_coordinates-Hook,
|
|
// damit die Vendor-Datei esp_lcd_touch_gt911.c unveraendert bleibt.
|
|
#define JC_TOUCH_RAW_H_RES (800)
|
|
#define JC_TOUCH_RAW_V_RES (480)
|
|
|
|
static void jc_touch_scale(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y,
|
|
uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
|
|
{
|
|
(void)tp; (void)strength; (void)max_point_num;
|
|
if (point_num == NULL) return;
|
|
for (uint8_t i = 0; i < *point_num; i++) {
|
|
x[i] = (uint16_t)(((uint32_t)x[i] * LCD_H_RES) / JC_TOUCH_RAW_H_RES);
|
|
y[i] = (uint16_t)(((uint32_t)y[i] * LCD_V_RES) / JC_TOUCH_RAW_V_RES);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Bringt Panel + Touch + LVGL-Port hoch (LVGL laeuft danach in eigenem Task).
|
|
void jc_board_bringup(void)
|
|
{
|
|
jc_backlight_init();
|
|
|
|
i2c_master_bus_config_t i2c_bus_conf = {
|
|
.clk_source = I2C_CLK_SRC_DEFAULT,
|
|
.sda_io_num = BSP_I2C_SDA,
|
|
.scl_io_num = BSP_I2C_SCL,
|
|
.i2c_port = BSP_I2C_NUM,
|
|
};
|
|
i2c_new_master_bus(&i2c_bus_conf, &s_i2c_handle);
|
|
|
|
static esp_ldo_channel_handle_t phy_pwr_chan = NULL;
|
|
esp_ldo_channel_config_t ldo_cfg = {
|
|
.chan_id = BSP_MIPI_DSI_PHY_PWR_LDO_CHAN,
|
|
.voltage_mv = BSP_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV,
|
|
};
|
|
esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan);
|
|
|
|
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
|
|
esp_lcd_panel_io_handle_t io = NULL;
|
|
esp_lcd_panel_handle_t disp_panel = NULL;
|
|
|
|
#if JC_PANEL_TYPE == JC_PANEL_70
|
|
// ---------------- 7,0" JD9165 (1024x600) ----------------
|
|
esp_lcd_dsi_bus_config_t bus_config = JD9165_PANEL_BUS_DSI_2CH_CONFIG();
|
|
esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus);
|
|
|
|
esp_lcd_dbi_io_config_t dbi_config = JD9165_PANEL_IO_DBI_CONFIG();
|
|
esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io);
|
|
|
|
esp_lcd_dpi_panel_config_t dpi_config = JD9165_1024_600_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB565);
|
|
dpi_config.num_fbs = LVGL_PORT_LCD_BUFFER_NUMS;
|
|
|
|
jd9165_vendor_config_t vendor_config = {
|
|
.mipi_config = {
|
|
.dsi_bus = mipi_dsi_bus,
|
|
.dpi_config = &dpi_config,
|
|
},
|
|
};
|
|
esp_lcd_panel_dev_config_t lcd_dev_config = {
|
|
.bits_per_pixel = 16,
|
|
.rgb_ele_order = ESP_LCD_COLOR_SPACE_RGB,
|
|
.reset_gpio_num = BSP_LCD_RST,
|
|
.vendor_config = &vendor_config,
|
|
};
|
|
esp_lcd_new_panel_jd9165(io, &lcd_dev_config, &disp_panel);
|
|
#else
|
|
// ---------------- 4,3" ST7701 (480x800) ----------------
|
|
esp_lcd_dsi_bus_config_t bus_config = ST7701_PANEL_BUS_DSI_2CH_CONFIG();
|
|
esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus);
|
|
|
|
esp_lcd_dbi_io_config_t dbi_config = ST7701_PANEL_IO_DBI_CONFIG();
|
|
esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io);
|
|
|
|
esp_lcd_dpi_panel_config_t dpi_config = ST7701_480_360_PANEL_60HZ_DPI_CONFIG(LCD_COLOR_PIXEL_FORMAT_RGB565);
|
|
dpi_config.num_fbs = LVGL_PORT_LCD_BUFFER_NUMS;
|
|
|
|
st7701_vendor_config_t vendor_config = {
|
|
.mipi_config = {
|
|
.dsi_bus = mipi_dsi_bus,
|
|
.dpi_config = &dpi_config,
|
|
},
|
|
.flags = {
|
|
.use_mipi_interface = 1,
|
|
},
|
|
};
|
|
esp_lcd_panel_dev_config_t lcd_dev_config = {
|
|
.bits_per_pixel = 16,
|
|
.rgb_ele_order = ESP_LCD_COLOR_SPACE_RGB,
|
|
.reset_gpio_num = BSP_LCD_RST,
|
|
.vendor_config = &vendor_config,
|
|
};
|
|
esp_lcd_new_panel_st7701(io, &lcd_dev_config, &disp_panel);
|
|
#endif
|
|
esp_lcd_panel_reset(disp_panel);
|
|
esp_lcd_panel_init(disp_panel);
|
|
|
|
// Alle Framebuffer einmal auf Schwarz loeschen. Im Avoid-Tear-Direct-Mode (mehrere
|
|
// Buffer) kopiert LVGL pro Frame nur die geaenderten Bereiche in den naechsten Buffer;
|
|
// bis alle Buffer einmal vollstaendig bemalt sind, wuerde sonst uninitialisierter
|
|
// Speicher (weisses Rauschen) durchblitzen. Schwarz faellt gegen das dunkle Theme
|
|
// nicht auf. Cache-Writeback noetig, da die Buffer im PSRAM liegen und der DMA liest.
|
|
{
|
|
void *fbs[3] = { NULL, NULL, NULL };
|
|
size_t fb_size = (size_t)BSP_LCD_H_RES * BSP_LCD_V_RES * 2; // RGB565 = 2 Byte/Pixel
|
|
#if LVGL_PORT_LCD_BUFFER_NUMS >= 3
|
|
esp_lcd_dpi_panel_get_frame_buffer(disp_panel, 3, &fbs[0], &fbs[1], &fbs[2]);
|
|
#elif LVGL_PORT_LCD_BUFFER_NUMS == 2
|
|
esp_lcd_dpi_panel_get_frame_buffer(disp_panel, 2, &fbs[0], &fbs[1]);
|
|
#else
|
|
esp_lcd_dpi_panel_get_frame_buffer(disp_panel, 1, &fbs[0]);
|
|
#endif
|
|
for (int i = 0; i < 3; i++) {
|
|
if (fbs[i]) {
|
|
memset(fbs[i], 0, fb_size);
|
|
esp_cache_msync(fbs[i], fb_size, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
|
}
|
|
}
|
|
}
|
|
|
|
esp_lcd_dpi_panel_event_callbacks_t cbs = {
|
|
#if LVGL_PORT_AVOID_TEAR_MODE
|
|
.on_refresh_done = on_vsync,
|
|
#else
|
|
.on_color_trans_done = on_vsync,
|
|
#endif
|
|
};
|
|
esp_lcd_dpi_panel_register_event_callbacks(disp_panel, &cbs, NULL);
|
|
|
|
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
|
|
esp_lcd_touch_handle_t tp_handle;
|
|
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG();
|
|
tp_io_config.scl_speed_hz = 100000;
|
|
esp_lcd_new_panel_io_i2c(s_i2c_handle, &tp_io_config, &tp_io_handle);
|
|
const esp_lcd_touch_config_t tp_cfg = {
|
|
.x_max = BSP_LCD_H_RES,
|
|
.y_max = BSP_LCD_V_RES,
|
|
.rst_gpio_num = BSP_LCD_TOUCH_RST,
|
|
.int_gpio_num = BSP_LCD_TOUCH_INT,
|
|
.levels = {
|
|
.reset = 0,
|
|
.interrupt = 0,
|
|
},
|
|
.flags = {
|
|
.swap_xy = 0,
|
|
.mirror_x = 0,
|
|
.mirror_y = 0,
|
|
},
|
|
#if JC_PANEL_TYPE == JC_PANEL_70
|
|
.process_coordinates = jc_touch_scale,
|
|
#endif
|
|
};
|
|
esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp_handle);
|
|
|
|
lvgl_port_interface_t interface =
|
|
(dpi_config.flags.use_dma2d) ? LVGL_PORT_INTERFACE_MIPI_DSI_DMA
|
|
: LVGL_PORT_INTERFACE_MIPI_DSI_NO_DMA;
|
|
lvgl_port_init(disp_panel, tp_handle, interface);
|
|
}
|
|
|
|
#endif // JC_USE_REAL_PANEL
|