katzrydz
(Katzrydz)
October 13, 2025, 3:24pm
1
Hi all. I thought I would start a new topic for the ESP32-P4 + ESP32-C6 device by Guition with a 10.1" display that can be found for rather cheap on AliExpress:
https://www.aliexpress.com/item/1005009147577522.html?spm=a2g0o.detail.1000023.1.2fa43hUz3hUzla
Through a number of posts on GitHub and here I been able to get some of the basic functionality working. However there are lots of things that don’t. My main source of information was from Willumpie82 on Github .
Display: Uses the MIPI_DSI driver. Seems to not support HW rotation, and default is in portrait mode.
Touch: Uses the GSL3680 chip and does require using the specific code/drivers found in Willumpie82’s YAML file otherwise it will fail.
Wifi/BT: Works out of the box.
Camera: Supposedly uses an OV02C10 sensor, and the P4 uses a CSI protocol. Have not found a method to interface them yet.
Speaker: Board has an ES8311 codec for DAC. Tried code using this but no success getting any output.
Microphone: Needs to have an ADC defined, and from the documentation it shows a reference to an ES7210 ADC, but that fails to be detected. The ES8311 documentation shows that it also has ADC functionality, but there are no drivers in place for that.
Perhaps we can use this topic to track what works and not, as well as tips/tricks we have discovered.
3 Likes
katzrydz
(Katzrydz)
October 13, 2025, 4:25pm
2
This is my YAML code thus far:
# ---------------------------------------------------------------------------------------------
# Home Assistant/System Setup
# ---------------------------------------------------------------------------------------------
captive_portal:
http_request:
web_server:
port: 80
esphome:
name: ${device_name}
comment: ${comment}
friendly_name: ${friendly_name}
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxxxxxx"
on_client_connected:
- if:
condition:
lambda: 'return (0 == client_info.find("Home Assistant "));'
then:
- lvgl.label.update:
id: ha_status_icon_label
text_color: ${color_white}
text: ${mdi_wifi}
- logger.log: "Wifi found"
on_client_disconnected:
- if:
condition:
lambda: 'return (0 == client_info.find("Home Assistant "));'
then:
- lvgl.label.update:
id: ha_status_icon_label
text_color: ${color_warning}
text: ${mdi_wifi_off}
- logger.log: "No wifi"
# Example configuration entry
button:
- platform: restart
name: "P4 Restart"
ota:
- platform: esphome
id: my_ota
password: "xxxxxxxxxxxxxxxxx"
wifi:
ssid: "xxxxxx"
password: "xxxxxxx"
output_power: "8.5db"
esp32:
board: esp32-p4-evboard
cpu_frequency: 400MHz
flash_size: 16MB
framework:
type: esp-idf
advanced:
enable_idf_experimental_features: yes
logger:
hardware_uart: USB_SERIAL_JTAG
level: DEBUG
logs:
lvgl: DEBUG
display: DEBUG
app: DEBUG
esp_ldo:
- channel: 3
voltage: 2.5V
esp32_hosted:
variant: ESP32C6
reset_pin: 54
cmd_pin: 19
clk_pin: 18
d0_pin: 14
d1_pin: 15
d2_pin: 16
d3_pin: 17
active_high: true
psram:
speed: 200MHz
color:
- id: my_red
red: 100%
green: 0%
blue: 0%
globals:
- id: counter
type: int
restore_value: no
initial_value: '10'
- id: door_locked
type: bool
restore_value: no
initial_value: "false"
# ---------------------------------------------------------------------------------------------
# Internal Assignments/Preparation
# ---------------------------------------------------------------------------------------------
substitutions:
device_name: "p4tablet"
friendly_name: "P4 tablet"
comment: "esp32-P4"
# Material Design Icons
mdi_wifi: "\U000F05A9"
mdi_wifi_off: "\U000F05AA"
mdi_power: "\U000F0425"
mdi_thermometer: "\U000F050F"
mdi_lock_unlocked: "\U000F033F"
mdi_lock_locked: "\U000F033E"
color_warning: "0xd2691e"
color_white: "0xFFFFFF"
external_components:
- source: github://willumpie82/esphome@dev
components: [mipi_dsi]
- source: github://kvj/esphome@jd9365_gsl3680
refresh: 0s
components: [gsl3680]
- source: github://esphome/[email protected]
components: [i2c]
# -------------------------------
# Interval checks
# -------------------------------
interval:
- interval: 10s
then:
# ---------------------------------------------------------------------------------------
# Periodically checking on light switch status to update buttons
# ---------------------------------------------------------------------------------------
- lvgl.obj.update:
id: humidity_section
bg_image_src: door_snapshot
- if:
condition:
lambda: 'return id(front_door_lock_sensor).state == "locked";'
then:
- lvgl.label.update:
id: lock_status_icon_label
text_color: "0xffffff"
text: ${mdi_lock_locked}
- logger.log: "Door is locked"
else:
- lvgl.label.update:
id: lock_status_icon_label
text_color: "0xFF4500"
text: ${mdi_lock_unlocked}
- logger.log: "Door is unlocked"
- if:
condition:
switch.is_on: dining_light_switch
then:
- lvgl.button.update:
id: dining_light_toggle_btn
bg_color: "0xff4500"
- logger.log: "Dining Light is on"
else:
- lvgl.button.update:
id: dining_light_toggle_btn
bg_color: "0x222222"
- logger.log: "Dining Light is off"
- if:
condition:
switch.is_on: living_light_switch
then:
- lvgl.button.update:
id: living_light_toggle_btn
bg_color: "0xff4500"
- logger.log: "Living Room Light is on"
else:
- lvgl.button.update:
id: living_light_toggle_btn
bg_color: "0x222222"
- logger.log: "Living Room Light is off"
- if:
condition:
switch.is_on: kitchen_light_switch
then:
- lvgl.button.update:
id: kitchen_light_toggle_btn
bg_color: "0xff4500"
- logger.log: "Kitchen Light is on"
else:
- lvgl.button.update:
id: kitchen_light_toggle_btn
bg_color: "0x222222"
- logger.log: "Kitchen Light is off"
# ---------------------------------------------------------------------------------------
# Periodic updates to temperatures and humidity
# ---------------------------------------------------------------------------------------
- homeassistant.service:
service: homeassistant.update_entity
data:
entity_id: sensor.hallway_temperature
- homeassistant.service:
service: homeassistant.update_entity
data:
entity_id: sensor.home_realfeel_temperature
- homeassistant.service:
service: homeassistant.update_entity
data:
entity_id: sensor.hallway_humidity
- homeassistant.service:
service: homeassistant.update_entity
data:
entity_id: lock.front_door
- homeassistant.service:
service: homeassistant.update_entity
data:
entity_id: switch.dining_room_light
# Update the label text manually
- lambda: |-
if (id(ha_temperature_sensor).has_state()) {
char temp_str[10]; // Buffer to store formatted string (e.g., "23.50°C")
float temp = id(ha_temperature_sensor).state;
snprintf(temp_str, sizeof(temp_str), "%.2f°C", temp); // Formats to 2 decimals
lv_label_set_text(id(temp_value_label), temp_str);
} else {
lv_label_set_text(id(temp_value_label), "--- °C");
}
if (id(ha_outsidetemperature_sensor).has_state()) {
char temp_str[10]; // Buffer to store formatted string (e.g., "23.50°C")
float temp = id(ha_outsidetemperature_sensor).state;
snprintf(temp_str, sizeof(temp_str), "%.2f°C", temp); // Formats to 2 decimals
lv_label_set_text(id(outtemp_value_label), temp_str);
} else {
lv_label_set_text(id(outtemp_value_label), "--- °C");
}
# ---------------------------------------------------------------------------------------------
# Sensor Definitions
# ---------------------------------------------------------------------------------------------
# --- Define Sensors to fetch data from Home Assistant ---
sensor:
- platform: homeassistant
id: ha_temperature_sensor
entity_id: sensor.hallway_temperature
internal: true #
unit_of_measurement: "°C"
- platform: homeassistant
id: ha_outsidetemperature_sensor
entity_id: sensor.home_realfeel_temperature
internal: true
unit_of_measurement: "°C"
- platform: homeassistant
id: ha_humidity_sensor
entity_id: sensor.hallway_humidity
internal: true
unit_of_measurement: "%"
- platform: uptime
name: "Uptime"
id: sys_uptime
entity_category: "diagnostic"
update_interval: 60s
- platform: wifi_signal
name: "Wifi RSSI"
id: wifi_signal_db
icon: mdi:wifi-arrow-left-right
update_interval: 60s
entity_category: "diagnostic"
- platform: homeassistant
id: front_door_lock_battery
entity_id: sensor.front_door_battery
icon: mdi:mdi_lock_locked
text_sensor:
- platform: wifi_info
ip_address:
name: "IP Address"
entity_category: "diagnostic"
icon: mdi:ip-network
ssid:
name: "Wifi SSID"
icon: mdi:wifi-check
mac_address:
name: "Wifi MAC"
entity_category: "diagnostic"
icon: mdi:ip-network
- platform: homeassistant
id: front_door_lock_sensor
entity_id: lock.front_door
icon: mdi:mdi_lock_locked
output:
# Backlight LED
- platform: ledc
pin: GPIO23
id: GPIO23
frequency: 100Hz
min_power: 0.03
zero_means_zero: true
light:
- platform: monochromatic
output: GPIO23
name: Backlight
id: backlight
restore_mode: RESTORE_DEFAULT_ON
switch:
- platform: homeassistant
id: dining_light_switch
entity_id: switch.dining_room_light
internal: true
- platform: homeassistant
id: entry_light_switch
entity_id: switch.entryway_light
internal: true
- platform: homeassistant
id: hallway_light_switch
entity_id: switch.hallway_light
internal: true
- platform: homeassistant
id: kitchen_light_switch
entity_id: switch.kitchen_light
internal: true
- platform: homeassistant
id: living_light_switch
entity_id: switch.living_room_lamp
internal: true
- platform: homeassistant
id: stairs_light_switch
entity_id: switch.stair_light
internal: true
lock:
- platform: template
name: "Front Door Lock"
id: front_door_lock
lock_action:
- logger.log: "Door Locked"
unlock_action:
- logger.log: "Door Unlocked"
# -------------------------------
# LVGL Display
# -------------------------------
display:
- platform: mipi_dsi
model: JC8012P4A1
id: my_display
update_interval: 1s
reset_pin: GPIO27
rotation: 180
auto_clear_enabled: false
color_order: RGB
dimensions:
width: 800
height: 1280
i2c:
- id: i2c_bus
sda: GPIO7
scl: GPIO8
scan: true
frequency: 400kHz
i2c_device:
- id: i2cdev1
address: 0x18
- id: i2cdev2
address: 0x32
- id: i2cdev3
address: 0x36
- id: i2cdev4
address: 0x40
touchscreen:
- platform: gsl3680
id: touchscreen_
reset_pin: GPIO22
interrupt_pin: GPIO21
transform:
swap_xy: false
mirror_x: true
mirror_y: true
on_touch:
- light.turn_on: backlight
- lvgl.widget.redraw:
font:
- file: "fonts/arial.ttf"
id: my_font
size: 40
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs:
- ${mdi_wifi}
- ${mdi_wifi_off}
- ${mdi_power}
- ${mdi_thermometer}
- ${mdi_lock_locked}
- ${mdi_lock_unlocked}
- file: "fonts/arial.ttf"
id: font_medium
size: 24
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs:
- ${mdi_wifi}
- ${mdi_wifi_off}
- ${mdi_power}
- ${mdi_thermometer}
- ${mdi_lock_locked}
- ${mdi_lock_unlocked}
- file: "fonts/arial.ttf"
id: font_large
size: 32
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs:
- ${mdi_wifi}
- ${mdi_wifi_off}
- ${mdi_power}
- ${mdi_thermometer}
- ${mdi_lock_locked}
- ${mdi_lock_unlocked}
- file: "fonts/arial.ttf"
id: font_small
size: 16
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs:
- ${mdi_wifi}
- ${mdi_wifi_off}
- ${mdi_power}
- ${mdi_thermometer}
- ${mdi_lock_locked}
- ${mdi_lock_unlocked}
- file: "fonts/arial.ttf"
id: font_very_small
size: 10
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs:
- ${mdi_wifi}
- ${mdi_wifi_off}
- ${mdi_power}
- ${mdi_thermometer}
- ${mdi_lock_locked}
- ${mdi_lock_unlocked}
- file: "fonts/arial.ttf"
id: font_very_large
size: 60
extras:
- file: "fonts/materialdesignicons-webfont.ttf"
glyphs:
- ${mdi_wifi}
- ${mdi_wifi_off}
- ${mdi_power}
- ${mdi_thermometer}
- ${mdi_lock_locked}
- ${mdi_lock_unlocked}
image:
defaults:
type: rgb565
# zzzz
images:
- file: https://esphome.io/_images/logo.png
id: esphome_logo
resize: 200x162
online_image:
- url: http://192.168.0.7:8123/local/snapshot.jpg
type: RGB565
format: JPEG
id: door_snapshot
resize: 340x200
update_interval: 30s
byte_order: LITTLE_ENDIAN
time:
- platform: sntp
id: sntp_time
timezone: America/Toronto
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
on_time_sync:
- script.execute: time_update
on_time:
- minutes: '*'
seconds: 0
then:
- script.execute: time_update
script:
- id: time_update
then:
- lvgl.label.update:
id: display_time
text: !lambda |-
static char time_buf[17];
auto now = id(sntp_time).now();
snprintf(time_buf, sizeof(time_buf), "%02d:%02d", now.hour, now.minute);
return time_buf;
lvgl:
buffer_size: 100%
byte_order: little_endian
touchscreens:
- touchscreen_id: touchscreen_
on_idle:
- timeout: 10s
then:
- logger.log: idle timeout
- light.turn_off:
id: backlight
transition_length: 5s
color_depth: 16
bg_color: 0x000000
border_width: 0
style_definitions:
- id: header_footer
bg_color: 0x2F8CD8
bg_grad_color: 0x005782
bg_grad_dir: VER
bg_opa: COVER
border_opa: TRANSP
radius: 0
pad_all: 0
pad_row: 0
pad_column: 0
border_color: 0x0077b3
text_color: 0xFFFFFF
width: 100%
height: 50
- id: advanced_btn_style
text_color: 0xD5D5D5
bg_color: 0x222222
bg_opa: COVER
radius: 20
outline_width: 0
border_width: 0
#border_opa:
pad_all: 0
# --- Base Styles ---
- id: base_panel_style
bg_color: 0x000000
border_width: 0
radius: 0
pad_all: 0
# --- Section Styles ---
- id: section_panel_style
bg_color: 0x111111
border_width: 1
border_color: 0x444444
radius: 10
pad_all: 0
# --- Label Styles ---
- id: title_label_style
text_font: font_medium
text_color: 0xCCCCCC
align: CENTER
bg_opa: TRANSP
- id: sensor_value_style
text_font: font_very_small
text_color: 0xFFFFFF
align: CENTER
bg_opa: TRANSP
- id: sensor_value_style2
text_font: font_very_small
text_color: 0x89FF88
align: CENTER
bg_opa: TRANSP
- id: button_label_style
text_font: font_medium
text_color: 0xFFFFFF
align: CENTER
bg_opa: TRANSP
- id: button_label_style2
text_font: font_small
text_color: 0xFFFFFF
align: CENTER
bg_opa: TRANSP
# --- Button Style ---
- id: button_style
bg_color: 0x00ABCD #0x0000FF
radius: 15
border_width: 1
border_color: 0xCCCCCC
pad_all: 10
top_layer:
widgets:
- buttonmatrix:
align: bottom_mid
styles: header_footer
pad_all: 0
outline_width: 0
id: top_layer
items:
styles: header_footer
rows:
- buttons:
- id: page_prev
text: "\uF053"
on_press:
then:
lvgl.page.previous:
- id: page_home
text: "\uF015"
on_press:
then:
lvgl.page.show: main_page
- id: page_next
text: "\uF054"
on_press:
then:
lvgl.page.next:
- label:
id: ha_status_icon_label
hidden: false
align: top_right
x: -75
y: 0
text_align: right
text_color: ${color_warning}
text: ${mdi_wifi_off}
text_font: font_very_small
- label:
id: temp_value_label
styles: sensor_value_style
align: TOP_LEFT
x: 35
- label:
id: outtemp_value_label
styles: sensor_value_style
align: TOP_LEFT
x: 90
- label:
text: "--:--"
id: display_time
styles: sensor_value_style2
align: TOP_RIGHT
x: -35
pages:
- id: main_page
widgets:
# --- Main Container ---
- obj:
id: main_screen
styles: base_panel_style
width: 800
height: 480
widgets:
# === Left Panel (Sensors) ===
- obj:
id: left_panel
styles: base_panel_style
width: 360
height: 470
align: TOP_LEFT
x: 35
y: 15
widgets:
# --- Temperature Section ---
- obj:
id: lock_section
styles: section_panel_style
width: 360
height: 225
align: TOP_MID
widgets:
- label:
id: lock_status_icon_label
hidden: false
align: CENTER
x: 0
y: 0
text_align: CENTER
text_color: ${color_warning}
text: ${mdi_lock_locked}
text_font: font_very_large
- label:
styles: title_label_style
align: TOP_MID
y: 5
text: "Front Door Lock"
# --- Humidity Section ---
- obj:
id: humidity_section
styles: section_panel_style
bg_image_src: door_snapshot
width: 360
height: 205
y: -20
align: BOTTOM_MID
widgets:
- label:
styles: title_label_style
align: TOP_MID
text: "Last Door Event"
# === Right Panel (Buttons & Counter) ===
- obj:
id: right_panel
styles: base_panel_style
width: 360
height: 470
align: TOP_RIGHT
x: -35
y: 15
bg_color: 0x222222
widgets:
# --- Toggle Buttons Section ---
- obj:
id: toggle_buttons_section
styles: section_panel_style
width: 360
height: 200
align: TOP_MID
bg_color: 0x222222
layout: # Layout is a dictionary
type: flex
flex_flow: COLUMN
flex_align_main: SPACE_EVENLY
flex_align_cross: CENTER
flex_align_track: CENTER
pad_column: 10
widgets:
# --- Button 1: Test Light ---
- button:
id: dining_light_toggle_btn
styles: advanced_btn_style #button_style
width: 250
height: 50
on_click:
then:
- switch.toggle: dining_light_switch
- logger.log: "Toggled 1 via HA service"
- if:
condition:
switch.is_off: dining_light_switch
then:
- lvgl.button.update:
id: dining_light_toggle_btn
bg_color: "0xff4500"
else:
- lvgl.button.update:
id: dining_light_toggle_btn
bg_color: "0x222222"
widgets:
- label:
styles: button_label_style
text: "Dining Room"
# --- Button 2: Placeholder ---
- button:
id: kitchen_light_toggle_btn
styles: advanced_btn_style #button_style
width: 250
height: 50
on_click:
then:
- switch.toggle: kitchen_light_switch
- logger.log: "Toggled 2 via HA service"
- if:
condition:
switch.is_off: kitchen_light_switch
then:
- lvgl.button.update:
id: kitchen_light_toggle_btn
bg_color: "0xff4500"
else:
- lvgl.button.update:
id: kitchen_light_toggle_btn
bg_color: "0x222222"
widgets:
- label:
styles: button_label_style
text: "Kitchen"
# --- Button 3: Placeholder ---
- button:
id: living_light_toggle_btn
styles: advanced_btn_style #button_style
width: 250
height: 50
on_click:
then:
- switch.toggle: living_light_switch
- logger.log: "Toggled 3 via HA service"
- if:
condition:
switch.is_off: living_light_switch
then:
- lvgl.button.update:
id: living_light_toggle_btn
bg_color: "0xff4500"
else:
- lvgl.button.update:
id: living_light_toggle_btn
bg_color: "0x222222"
widgets:
- label:
styles: button_label_style
text: "Living Room"
# --- Counter Section ---
- obj:
id: counter_section
styles: section_panel_style
width: 360
height: 240
y: -10
align: BOTTOM_MID
widgets:
# Counter Display Label
- label:
id: counter_display
styles: sensor_value_style
width: 330
align: TOP_MID
x: 15
y: 15
text: !lambda 'return "Counter: " + std::to_string(id(counter));'
# Counter Buttons Container
- obj:
id: counter_buttons_container
width: 330
height: 80
align: BOTTOM_MID
y: -20
layout:
type: flex
flex_flow: ROW
flex_align_main: SPACE_EVENLY
flex_align_cross: CENTER
flex_align_track: CENTER
pad_column: 10
bg_color: 0x222222
widgets:
# Increment Button
- button:
id: increment_btn
styles: button_style
width: 70
height: 60
on_press:
then:
- lambda: |-
id(counter)++;
lv_label_set_text(id(counter_display), ("Counter: " + std::to_string(id(counter))).c_str());
widgets:
- label:
styles: button_label_style
text: "+"
# Reset Button
- button:
id: reset_btn
styles: advanced_btn_style #button_style
width: 90
height: 60
on_press:
then:
- lambda: |-
id(counter) = 0;
lv_label_set_text(id(counter_display), ("Counter: " + std::to_string(id(counter))).c_str());
widgets:
- label:
styles: button_label_style
text: "Reset"
# Decrement Button
- button:
id: decrement_btn
styles: button_style
width: 70
height: 60
on_press:
then:
- lambda: |-
id(counter)--;
lv_label_set_text(id(counter_display), ("Counter: " + std::to_string(id(counter))).c_str());
widgets:
- label:
styles: button_label_style
text: "-"
- id: second_page
widgets:
# --- Main Container ---
- obj:
id: main_screen2
styles: base_panel_style
width: 800
height: 480
widgets:
- label:
text: "Settings"
styles: button_label_style
align: TOP_MID
- slider:
id: dimmer_slider
align: RIGHT_MID
x: -67
#y: 50
width: 30
height: 220
pad_all: 8
min_value: 1
max_value: 10
value: 8
on_change:
- light.turn_on:
id: backlight
brightness: !lambda |-
return x / 10.0;
- label:
text: "Backlight"
styles: button_label_style2
align: RIGHT_MID
x: -50
y: -175
- label:
text: "Max"
styles: sensor_value_style2
align: RIGHT_MID
x: -73
y: -130
- label:
text: "Off"
styles: sensor_value_style2
align: RIGHT_MID
x: -73
y: 115
audio_dac:
- platform: es8311
id: es8311_dac
bits_per_sample: 16bit
sample_rate: 16000
use_microphone: True
i2s_audio:
- id: i2s_output
i2s_lrclk_pin: GPIO10
i2s_bclk_pin: GPIO12
i2s_mclk_pin: GPIO13
speaker:
- platform: i2s_audio
i2s_audio_id: i2s_output
id: p4_speaker
i2s_dout_pin: GPIO9
dac_type: external
sample_rate: 16000
bits_per_sample: 16bit
channel: stereo
audio_dac: es8311_dac
- platform: mixer
id: mixer_speaker_id
output_speaker: p4_speaker
source_speakers:
- id: announcement_spk_mixer_input
- id: media_spk_mixer_input
- platform: resampler
id: media_spk_resampling_input
output_speaker: media_spk_mixer_input
- platform: resampler
id: announcement_spk_resampling_input
output_speaker: announcement_spk_mixer_input
media_player:
- platform: speaker
name: "Speaker Media Player"
id: speaker_media_player_id
media_pipeline:
speaker: media_spk_resampling_input
num_channels: 2
announcement_pipeline:
speaker: announcement_spk_resampling_input
num_channels: 1
microphone:
- platform: i2s_audio
id: p4_microphone
i2s_din_pin: GPIO11
sample_rate: 16000
bits_per_sample: 16bit
adc_type: external
#audio_adc:
# - platform: es8311
# id: es8311_adc
# bits_per_sample: 16bit
# sample_rate: 16000
No DSI or RGB controllers support hardware rotation (since the driver chip does not host the display buffer.)
katzrydz
(Katzrydz)
October 13, 2025, 7:45pm
4
Clyde,
Thank you for the input. Do you have any insights on Camera Serial Interface (CSI) implementation?
Kat
No, sorry, have not looked at that at all. There is discussion on Discord in the P4 thread.
KrX
(KrX)
October 13, 2025, 8:11pm
6
katzrydz:
hi, im reposting the link i got for my device from the seller at aliexpress:
http://pan.jczn1688.com/1/HMI%20display
and as i mentioned on the other thread, on the link the zip package for the JC8012P4A1C was updated last month and it now contains an example for SW rotation under \1-Demo\arduino-examples\Arduino_lvgl_sw_rotation
if that helps
DJFliX
(Felix Mann)
October 26, 2025, 8:14pm
7
Hey! Thanks for your example code. I figured some parts out on my own, but this helped me immensely in getting my “hello world” dashboard running. I’m still trying to figure out the best way to do layout, but for now I’ve settled on using “flex” for the left and right container. That way I can add more components as I go without having to think about their exact positioning.
For my particular screen I had to turn off mirror_x since with it enabled my touchscreen was indeed mirrored.
Over the coming weeks I’ll try to clean up my dashboard code and share it. Right now it contains too many commented out parts from your code that I won’t be using for my particular use case.
Thanks again and hope to hear if you came up with any improvements on your end