Compare commits

..

31 Commits

Author SHA1 Message Date
Adolfo Reyna 1a96307de2 feat(rlcd): Waveshare ESP32-S3-RLCD-4.2 support on latest main
- ST7305 driver with persistent 15KB DMA buffer (fix use-after-free +
  WDT lockup that caused freeze after flash)
- Reset timing fix: 150ms after reset, 50ms after init
- DTS: i2s0 mclk 16, bclk 9, ws 45, out 8, in 10 - fixes GPIO5 conflict
- i2c0 uses esp32-i2c-master, SDMMC 1-bit
- device.properties: colorDepth 16, fontSize 20, DefaultDark
- Amp GPIO46 init in initBoot
- Buttons: two-button control GPIO18 (cycle) + GPIO0 (select)

Base: origin/main f9453d89
2026-07-18 22:44:53 -04:00
Ken Van Hoeylandt f9453d8956 Migrate devices, create drivers, other improvements & fixes (#574)
Migrated devices to kernel drivers:

- guition-jc3248w535c
- m5stack-core2
- m5stack-cores3
- m5stack-papers3

New drivers:

- axp192-module
- axp2101-module

Fixes:

- Fix SD card LDO for P4 devices
- Updated PowerOff app to work with kernel displays
- Fix for `lvgl_try_lock()` timing
- Fix for touch events with slow updating displays

Improvements:

- `GuiService` now keeps trying to lock to prevent silent failures caused by drivers.
- `GuiService` now uses lvgl-module calls for locking/unlocking
- display driver now has capability `DISPLAY_CAPABILITY_SLOW_REFRESH`
2026-07-19 00:39:26 +02:00
Ken Van Hoeylandt 5f54f7ca3d Fix for SDMMC driver on ESP32-P4 (#572)
The driver was using the incorrect (read: old) if-defs for a capability check.
2026-07-18 15:58:48 +02:00
Ken Van Hoeylandt d896657bf9 Device migrations, drivers and fixes (#571)
Device migrations:

- cyd-4848S040c
- guition-jc1060p470ciwy
- guition-jc2432w328c
- guition-jc3248w535c (known issue with display and touch, Shadowtrance will look into it)
- guition-jc8048w550c
- heltec-wifi-lora-32-v3
- lilygo-tdeck-max (excluding graphics)
- lilygo-tdisplay
- lilygo-tdisplay-s3
- lilygo-tdongle-s3
- lilygo-tlora-pager

Driver migrations:

- Implemented haptic driver interface in kernel
- AXS15231b
- BQ25896
- BQ27220
- CST328
- CST6xx
- DRV2605
- JD9165
- Custom LilyGO driver for T-Lora Pager
- SSD1306
- ST7701
- ST7735
- SY6970
- TCA8418

Fixes/improvements:

- Boot app: support for multiple power devices, improved UI
- lvgl_devices and related code: fixes for mapping
- Support for arrays in dts parser
2026-07-18 15:01:42 +02:00
Ken Van Hoeylandt 3b5a401594 Device migrations, new drivers, cleanup (#567)
* **New Features**
  * Added native display support for ST7796, ILI9341, and ST7789 panels across supported boards.
  * Added FT5x06 and FT6x36 touchscreen support.
  * Generic PWM driver
  * ESP32 PWM driver
  * Generic RGB LED driver
  * RGB PWM LED driver
  * RGB GPIO LED driver
  * Implementation of RGB LED for various boards

* **Improvements**
  * Updated board hardware descriptions to use explicit display/touch/backlight device-tree bindings and disabled deprecated HAL usage.
  * Improved display and touch-driver cleanup to prevent stale resources and improve shutdown reliability.
  * Pinned esp-hosted library to a fixed version
 
* **Deletions**
  * Obsolete placeholder display
  * Legacy ILI9488 support.
  * ESP32-specific LEDC PWM implementation
2026-07-16 22:47:26 +02:00
Ken Van Hoeylandt 6fb2bb736c Drivers, device migrations and other improvements (#566)
- RGB display driver added
- display_driver API:
  - Added software-based display rotation for screens without hardware rotation support.
  - Improved display capability detection across supported display drivers.
- lvgl_display driver:
  - Improved framebuffer handling for smoother, more reliable display updates.
  - Display gap and rotation behavior now adapts more accurately to hardware capabilities.
- Migration Crowpanel 5" basic & advance to kernel drivers
- Improve KernelDisplay app: brightness controls are hidden for displays that only support on/off operation
- device.py now allows for (non-ambiguous) partial device IDs
- TactilityKernel: Implement more tests
2026-07-15 22:56:21 +02:00
Ken Van Hoeylandt bd8fdfd858 Device migrations and driver implementations (#564) 2026-07-15 12:46:24 +02:00
Ken Van Hoeylandt 8af6204ba1 New kernel drivers and device migrations (#563) 2026-07-14 20:26:57 +02:00
Shadowtrance 955416dac8 Audio System + Drivers (#562) 2026-07-14 08:34:29 +02:00
Ken Van Hoeylandt fa4a6e255c New kernel drivers and device implementation updates (#561)
- Added modular device support and devicetree bindings for ILI9341, ILI9488, CST816S, XPT2046, and GPIO button input, updating several board configurations for display/touch/backlight/keyboard/battery.
- Added a setting to control deprecated HAL usage (device property + Kconfig).
2026-07-12 23:54:55 +02:00
Ken Van Hoeylandt 50c0a14a93 New kernel drivers and more (#560)
- Added kernel base drivers for: display, pointer (touch, mouse, etc.), keyboard, adc, power supply and backlight
- Implement new kernel driver modules: `st7789-module` and `gt911-module`
- Implement ESP32 ADC "oneshot" kernel driver
- Implement ESP32  backlight kernel driver with ledc API
- Implemented `battery-sense` driver that allows for voltage measurement and creates a power supply child device
- Updated github actions
- Updated flash scripts
- Fix for esp32 legacy driver conflict with ADC
- Created separate `lilygo-tdeck` and `lilygo-tdeck-plus` devices
- Created `lilygo-module` with LilyGO kernel drivers
- Fix for intermittent errors in build related to code generation of `devicetree.c`
- `lvgl-module` can now map kernel drivers onto LVGL devices
- Created `KernelDisplayApp` as a mirror of `HalDisplayApp` (formerly `DisplayApp`)
- Removed `struct` and `enum` prefix in a lot of kernel driver cpp source files
- `lilygo-tdeck` and `lilygo-tdeck-plus` are now fully relying on kernel drivers and don't use any of the old HAL
2026-07-12 00:29:12 +02:00
Ken Van Hoeylandt c4406b24ba Fixes and improvements (#559)
- **Fixes**
  - Added missing Wi-Fi hardware configuration support for P4 devices.
  - Fixed build warning
  - Fixed build wrt Tab5

- **Changes**
  - M5Stack StickS3: Switched default storage location from SD to Internal
  - M5Stack StickS3: Removed DIY SD card support over SPI
  - M5Stack StickC Plus2: Removed the automatic startup of the web server
2026-07-10 18:19:11 +02:00
Crazypedia 0922c4d55b Show a confirmed shutdown screen before cutting power (#555) 2026-07-10 08:49:46 +02:00
Shadowtrance 7a7f09be35 Tab5 camera + other stuff (#558)
* Tab5 camera + other stuff

Tab5 camera driver - SC2356
Custom SliderBox widget - slider with plus and minus buttons + value label and snapping
Rtc Time service + rtc api
Sdk release - only include drivers built for that specific target, eg: sc2356 driver is mipi / p4 only.
No more hardcoded manual sdk cmakelists
New function to find device by compatible string match. no more static cast bool wildness when trying to match a single device (like M5Stack PaperS3 for example)

* feedback + fixes

Fixed external app user data path.
fix(gui): block app teardown until onHide() completes, preventing ELF unload racing a still-running app
added camera device type and api

* drain the snake sssem

---------

Co-authored-by: Ken Van Hoeylandt <git@kenvanhoeylandt.net>
2026-07-10 08:45:03 +02:00
Crazypedia 16a61a087c Add power device (battery + power-off) to lilygo-tdeck-max (#553) 2026-07-09 22:55:14 +02:00
Ken Van Hoeylandt 1c2806bddf Added WiFi kernel drivers and refactored Wifi service (#557)
+ other improvements
2026-07-09 21:03:38 +02:00
Ken Van Hoeylandt dbb96a891c Generate device matrix and add missing symbol (#556) 2026-07-08 08:58:45 +02:00
Crazypedia d6ac070e30 Add LilyGO T-Deck Max (e-paper) base board support (#552) 2026-07-08 08:40:09 +02:00
Ken Van Hoeylandt f4f91f81d6 Service logic moved to kernel (#554)
+ fix BT service file paths
2026-07-07 22:52:19 +02:00
Crazypedia cca7224252 fix(tests): repair stale TestFile.h includes and stop hardcoding g++ in test CMakeLists (#551)
PR #550 moved TestFile.h from Tests/TactilityCore to Tests/Tactility, but
AppManifestParsingTest.cpp and PropertiesFileTest.cpp still include the old
path, so the test build fails on main.
2026-07-05 22:05:54 +02:00
Ken Van Hoeylandt 66a4eb66d6 Remove TactilityCore (#550) 2026-07-05 12:47:37 +02:00
Ken Van Hoeylandt dfaeb9a2d9 Crypt module (#549)
- Moved cryptography code out of Tactility project and into a kernel module.
- Converted C++ code to C style interface
- Hardened security
2026-07-05 11:17:42 +02:00
Ken Van Hoeylandt 9d5993930d Replaced Logger usage with LOG_x (#548) 2026-07-04 23:49:19 +02:00
Ken Van Hoeylandt ecad2248d9 Various improvements (#547)
- Fixed crash when returning to Setup app (from any of the steps)
- Fixed crash when returning to TimeDateSettings app (after locale selection)
- Fixed GuiService inconsistent behaviour: now always perform operations async (e.g. to show/hide apps). This fixes crashes in some onHide() calls where onHide() might be called before onShow() was called.
- Fix for incorrect WebServService path
- Remove CYD-4848S040C SD card functionality, but added a GPIO fix for releasing 3-wire SPI pin sharing.
- Fix for saving/loading settings for various apps
2026-07-04 21:26:43 +02:00
Ken Van Hoeylandt a323f8e148 Implement SD card for WaveShare S3 Touch LCD 4.3" (#546) 2026-07-04 09:28:31 +02:00
Ken Van Hoeylandt 05720821f8 Require SD card or >4MB flash (#545) 2026-07-03 23:56:03 +02:00
Ken Van Hoeylandt 90afba647e Update properties parsing for app manifest and device manifest files (#544) 2026-07-03 00:29:01 +02:00
Ken Van Hoeylandt 35fd7dd536 Post-release changes (#543)
- Update version to 0.8.0-dev
- Add new release scripts
- Update release docs
2026-07-02 20:52:26 +02:00
Ken Van Hoeylandt cd07c64926 Release 0.7.0 (#542) 2026-07-02 17:34:40 +02:00
Ken Van Hoeylandt 2f5e183f18 Setup app (#541)
- Implement Setup app for device's first boot
- Implement device simple name and vendor name variables
- Remove region setting (locale setting is already available)
2026-07-02 00:29:03 +02:00
Ken Van Hoeylandt d3439f6f45 Fixes & memory optimizations (#540)
- Disable BlueTooth driver by default, to ensure it doesn't allocate memory
- Update BlueTooth settings app behaviour to make sure it starts/stops the devices
- Disable SPI RAM usage for ST7789 as it broke App Hub
- Reduce T-Display and T-Deck display buffers from 1/3rd to 1/10th of resolution
- Enabled dynamic buffers for MbedTLS to optimize memory
- TLS 1.3 did not work with dynamic buffers: downgrade to 1.2 for now
- WiFi is now enabled from the Boot app callback to the WiFi service, instead of the WiFi service start() function. This avoids a lockup when WiFi is started by the service while the Boot app is updating the WiFi settings.
2026-07-01 21:11:46 +02:00
1426 changed files with 55166 additions and 22956 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ inputs:
runs:
using: "composite"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: recursive
- name: 'Board select'
+1 -1
View File
@@ -11,7 +11,7 @@ inputs:
runs:
using: "composite"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: recursive
- name: 'Board select'
+1 -1
View File
@@ -15,7 +15,7 @@ runs:
using: "composite"
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
submodules: recursive
- name: Install Linux Dependencies for SDL
+6 -2
View File
@@ -10,7 +10,9 @@ jobs:
Linux:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Build"
uses: ./.github/actions/build-simulator
with:
@@ -20,7 +22,9 @@ jobs:
macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Build"
uses: ./.github/actions/build-simulator
with:
+26 -56
View File
@@ -22,66 +22,34 @@ jobs:
]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Build SDK"
uses: ./.github/actions/build-sdk
with:
board_id: ${{ matrix.board.id }}
arch: ${{ matrix.board.arch }}
BuildFirmware:
strategy:
matrix:
board: [
{ id: btt-panda-touch, arch: esp32s3 },
{ id: cyd-2432s024c, arch: esp32 },
{ id: cyd-2432s024r, arch: esp32 },
{ id: cyd-2432s028r, arch: esp32 },
{ id: cyd-2432s028rv3, arch: esp32 },
{ id: cyd-e32r28t, arch: esp32 },
{ id: cyd-e32r32p, arch: esp32 },
{ id: cyd-2432s032c, arch: esp32 },
{ id: cyd-3248s035c, arch: esp32 },
{ id: cyd-8048s043c, arch: esp32s3 },
{ id: cyd-4848s040c, arch: esp32s3 },
{ id: elecrow-crowpanel-advance-28, arch: esp32s3 },
{ id: elecrow-crowpanel-advance-35, arch: esp32s3 },
{ id: elecrow-crowpanel-advance-50, arch: esp32s3 },
{ id: elecrow-crowpanel-basic-28, arch: esp32 },
{ id: elecrow-crowpanel-basic-35, arch: esp32 },
{ id: elecrow-crowpanel-basic-50, arch: esp32s3 },
{ id: guition-jc1060p470ciwy, arch: esp32p4 },
{ id: guition-jc2432w328c, arch: esp32 },
{ id: guition-jc3248w535c, arch: esp32s3 },
{ id: guition-jc8048w550c, arch: esp32s3 },
{ id: heltec-wifi-lora-32-v3, arch: esp32s3 },
{ id: lilygo-tdeck, arch: esp32s3 },
{ id: lilygo-thmi, arch: esp32s3 },
{ id: lilygo-tdongle-s3, arch: esp32s3 },
{ id: lilygo-tdisplay-s3, arch: esp32s3 },
{ id: lilygo-tlora-pager, arch: esp32s3 },
{ id: lilygo-tdisplay, arch: esp32 },
{ id: m5stack-cardputer, arch: esp32s3 },
{ id: m5stack-cardputer-adv, arch: esp32s3 },
{ id: m5stack-core2, arch: esp32 },
{ id: m5stack-cores3, arch: esp32s3 },
{ id: m5stack-papers3, arch: esp32s3 },
{ id: m5stack-stackchan, arch: esp32s3 },
{ id: m5stack-stickc-plus, arch: esp32 },
{ id: m5stack-stickc-plus2, arch: esp32 },
{ id: m5stack-sticks3, arch: esp32s3 },
{ id: m5stack-tab5, arch: esp32p4 },
{ id: unphone, arch: esp32s3 },
{ id: waveshare-esp32-s3-geek, arch: esp32s3 },
{ id: waveshare-s3-lcd-13, arch: esp32s3 },
{ id: waveshare-s3-touch-lcd-128, arch: esp32s3 },
{ id: waveshare-s3-touch-lcd-147, arch: esp32s3 },
{ id: waveshare-s3-touch-lcd-43, arch: esp32s3 },
{ id: wireless-tag-wt32-sc01-plus, arch: esp32s3 }
]
GenerateDeviceMatrix:
runs-on: ubuntu-latest
needs: [ BuildSdk ]
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- id: set-matrix
run: python3 Buildscripts/gh-generate-device-matrix.py
BuildFirmware:
runs-on: ubuntu-latest
needs: GenerateDeviceMatrix
strategy:
matrix: ${{ fromJSON(needs.GenerateDeviceMatrix.outputs.matrix) }}
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Build Firmware"
uses: ./.github/actions/build-firmware
with:
@@ -94,7 +62,9 @@ jobs:
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Bundle Artifacts"
uses: ./.github/actions/bundle-artifacts
PublishFirmwareSnapshot:
@@ -102,7 +72,7 @@ jobs:
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: "Publish Firmware Snapshot"
env:
CDN_ID: ${{ secrets.CDN_ID }}
@@ -116,7 +86,7 @@ jobs:
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: "Publish Firmware Stable"
env:
CDN_ID: ${{ secrets.CDN_ID }}
@@ -130,7 +100,7 @@ jobs:
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: "Publish SDKs"
env:
CDN_ID: ${{ secrets.CDN_ID }}
+6 -6
View File
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
submodules: recursive
- name: "Configure Project"
@@ -19,20 +19,20 @@ jobs:
run: cmake -S ./ -B build
- name: "Build Tests"
run: cmake --build build --target build-tests
- name: "Run TactilityCore Tests"
run: build/Tests/TactilityCore/TactilityCoreTests
- name: "Run TactilityFreeRtos Tests"
run: build/Tests/TactilityFreeRtos/TactilityFreeRtosTests
- name: "Run TactilityHeadless Tests"
- name: "Run Tactility Tests"
run: build/Tests/Tactility/TactilityTests
- name: "Run TactilityKernel Tests"
run: build/Tests/TactilityKernel/TactilityKernelTests
- name: "Run CryptModuleTests Tests"
run: build/Tests/crypt-module/CryptModuleTests
DevicetreeTests:
runs-on: ubuntu-latest
steps:
- name: "Checkout repo"
uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
persist-credentials: false
submodules: recursive
- name: "Install Python Dependencies"
shell: bash
+1
View File
@@ -3,6 +3,7 @@
build/
buildsim/
build-*/
cmake-*/
CMakeCache.txt
*.cbp
+21 -26
View File
@@ -2,11 +2,9 @@ import subprocess
from datetime import datetime, UTC
import os
import sys
import configparser
from dataclasses import dataclass, asdict
import json
import shutil
from configparser import RawConfigParser
VERBOSE = False
DEVICES_FOLDER = "Devices"
@@ -68,32 +66,29 @@ def exit_with_error(message):
sys.exit(1)
def read_properties_file(path):
config = configparser.RawConfigParser()
# Don't convert keys to lowercase
config.optionxform = str
config.read(path)
return config
properties = {}
with open(path, "r") as file:
for line in file:
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
key, sep, value = line.partition("=")
if not sep:
continue
properties[key.strip()] = value.strip()
return properties
def get_property_or_none(properties: RawConfigParser, group: str, key: str):
if group not in properties.sections():
return None
if key not in properties[group].keys():
return None
return properties[group][key]
def get_property_or_none(properties: dict, group: str, key: str):
return properties.get(f"{group}.{key}")
def get_boolean_property_or_false(properties: RawConfigParser, group: str, key: str):
if group not in properties.sections():
return False
if key not in properties[group].keys():
return False
return properties[group][key] == "true"
def get_boolean_property_or_false(properties: dict, group: str, key: str):
return properties.get(f"{group}.{key}") == "true"
def get_property_or_exit(properties: RawConfigParser, group: str, key: str):
if group not in properties.sections():
exit_with_error(f"Device properties does not contain group: {group}")
if key not in properties[group].keys():
exit_with_error(f"Device properties does not contain key: {key}")
return properties[group][key]
def get_property_or_exit(properties: dict, group: str, key: str):
full_key = f"{group}.{key}"
if full_key not in properties:
exit_with_error(f"Device properties does not contain key: {full_key}")
return properties[full_key]
def read_device_properties(device_id):
mapping_file_path = os.path.join(DEVICES_FOLDER, device_id, "device.properties")
@@ -129,7 +124,7 @@ def to_manifest_chip_name(name):
return ""
def process_device(in_path: str, out_path: str, device_directory: str, device_id: str, device_properties: RawConfigParser, version: str):
def process_device(in_path: str, out_path: str, device_directory: str, device_id: str, device_properties: dict, version: str):
in_device_path = os.path.join(in_path, device_directory)
in_device_binaries_path = os.path.join(in_device_path, "Binaries")
if not os.path.isdir(in_device_binaries_path):
@@ -46,6 +46,8 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding:
description=details.get('description', '').strip(),
default=details.get('default', None),
element_type=details.get('element-type', None),
min=details.get('min', None),
max=details.get('max', None),
)
properties_dict[name] = prop
filename = os.path.basename(file_path)
@@ -79,6 +79,11 @@ def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
value_list.append(str(item))
return "{ " + ",".join(value_list) + " }"
elif type == "phandle":
# Mirrors the string-passthrough convention "phandles" already uses for sentinel defaults
# like GPIO_PIN_SPEC_NONE: a binding default of "NULL" represents "no device referenced",
# not an actual node name to resolve.
if isinstance(property.value, str) and property.value == "NULL":
return "NULL"
return find_phandle(devices, property.value)
elif type == "phandles":
value_list = list()
@@ -113,6 +118,25 @@ def resolve_phandle_array_entries(device_property, devices):
entries.append(str(item))
return entries
def validate_property_range(device: Device, binding_property, value) -> None:
"""Enforces a binding's optional min/max on int-typed properties. Silently skips
values that aren't parseable as a plain integer literal (e.g. a passed-through
symbolic #define) - those can't be range-checked at compile time."""
if binding_property.min is None and binding_property.max is None:
return
try:
numeric_value = int(value, 0) if isinstance(value, str) else int(value)
except (TypeError, ValueError):
return
if binding_property.min is not None and numeric_value < binding_property.min:
raise DevicetreeException(
f"Device '{device.node_name}' property '{binding_property.name}' value {numeric_value} is below minimum {binding_property.min}"
)
if binding_property.max is not None and numeric_value > binding_property.max:
raise DevicetreeException(
f"Device '{device.node_name}' property '{binding_property.name}' value {numeric_value} is above maximum {binding_property.max}"
)
def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], devices: list[Device]) -> list:
compatible_property = find_device_property(device, "compatible")
if compatible_property is None:
@@ -137,7 +161,7 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
node_name = get_device_node_name_safe(device)
result = []
phandle_arrays = []
array_decls = []
for binding_property in binding_properties:
device_property = find_device_property(device, binding_property.name)
@@ -148,7 +172,35 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
array_var = f"{node_name}_{prop_safe}"
if device_property is not None:
entries = resolve_phandle_array_entries(device_property, devices)
phandle_arrays.append((array_var, binding_property.element_type, entries))
array_decls.append((array_var, binding_property.element_type, entries))
result.append(f"({binding_property.element_type}*){array_var}")
result.append(str(len(entries)))
elif binding_property.default is not None:
result.append("NULL")
result.append("0")
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
else:
result.append("NULL")
result.append("0")
continue
if binding_property.type == "array":
# A flat literal array (DTS `[ ... ]` syntax, e.g. a byte blob), as opposed to
# phandle-array's list of resolved device references. Emits the same
# (pointer, length) parameter pair, backed by a plain data array instead of one
# holding phandle-derived initializers.
if binding_property.element_type is None:
raise DevicetreeException(f"array property '{binding_property.name}' requires 'element-type' in binding")
prop_safe = binding_property.name.replace("-", "_")
array_var = f"{node_name}_{prop_safe}"
if device_property is not None:
if device_property.type != "array":
raise DevicetreeException(
f"Device '{device.node_name}' property '{binding_property.name}' must use '[ ... ]' array syntax"
)
entries = [str(value) for value in device_property.value]
array_decls.append((array_var, binding_property.element_type, entries))
result.append(f"({binding_property.element_type}*){array_var}")
result.append(str(len(entries)))
elif binding_property.default is not None:
@@ -163,6 +215,7 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
if device_property is None:
if binding_property.default is not None:
validate_property_range(device, binding_property, binding_property.default)
temp_prop = DeviceProperty(
name=binding_property.name,
type=binding_property.type,
@@ -179,19 +232,20 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
else:
raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set")
else:
validate_property_range(device, binding_property, device_property.value)
result.append(property_to_string(device_property, devices))
return result, phandle_arrays
return result, array_decls
def write_config(file, device: Device, bindings: list[Binding], devices: list[Device], type_name: str):
node_name = get_device_node_name_safe(device)
config_type = f"{type_name}_config_dt"
config_variable_name = f"{node_name}_config"
config_params, phandle_arrays = resolve_parameters_from_bindings(device, bindings, devices)
config_params, array_decls = resolve_parameters_from_bindings(device, bindings, devices)
# Write phandle-array variables before the config struct
for array_var, element_type, entries in phandle_arrays:
# Write phandle-array/array variables before the config struct
for array_var, element_type, entries in array_decls:
entries_str = ", ".join(entries)
file.write(f"static {element_type} {array_var}[] = {{ {entries_str} }};\n")
@@ -40,6 +40,8 @@ class BindingProperty:
description: str
default: object = None
element_type: str = None
min: object = None
max: object = None
@dataclass
class Binding:
@@ -76,6 +76,225 @@ def test_compile_invalid_dts():
print("PASSED")
return True
def write_minmax_config(tmp_dir, device_property_line, binding_min=0, binding_max=3, binding_default=1):
config_dir = os.path.join(tmp_dir, "minmax_data")
bindings_dir = os.path.join(config_dir, "bindings")
os.makedirs(bindings_dir)
with open(os.path.join(config_dir, "devicetree.yaml"), "w") as f:
f.write("dts: test.dts\nbindings: bindings")
with open(os.path.join(config_dir, "test.dts"), "w") as f:
f.write(f"""/dts-v1/;
/ {{
compatible = "test,root";
model = "Test Model";
test-device@0 {{
compatible = "test,minmax-device";
{device_property_line}
}};
}};
""")
with open(os.path.join(bindings_dir, "test,root.yaml"), "w") as f:
f.write("description: Test root binding\ncompatible: \"test,root\"\nproperties:\n model:\n type: string\n")
with open(os.path.join(bindings_dir, "test,minmax-device.yaml"), "w") as f:
f.write(f"""description: Test min/max binding
compatible: "test,minmax-device"
properties:
ranged-prop:
type: int
default: {binding_default}
min: {binding_min}
max: {binding_max}
""")
return config_dir
def test_minmax_within_range_succeeds():
print("Running test_minmax_within_range_succeeds...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_minmax_config(tmp_dir, "ranged-prop = <2>;")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False
print("PASSED")
return True
def test_minmax_below_minimum_fails():
print("Running test_minmax_below_minimum_fails...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_minmax_config(tmp_dir, "ranged-prop = <-1>;")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed for a below-minimum value")
return False
if "below minimum" not in result.stdout:
print(f"FAILED: Expected 'below minimum' error message, got: {result.stdout}")
return False
print("PASSED")
return True
def test_minmax_above_maximum_fails():
print("Running test_minmax_above_maximum_fails...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_minmax_config(tmp_dir, "ranged-prop = <7>;")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed for an above-maximum value")
return False
if "above maximum" not in result.stdout:
print(f"FAILED: Expected 'above maximum' error message, got: {result.stdout}")
return False
print("PASSED")
return True
def test_minmax_out_of_range_default_fails():
print("Running test_minmax_out_of_range_default_fails...")
with tempfile.TemporaryDirectory() as tmp_dir:
# Property omitted from the .dts entirely, so the (invalid) binding default is used.
config_dir = write_minmax_config(tmp_dir, "", binding_default=9)
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode == 0:
print("FAILED: Compilation should have failed for an out-of-range default value")
return False
if "above maximum" not in result.stdout:
print(f"FAILED: Expected 'above maximum' error message, got: {result.stdout}")
return False
print("PASSED")
return True
def test_minmax_symbolic_value_skips_validation():
print("Running test_minmax_symbolic_value_skips_validation...")
with tempfile.TemporaryDirectory() as tmp_dir:
# A passed-through symbolic constant can't be range-checked at compile time and must
# not be rejected just because a min/max is declared.
config_dir = write_minmax_config(tmp_dir, "ranged-prop = <SOME_DEFINE>;")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded for a symbolic value: {result.stderr} {result.stdout}")
return False
print("PASSED")
return True
def write_array_config(tmp_dir, device_property_line):
config_dir = os.path.join(tmp_dir, "array_data")
bindings_dir = os.path.join(config_dir, "bindings")
os.makedirs(bindings_dir)
with open(os.path.join(config_dir, "devicetree.yaml"), "w") as f:
f.write("dts: test.dts\nbindings: bindings")
with open(os.path.join(config_dir, "test.dts"), "w") as f:
f.write(f"""/dts-v1/;
/ {{
compatible = "test,root";
model = "Test Model";
test-device@0 {{
compatible = "test,array-device";
{device_property_line}
}};
}};
""")
with open(os.path.join(bindings_dir, "test,root.yaml"), "w") as f:
f.write("description: Test root binding\ncompatible: \"test,root\"\nproperties:\n model:\n type: string\n")
with open(os.path.join(bindings_dir, "test,array-device.yaml"), "w") as f:
f.write("""description: Test array binding
compatible: "test,array-device"
properties:
init-sequence:
type: array
element-type: uint8_t
""")
return config_dir
def test_array_property_generates_static_array_and_length():
print("Running test_array_property_generates_static_array_and_length...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_array_config(tmp_dir, "init-sequence = [0xFF 0x01 0x00 0x00 0x10 5 0];")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False
with open(os.path.join(output_dir, "devicetree.c")) as f:
generated = f.read()
if "static uint8_t test_device_init_sequence[] = { 0xFF, 0x01, 0x00, 0x00, 0x10, 5, 0 };" not in generated:
print(f"FAILED: Expected static array declaration not found:\n{generated}")
return False
if "(uint8_t*)test_device_init_sequence" not in generated or "\t7\n" not in generated:
print(f"FAILED: Expected (pointer, length) config params not found:\n{generated}")
return False
print("PASSED")
return True
def test_array_property_defaults_to_null_when_absent():
print("Running test_array_property_defaults_to_null_when_absent...")
with tempfile.TemporaryDirectory() as tmp_dir:
config_dir = write_array_config(tmp_dir, "")
output_dir = os.path.join(tmp_dir, "output")
os.makedirs(output_dir)
result = run_compiler(config_dir, output_dir)
if result.returncode != 0:
print(f"FAILED: Compilation should have succeeded: {result.stderr} {result.stdout}")
return False
with open(os.path.join(output_dir, "devicetree.c")) as f:
generated = f.read()
if "NULL,\n\t0" not in generated:
print(f"FAILED: Expected NULL/0 defaults not found:\n{generated}")
return False
print("PASSED")
return True
def test_compile_missing_config():
print("Running test_compile_missing_config...")
with tempfile.TemporaryDirectory() as output_dir:
@@ -96,7 +315,14 @@ if __name__ == "__main__":
tests = [
test_compile_success,
test_compile_invalid_dts,
test_compile_missing_config
test_compile_missing_config,
test_minmax_within_range_succeeds,
test_minmax_below_minimum_fails,
test_minmax_above_maximum_fails,
test_minmax_out_of_range_default_fails,
test_minmax_symbolic_value_skips_validation,
test_array_property_generates_static_array_and_length,
test_array_property_defaults_to_null_when_absent
]
failed = 0
+2 -2
View File
@@ -13,9 +13,9 @@ $jsonClean = $json.flash_files -replace '[\{\}\@\;]', ''
$jsonClean = $jsonClean -replace '[\=]', ' '
cd Binaries
$command = "esptool --port $port erase_flash"
$command = "esptool --port $port erase-flash"
Invoke-Expression $command
$command = "esptool --port $port write_flash $jsonClean"
$command = "esptool --port $port write-flash $jsonClean"
Invoke-Expression $command
cd ..
+2 -2
View File
@@ -49,7 +49,7 @@ fi
# Take the flash_arg file contents and join each line in the file into a single line
flash_args=`grep \n Binaries/flash_args | awk '{print}' ORS=' '`
cd Binaries
$esptoolPath --port $1 erase_flash
$esptoolPath --port $1 write_flash $flash_args
$esptoolPath --port $1 erase-flash
$esptoolPath --port $1 write-flash $flash_args
cd -
+1 -6
View File
@@ -5,12 +5,7 @@ idf_component_register(
"Libraries/TactilityFreeRtos/include"
"Libraries/lvgl/include"
"Modules/lvgl-module/include"
"Drivers/bm8563-module/include"
"Drivers/bmi270-module/include"
"Drivers/mpu6886-module/include"
"Drivers/pi4ioe5v6408-module/include"
"Drivers/qmi8658-module/include"
"Drivers/rx8130ce-module/include"
# DRIVER_INCLUDE_DIRS_PLACEHOLDER
REQUIRES esp_timer
)
+1 -6
View File
@@ -25,12 +25,7 @@ macro(tactility_project project_name)
set(COMPONENTS
TactilityFreeRtos
bm8563-module
bmi270-module
mpu6886-module
pi4ioe5v6408-module
qmi8658-module
rx8130ce-module
# DRIVER_COMPONENTS_PLACEHOLDER
)
endmacro()
+135
View File
@@ -0,0 +1,135 @@
#!/usr/bin/env python3
"""Download all artifacts from a GitHub Actions workflow run."""
import argparse
import os
import subprocess
import sys
import zipfile
from pathlib import Path
import requests
API_URL = "https://api.github.com"
def get_token(cli_token: str | None) -> str:
if cli_token:
return cli_token
env_token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
if env_token:
return env_token
try:
result = subprocess.run(
["gh", "auth", "token"], capture_output=True, text=True, check=True
)
return result.stdout.strip()
except (FileNotFoundError, subprocess.CalledProcessError):
sys.exit(
"No token found. Pass --token, set GITHUB_TOKEN/GH_TOKEN, or run `gh auth login`."
)
def get_repo(cli_repo: str | None) -> str:
if cli_repo:
return cli_repo
try:
result = subprocess.run(
["git", "remote", "get-url", "origin"],
capture_output=True,
text=True,
check=True,
)
url = result.stdout.strip()
except (FileNotFoundError, subprocess.CalledProcessError):
sys.exit("Could not detect repo from git remote. Pass --repo owner/name.")
# Handle both SSH and HTTPS remote URLs.
if url.startswith("git@"):
path = url.split(":", 1)[1]
else:
path = url.split("github.com/", 1)[-1]
return path.removesuffix(".git")
def download_artifacts(repo: str, run_id: str, token: str, out_dir: Path):
headers = {
"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
}
out_dir.mkdir(parents=True, exist_ok=True)
url = f"{API_URL}/repos/{repo}/actions/runs/{run_id}/artifacts"
artifacts = []
while url:
resp = requests.get(url, headers=headers, params={"per_page": 100})
resp.raise_for_status()
data = resp.json()
artifacts.extend(data["artifacts"])
url = resp.links.get("next", {}).get("url")
if not artifacts:
print(f"No artifacts found for run {run_id}.")
return
for artifact in artifacts:
name = artifact["name"]
if name == "all-artifacts":
print(f"Skipping {name}")
continue
if artifact.get("expired"):
print(f"Skipping expired artifact: {name}")
continue
print(f"Downloading {name} ({artifact['size_in_bytes']} bytes)...")
download_url = artifact["archive_download_url"]
resp = requests.get(download_url, headers=headers, stream=True)
resp.raise_for_status()
zip_path = out_dir / f"{name}.zip"
with open(zip_path, "wb") as f:
for chunk in resp.iter_content(chunk_size=8192):
f.write(chunk)
if name.endswith(".bin"):
with zipfile.ZipFile(zip_path) as zf:
zf.extractall(out_dir)
zip_path.unlink()
print(f" Extracted to {out_dir}")
else:
print(f" Saved to {zip_path}")
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("run_id", help="GitHub Actions run ID")
parser.add_argument(
"--repo",
help="owner/repo (default: detected from git remote 'origin')",
)
parser.add_argument(
"--token",
help="GitHub token (default: $GITHUB_TOKEN, $GH_TOKEN, or `gh auth token`)",
)
parser.add_argument(
"--out",
default="artifacts",
help="Output directory (default: ./artifacts)",
)
args = parser.parse_args()
repo = get_repo(args.repo)
token = get_token(args.token)
out_dir = Path(args.out)
print(f"Repo: {repo}")
print(f"Run ID: {args.run_id}")
print(f"Output: {out_dir.resolve()}")
download_artifacts(repo, args.run_id, token, out_dir)
if __name__ == "__main__":
main()
+57
View File
@@ -0,0 +1,57 @@
import fnmatch
import json
import os
import sys
DEVICES_DIRECTORY = os.path.join(os.path.dirname(__file__), "..", "Devices")
IGNORE_LIST = {
"simulator",
"generic-*",
}
def is_ignored(device_id):
return any(fnmatch.fnmatch(device_id, pattern) for pattern in IGNORE_LIST)
def read_properties_file(path):
properties = {}
with open(path, "r") as file:
for line in file:
stripped = line.strip()
if not stripped or stripped.startswith("#"):
continue
key, sep, value = line.partition("=")
if not sep:
continue
properties[key.strip()] = value.strip()
return properties
def get_board_entries():
boards = []
for device_id in sorted(os.listdir(DEVICES_DIRECTORY)):
if is_ignored(device_id):
continue
device_dir = os.path.join(DEVICES_DIRECTORY, device_id)
properties_path = os.path.join(device_dir, "device.properties")
if not os.path.isdir(device_dir) or not os.path.isfile(properties_path):
continue
properties = read_properties_file(properties_path)
target = properties.get("hardware.target")
if not target:
sys.exit(f"ERROR: {properties_path} has no hardware.target property")
boards.append({"id": device_id, "arch": target.lower()})
return boards
def main():
matrix_json = json.dumps({"board": get_board_entries()})
github_output = os.environ.get("GITHUB_OUTPUT")
if github_output:
with open(github_output, "a") as file:
file.write(f"matrix={matrix_json}\n")
else:
print(matrix_json)
if __name__ == "__main__":
main()
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""Summarize commits between the last 2 pushed git tags into commits.md and pull-requests.md."""
import argparse
import re
import subprocess
import sys
from pathlib import Path
PR_REF_RE = re.compile(r"#(\d+)")
def get_repo(cli_repo: str | None) -> str:
if cli_repo:
return cli_repo
try:
result = subprocess.run(
["git", "remote", "get-url", "origin"],
capture_output=True,
text=True,
check=True,
)
url = result.stdout.strip()
except (FileNotFoundError, subprocess.CalledProcessError):
sys.exit("Could not detect repo from git remote. Pass --repo owner/name.")
if url.startswith("git@"):
path = url.split(":", 1)[1]
else:
path = url.split("github.com/", 1)[-1]
return path.removesuffix(".git")
def get_last_two_tags() -> tuple[str, str]:
result = subprocess.run(
["git", "tag", "--sort=-creatordate"],
capture_output=True,
text=True,
check=True,
)
tags = [t for t in result.stdout.splitlines() if t]
if len(tags) < 2:
sys.exit(f"Need at least 2 tags, found {len(tags)}.")
return tags[1], tags[0] # previous, latest
def get_commits(prev_tag: str, latest_tag: str) -> list[tuple[str, str]]:
result = subprocess.run(
[
"git",
"log",
"--pretty=format:%H\x1f%s",
f"{prev_tag}..{latest_tag}",
],
capture_output=True,
text=True,
check=True,
)
commits = []
for line in result.stdout.splitlines():
if not line:
continue
sha, subject = line.split("\x1f", 1)
commits.append((sha, subject))
return commits
def write_commits_md(path: Path, repo: str, prev_tag: str, latest_tag: str, commits: list[tuple[str, str]]):
lines = [f"# Commits: {prev_tag}..{latest_tag}", ""]
for sha, subject in commits:
link = f"https://github.com/{repo}/commit/{sha}"
lines.append(f"- [{subject}]({link})")
path.write_text("\n".join(lines) + "\n")
def write_pull_requests_md(path: Path, repo: str, commits: list[tuple[str, str]]):
pr_numbers = []
seen = set()
for _, subject in commits:
for match in PR_REF_RE.finditer(subject):
number = match.group(1)
if number not in seen:
seen.add(number)
pr_numbers.append(number)
lines = ["# Pull Requests", ""]
for number in pr_numbers:
lines.append(f"- https://github.com/{repo}/pull/{number}")
path.write_text("\n".join(lines) + "\n")
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--repo",
help="owner/repo (default: detected from git remote 'origin')",
)
parser.add_argument(
"--out",
default=".",
help="Output directory for commits.md and pull-requests.md (default: current directory)",
)
args = parser.parse_args()
repo = get_repo(args.repo)
prev_tag, latest_tag = get_last_two_tags()
commits = get_commits(prev_tag, latest_tag)
out_dir = Path(args.out)
out_dir.mkdir(parents=True, exist_ok=True)
commits_path = out_dir / "release-commits.md"
prs_path = out_dir / "release-pull-requests.md"
write_commits_md(commits_path, repo, prev_tag, latest_tag, commits)
write_pull_requests_md(prs_path, repo, commits)
print(f"Repo: {repo}")
print(f"Tags: {prev_tag}..{latest_tag}")
print(f"Commits: {len(commits)}")
print(f"Wrote {commits_path}")
print(f"Wrote {prs_path}")
if __name__ == "__main__":
main()
+11 -5
View File
@@ -1,4 +1,11 @@
function(GET_PROPERTY_VALUE PROPERTIES_CONTENT_VAR KEY_NAME RESULT_VAR)
# Optional 4th arg: default value returned when key is missing, instead of erroring.
set(has_default FALSE)
if (${ARGC} GREATER 3)
set(has_default TRUE)
set(default_value "${ARGV3}")
endif ()
# Search for the key and its value in the properties content
# Supports KEY=VALUE, KEY="VALUE", and optional spaces around =
# Use parentheses to capture the value
@@ -6,6 +13,8 @@ function(GET_PROPERTY_VALUE PROPERTIES_CONTENT_VAR KEY_NAME RESULT_VAR)
# So we look for the key at the beginning of the string or after a newline.
if ("${${PROPERTIES_CONTENT_VAR}}" MATCHES "(^|\n)${KEY_NAME}[ \t]*=[ \t]*\"?([^\n\"]*)\"?")
set(${RESULT_VAR} "${CMAKE_MATCH_2}" PARENT_SCOPE)
elseif (has_default)
set(${RESULT_VAR} "${default_value}" PARENT_SCOPE)
else ()
message(FATAL_ERROR "Property '${KEY_NAME}' not found in the properties content.")
endif ()
@@ -28,7 +37,6 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
endif ()
file(STRINGS ${PROPERTY_FILE_ABS} lines)
set(current_section "")
set(map_content "")
foreach(line IN LISTS lines)
@@ -37,9 +45,7 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
continue()
endif ()
if (line MATCHES "^\\[.*\\]$")
set(current_section "${line}")
elseif (line MATCHES "^([^=]+)=(.*)$")
if (line MATCHES "^([^=]+)=(.*)$")
set(key "${CMAKE_MATCH_1}")
set(value "${CMAKE_MATCH_2}")
string(STRIP "${key}" key)
@@ -49,7 +55,7 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
set(value "${CMAKE_MATCH_1}")
endif ()
list(APPEND map_content "${current_section}${key}" "${value}")
list(APPEND map_content "${key}" "${value}")
endif ()
endforeach()
+60 -10
View File
@@ -88,6 +88,17 @@ def write_module_cmakelists(path, content):
with open(path, 'w') as f:
f.write(content)
def driver_is_available(driver_name):
"""
Some drivers only build for certain chip targets (e.g. sc2356-module is ESP32-P4 only,
since it depends on esp_video/esp_cam_sensor/PPA which are themselves chip-restricted).
Build output presence is the single source of truth for "does this driver support the
current target" - no separate manifest to keep in sync with the real CMakeLists.txt
REQUIRES/Kconfig guards.
"""
binary_pattern = f'build/esp-idf/{driver_name}/lib{driver_name}.a'
return bool(glob.glob(binary_pattern))
def add_driver(target_path, driver_name):
mappings = get_driver_mappings(driver_name)
map_copy(mappings, target_path)
@@ -100,6 +111,44 @@ def add_module(target_path, module_name):
cmakelists_content = create_module_cmakelists(module_name)
write_module_cmakelists(os.path.join(target_path, f"Modules/{module_name}/CMakeLists.txt"), cmakelists_content)
def discover_all_drivers():
"""
Discover all *-module directories under Drivers/ (not Modules/ - those are handled
separately via add_module). Sorted for deterministic output across OS/filesystem order.
"""
pattern = os.path.join('Drivers', '*-module')
return sorted(
os.path.basename(p) for p in glob.glob(pattern) if os.path.isdir(p)
)
def generate_tactility_sdk_cmake(target_path, available_drivers):
src = os.path.join('Buildscripts', 'TactilitySDK', 'TactilitySDK.cmake')
with open(src) as f:
content = f.read()
placeholder = " # DRIVER_COMPONENTS_PLACEHOLDER"
assert placeholder in content, \
f"Placeholder '{placeholder.strip()}' not found in {src} - template drifted, generator needs updating"
components = "\n".join(f" {d}" for d in available_drivers)
new_content = content.replace(placeholder, components)
assert placeholder not in new_content, \
f"Placeholder '{placeholder.strip()}' still present after replacement in {src}"
with open(os.path.join(target_path, 'TactilitySDK.cmake'), 'w') as f:
f.write(new_content)
def generate_tactility_sdk_top_cmakelists(target_path, available_drivers):
src = os.path.join('Buildscripts', 'TactilitySDK', 'CMakeLists.txt')
with open(src) as f:
content = f.read()
placeholder = " # DRIVER_INCLUDE_DIRS_PLACEHOLDER"
assert placeholder in content, \
f"Placeholder '{placeholder.strip()}' not found in {src} - template drifted, generator needs updating"
include_dirs = "\n".join(f' "Drivers/{d}/include"' for d in available_drivers)
new_content = content.replace(placeholder, include_dirs)
assert placeholder not in new_content, \
f"Placeholder '{placeholder.strip()}' still present after replacement in {src}"
with open(os.path.join(target_path, 'CMakeLists.txt'), 'w') as f:
f.write(new_content)
def main():
if len(sys.argv) < 2:
print("Usage: release-sdk.py [target_path]")
@@ -136,23 +185,24 @@ def main():
# elf_loader
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
{'src': 'Libraries/elf_loader/license.txt', 'dst': 'Libraries/elf_loader/'},
# Final scripts
{'src': 'Buildscripts/TactilitySDK/TactilitySDK.cmake', 'dst': ''},
{'src': 'Buildscripts/TactilitySDK/CMakeLists.txt', 'dst': ''},
]
map_copy(mappings, target_path)
# Modules
add_module(target_path, "lvgl-module")
add_module(target_path, "crypt-module")
# Drivers
add_driver(target_path, "bm8563-module")
add_driver(target_path, "bmi270-module")
add_driver(target_path, "mpu6886-module")
add_driver(target_path, "pi4ioe5v6408-module")
add_driver(target_path, "qmi8658-module")
add_driver(target_path, "rx8130ce-module")
# Drivers - only ones actually built for this target (chip-restricted drivers like
# sc2356-module won't have a .a outside ESP32-P4)
available_drivers = [d for d in discover_all_drivers() if driver_is_available(d)]
for driver_name in available_drivers:
add_driver(target_path, driver_name)
# Final scripts - generated (not copied verbatim) so COMPONENTS/INCLUDE_DIRS only list
# drivers actually available for this target
generate_tactility_sdk_cmake(target_path, available_drivers)
generate_tactility_sdk_top_cmakelists(target_path, available_drivers)
# Output ESP-IDF SDK version to file
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Generate a release summary markdown by combining gh-release-summary.py output with Claude."""
import argparse
import subprocess
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
SECTIONS = [
"New Devices",
"New Features",
"New Apps",
"Improvements & Fixes",
"Other Changes",
"TactilitySDK",
"Known Issues",
]
def run_gh_release_summary(out_dir: Path, repo: str | None):
cmd = [sys.executable, str(SCRIPT_DIR / "gh-release-summary.py"), "--out", str(out_dir)]
if repo:
cmd += ["--repo", repo]
subprocess.run(cmd, check=True)
def build_prompt() -> str:
section_list = "\n".join(f"- {s}" for s in SECTIONS)
return (
"You are given a list of commits (with GitHub commit links) and a list of pull "
"request links from a software release. Write a release summary in Markdown, "
"organizing changes into these sections (omit a section if it has no relevant "
"changes):\n\n"
f"{section_list}\n\n"
"Use concise bullet points. Base every bullet strictly on the given commits and "
"pull requests, referencing the pull request link where applicable. Output only "
"the Markdown, no commentary before or after it."
"If a pull request or commit has multiple changes add them as separate entries."
"Ignore irrelevant changes: documentation, minor fixes, non-descript fixes, scripts, github workflows."
"For 'New Devices': only mention the device name, don't like pull request."
"For 'Improvements & Fixes': Avoid non-descript entries, write specifics."
"For 'TactilitySDK': Avoid generic changes, be specific. Mention API changes."
)
def run_claude(commits_md: str, prs_md: str) -> str:
prompt = build_prompt()
stdin_content = f"## Commits\n\n{commits_md}\n\n## Pull Requests\n\n{prs_md}"
result = subprocess.run(
["claude", "-p", prompt],
input=stdin_content,
capture_output=True,
text=True,
check=True,
)
return result.stdout
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--repo", help="owner/repo (default: detected from git remote 'origin')")
parser.add_argument("--out", default=".", help="Output directory (default: current directory)")
args = parser.parse_args()
out_dir = Path(args.out)
out_dir.mkdir(parents=True, exist_ok=True)
run_gh_release_summary(out_dir, args.repo)
commits_md = (out_dir / "release-commits.md").read_text()
prs_md = (out_dir / "release-pull-requests.md").read_text()
print("Generating release summary via claude...")
summary = run_claude(commits_md, prs_md)
summary_path = out_dir / "release-summary.md"
summary_path.write_text(summary)
print(f"Wrote {summary_path}")
if __name__ == "__main__":
main()
+24 -1
View File
@@ -9,7 +9,8 @@ CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
# EmbedTLS
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
# Use TLS 1.2 because 1.3 conflicts with MbedTLS dynamic buffer
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
# LVGL
CONFIG_LV_USE_USER_DATA=y
CONFIG_LV_USE_FS_STDIO=y
@@ -25,6 +26,9 @@ CONFIG_LV_USE_WIN=n
CONFIG_LV_USE_SNAPSHOT=y
CONFIG_LV_BUILD_EXAMPLES=n
CONFIG_LV_BUILD_DEMOS=n
# Slot 0 is reserved by ESP-IDF's pthread API (see esp_wifi/lwip pthread_getspecific usage).
# Tactility's Thread wrappers use slot 1 for their own self-pointer.
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=2
CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n
@@ -40,3 +44,22 @@ CONFIG_WL_SECTOR_MODE_SAFE=y
CONFIG_WL_SECTOR_MODE=1
# Allow new i2c_master API (used by Tab5Keyboard for LP_I2C_NUM_0) to coexist with legacy i2c driver
CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK=y
# Allow new adc_oneshot API (esp32_adc_oneshot kernel driver, linked into every device via
# platform-esp32) to coexist with boards still reading battery voltage via the legacy ADC driver
# (e.g. m5stack-cardputer, m5stack-cardputer-adv, lilygo-thmi). Only one API is ever actually used
# per board at runtime, so this just bypasses ESP-IDF's link-time-only conflict abort.
CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK=y
# Wi-Fi memory optimizations
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=3
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=5
CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=5
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=5
CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y
CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=5
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=5
+8 -2
View File
@@ -43,7 +43,6 @@ if (DEFINED ENV{ESP_IDF_VERSION})
"TactilityKernel"
"Tactility"
"TactilityC"
"TactilityCore"
"TactilityFreeRtos"
"Libraries/elf_loader"
"Libraries/lv_screenshot"
@@ -70,10 +69,17 @@ if (DEFINED ENV{ESP_IDF_VERSION})
else ()
message("Building for sim target")
# Devices/simulator/Source/Simulator.cpp always defines its own hardwareConfiguration; without
# this, Firmware/Source/Main.cpp's #else branch also defines an empty one (its ESP32-only
# fallback for devices migrated off the deprecated HAL), causing a duplicate-definition link error.
add_compile_definitions(CONFIG_TT_USE_DEPRECATED_HAL)
add_compile_definitions(CONFIG_TT_DEVICE_ID="simulator")
add_compile_definitions(CONFIG_TT_DEVICE_NAME="Simulator")
add_compile_definitions(CONFIG_TT_DEVICE_VENDOR="")
add_compile_definitions(CONFIG_TT_DEVICE_NAME_SIMPLE="Simulator")
add_compile_definitions(CONFIG_TT_LAUNCHER_APP_ID="Launcher")
add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="")
add_compile_definitions(CONFIG_TT_USER_DATA_LOCATION_INTERNAL)
endif ()
project(Tactility)
@@ -81,7 +87,6 @@ project(Tactility)
# Defined as regular project for PC and component for ESP
if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Tactility)
add_subdirectory(TactilityCore)
add_subdirectory(TactilityFreeRtos)
add_subdirectory(TactilityKernel)
add_subdirectory(Platforms/platform-posix)
@@ -93,6 +98,7 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Libraries/minmea)
add_subdirectory(Modules/hal-device-module)
add_subdirectory(Modules/lvgl-module)
add_subdirectory(Modules/crypt-module)
# FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
@@ -1 +0,0 @@
enableOnBoot=false
@@ -1 +0,0 @@
enableOnBoot=false
@@ -1 +0,0 @@
enableOnBoot=false
-5
View File
@@ -1,5 +0,0 @@
language=en-US
timeFormat24h=true
dateFormat=DD/MM/YYYY
region=EU
timezone=Europe/Amsterdam
@@ -485,7 +485,7 @@
<button class="btn btn-secondary btn-sm" onclick="goUp()" id="upBtn">Up</button>
</div>
<div class="toolbar-sep"></div>
<input type="text" id="pathInput" value="/data" onkeydown="if(event.key==='Enter')refreshFiles()">
<input type="text" id="pathInput" value="" onkeydown="if(event.key==='Enter')refreshFiles()">
<button class="btn btn-primary btn-sm" onclick="refreshFiles()">Go</button>
<div class="toolbar-sep"></div>
<div class="toolbar-group">
@@ -739,7 +739,6 @@ function renderDashboard(data) {
<div class="card">
<h2>Quick Actions</h2>
<div class="actions">
<button class="btn btn-primary" onclick="syncAssets(this)">Sync Assets</button>
${data.features_enabled?.screenshot ? '<button class="btn btn-secondary" onclick="captureScreenshot(this)">Screenshot</button>' : ''}
<button class="btn btn-danger" onclick="rebootDevice(this)">Reboot</button>
</div>
-63
View File
@@ -1,63 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tactility Dashboard</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 20px auto;
padding: 20px;
background-color: #f5f5f5;
}
h1 {
color: #333;
text-align: center;
}
.placeholder {
background: white;
padding: 40px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
text-align: center;
margin: 20px 0;
}
.placeholder h2 {
color: #666;
}
.placeholder p {
color: #666;
line-height: 1.6;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>Tactility Default Dashboard</h1>
<div class="placeholder">
<h2>Version 0 - Default Placeholder</h2>
<p>This is the default dashboard bundled with firmware.</p>
<p>To customize this interface:</p>
<ol style="text-align: left; display: inline-block;">
<li>Create your custom dashboard HTML/CSS/JS files</li>
<li>Add them to <code>/sdcard/tactility/webserver/</code></li>
<li>Create <code>version.json</code> with <code>{"version": 1}</code> or higher</li>
<li>Reboot or click "Sync Assets" on the <a href="/">Core Interface</a></li>
</ol>
<p><strong>Your custom assets will automatically replace this page!</strong></p>
</div>
<div class="placeholder">
<p><a href="/">← Back to Core Interface</a></p>
</div>
</body>
</html>
-3
View File
@@ -1,3 +0,0 @@
{
"version": 0
}
+3 -3
View File
@@ -1,7 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port esp_lcd RgbDisplay GT911 PwmBacklight driver vfs fatfs
INCLUDE_DIRS "source"
REQUIRES Tactility
)
@@ -1,31 +0,0 @@
#include <PwmBacklight.h>
#include "devices/Display.h"
#include <Tactility/hal/Configuration.h>
#include <driver/gpio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
using namespace tt::hal;
static bool initBoot() {
//Display Reset
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_46, GPIO_MODE_OUTPUT));
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_46, 0));
vTaskDelay(pdMS_TO_TICKS(100));
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_46, 1));
vTaskDelay(pdMS_TO_TICKS(10));
return driver::pwmbacklight::init(GPIO_NUM_21);
}
static DeviceVector createDevices() {
return {
createDisplay()
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,107 +0,0 @@
#include "Display.h"
#include <Gt911Touch.h>
#include <PwmBacklight.h>
#include <RgbDisplay.h>
#include <tactility/check.h>
#include <tactility/device.h>
std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 41 and interrupt pin is 40
auto* i2c = device_find_by_name("i2c0");
check(i2c);
auto configuration = std::make_unique<Gt911Touch::Configuration>(
i2c,
800,
480
);
return std::make_shared<Gt911Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
constexpr uint32_t bufferPixels = 800 * 10;
esp_lcd_rgb_panel_config_t rgb_panel_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.timings = {
.pclk_hz = 14000000,
.h_res = 800,
.v_res = 480,
.hsync_pulse_width = 4,
.hsync_back_porch = 8,
.hsync_front_porch = 8,
.vsync_pulse_width = 4,
.vsync_back_porch = 16,
.vsync_front_porch = 16,
.flags = {
.hsync_idle_low = false,
.vsync_idle_low = false,
.de_idle_high = false,
.pclk_active_neg = true,
.pclk_idle_high = true
}
},
.data_width = 16,
.bits_per_pixel = 0,
.num_fbs = 2,
.bounce_buffer_size_px = bufferPixels,
.sram_trans_align = 8,
.psram_trans_align = 64,
.hsync_gpio_num = GPIO_NUM_NC,
.vsync_gpio_num = GPIO_NUM_NC,
.de_gpio_num = GPIO_NUM_38,
.pclk_gpio_num = GPIO_NUM_5,
.disp_gpio_num = GPIO_NUM_NC,
.data_gpio_nums = {
GPIO_NUM_17, // B
GPIO_NUM_18, // B
GPIO_NUM_48, // B
GPIO_NUM_47, // B
GPIO_NUM_39, // B
GPIO_NUM_11, // G
GPIO_NUM_12, // G
GPIO_NUM_13, // G
GPIO_NUM_14, // G
GPIO_NUM_15, // G
GPIO_NUM_16, // G
GPIO_NUM_6, // R
GPIO_NUM_7, // R
GPIO_NUM_8, // R
GPIO_NUM_9, // R
GPIO_NUM_10, // R
},
.flags = {
.disp_active_low = false,
.refresh_on_demand = false,
.fb_in_psram = true,
.double_fb = true,
.no_fb = false,
.bb_invalidate_cache = false
}
};
RgbDisplay::BufferConfiguration buffer_config = {
.size = (800 * 480),
.useSpi = true,
.doubleBuffer = true,
.bounceBufferMode = true,
.avoidTearing = false
};
auto configuration = std::make_unique<RgbDisplay::Configuration>(
rgb_panel_config,
buffer_config,
touch,
LV_COLOR_FORMAT_RGB565,
false,
false,
false,
false,
driver::pwmbacklight::setBacklightDuty
);
return std::make_shared<RgbDisplay>(std::move(configuration));
}
@@ -2,17 +2,28 @@
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_ble.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_usbhost.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <bindings/rgb_display.h>
#include <bindings/gt911.h>
// Reference: https://github.com/bigtreetech/PandaTouch_PlatformIO/blob/master/docs/PINOUT.md
/ {
compatible = "root";
model = "BigTreeTech Panda Touch";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
ble0 {
compatible = "espressif,esp32-ble";
status = "disabled";
};
gpio0 {
@@ -26,6 +37,15 @@
clock-frequency = <400000>;
pin-sda = <&gpio0 2 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 1 GPIO_FLAG_NONE>;
touch0 {
// Reset pin 41 and interrupt pin 40 exist on the board but are not wired up here
// (unverified - left disconnected like the original deprecated-HAL config).
compatible = "goodix,gt911";
reg = <0x5D>;
x-max = <800>;
y-max = <480>;
};
};
i2c_external: i2c1 {
@@ -36,6 +56,57 @@
pin-scl = <&gpio0 3 GPIO_FLAG_NONE>;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 21 GPIO_FLAG_NONE>;
period-ns = <33333>;
ledc-timer = <0>;
ledc-channel = <0>;
};
display_backlight {
compatible = "pwm-backlight";
pwm = <&display_backlight_pwm>;
};
display0 {
compatible = "espressif,esp32-rgb-display";
horizontal-resolution = <800>;
vertical-resolution = <480>;
pixel-clock-hz = <14000000>;
hsync-pulse-width = <4>;
hsync-back-porch = <8>;
hsync-front-porch = <8>;
vsync-pulse-width = <4>;
vsync-back-porch = <16>;
vsync-front-porch = <16>;
pclk-active-neg;
pclk-idle-high;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <8000>;
pin-de = <&gpio0 38 GPIO_FLAG_NONE>;
pin-pclk = <&gpio0 5 GPIO_FLAG_NONE>;
pin-reset = <&gpio0 46 GPIO_FLAG_NONE>;
pin-data0 = <&gpio0 17 GPIO_FLAG_NONE>; // B
pin-data1 = <&gpio0 18 GPIO_FLAG_NONE>; // B
pin-data2 = <&gpio0 48 GPIO_FLAG_NONE>; // B
pin-data3 = <&gpio0 47 GPIO_FLAG_NONE>; // B
pin-data4 = <&gpio0 39 GPIO_FLAG_NONE>; // B
pin-data5 = <&gpio0 11 GPIO_FLAG_NONE>; // G
pin-data6 = <&gpio0 12 GPIO_FLAG_NONE>; // G
pin-data7 = <&gpio0 13 GPIO_FLAG_NONE>; // G
pin-data8 = <&gpio0 14 GPIO_FLAG_NONE>; // G
pin-data9 = <&gpio0 15 GPIO_FLAG_NONE>; // G
pin-data10 = <&gpio0 16 GPIO_FLAG_NONE>; // G
pin-data11 = <&gpio0 6 GPIO_FLAG_NONE>; // R
pin-data12 = <&gpio0 7 GPIO_FLAG_NONE>; // R
pin-data13 = <&gpio0 8 GPIO_FLAG_NONE>; // R
pin-data14 = <&gpio0 9 GPIO_FLAG_NONE>; // R
pin-data15 = <&gpio0 10 GPIO_FLAG_NONE>; // R
backlight = <&display_backlight>;
};
usbhost0 {
compatible = "espressif,esp32-usbhost";
+20 -21
View File
@@ -1,25 +1,24 @@
[general]
vendor=BigTreeTech
name=Panda Touch,K Touch
general.vendor=BigTreeTech
general.name=Panda Touch,K Touch
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB
spiRam=true
spiRamMode=OCT
spiRamSpeed=120M
esptoolFlashFreq=120M
bluetooth=true
usbHostEnabled=true
hardware.target=ESP32S3
hardware.flashSize=16MB
hardware.spiRam=true
hardware.spiRamMode=OCT
hardware.spiRamSpeed=120M
hardware.esptoolFlashFreq=120M
hardware.bluetooth=true
hardware.usbHostEnabled=true
[display]
size=5"
shape=rectangle
dpi=187
dependencies.useDeprecatedHal=false
[lvgl]
colorDepth=16
fontSize=18
storage.userDataLocation=Internal
display.size=5"
display.shape=rectangle
display.dpi=187
lvgl.colorDepth=16
lvgl.fontSize=18
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/rgb-display-module
- Drivers/gt911-module
dts: bigtreetech,panda-touch.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x CST816S PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel
)
@@ -1,30 +0,0 @@
#include "devices/Display.h"
#include <driver/gpio.h>
#include <Tactility/hal/Configuration.h>
#include <PwmBacklight.h>
static bool initBoot() {
// Set the RGB LED Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
// 0 on, 1 off
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static tt::hal::DeviceVector createDevices() {
return {
createDisplay(),
};
}
extern const tt::hal::Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,45 +0,0 @@
#include "Display.h"
#include "Cst816Touch.h"
#include <Ili934xDisplay.h>
#include <PwmBacklight.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note: GPIO 25 for reset and GPIO 21 for interrupt?
auto configuration = std::make_unique<Cst816sTouch::Configuration>(
I2C_NUM_0,
240,
320
);
return std::make_shared<Cst816sTouch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
Ili934xDisplay::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = true,
.mirrorY = false,
.invertColor = false,
.swapBytes = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC,
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR
};
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 40'000'000,
.transactionQueueDepth = 10
});
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
}
@@ -1,18 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <memory>
// Display
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+81 -3
View File
@@ -1,16 +1,26 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <tactility/bindings/rgb_led_pwm.h>
#include <bindings/ili9341.h>
#include <bindings/cst816s.h>
/ {
compatible = "root";
model = "CYD 2432S024C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -22,6 +32,66 @@
clock-frequency = <400000>;
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 32 GPIO_FLAG_NONE>;
touch {
compatible = "hynitron,cst816s";
reg = <0x15>;
x-max = <240>;
y-max = <320>;
};
};
rgb_led_channel_red {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 4 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <0>;
inverted;
};
rgb_led_channel_green {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 16 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <1>;
inverted;
};
rgb_led_channel_blue {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 17 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <2>;
inverted;
};
rgb_led_pwm {
compatible = "rgb-led-pwm";
pwm-red = <&rgb_led_channel_red>;
pwm-green = <&rgb_led_channel_green>;
pwm-blue = <&rgb_led_channel_blue>;
// Default is red, and we want to reset it to off by default
default-color = <0 0 0>;
enabled;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 27 GPIO_FLAG_NONE>;
period-ns = <1953125>;
ledc-timer = <1>;
ledc-channel = <3>;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
spi0 {
@@ -31,8 +101,15 @@
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
display {
compatible = "display-placeholder";
display@0 {
compatible = "ilitek,ili9341";
horizontal-resolution = <240>;
vertical-resolution = <320>;
mirror-x;
bgr-order;
pixel-clock-hz = <40000000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
};
@@ -43,6 +120,7 @@
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
miso-pull-up;
sdcard@0 {
compatible = "espressif,esp32-sdspi";
+14 -15
View File
@@ -1,19 +1,18 @@
[general]
vendor=CYD
name=2432S024C
general.vendor=CYD
general.name=2432S024C
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[display]
size=2.4"
shape=rectangle
dpi=167
dependencies.useDeprecatedHal=false
[lvgl]
colorDepth=16
storage.userDataLocation=SD
display.size=2.4"
display.shape=rectangle
display.dpi=167
lvgl.colorDepth=16
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/cst816s-module
dts: cyd,2432s024c.dts
@@ -3,17 +3,15 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module unphone_module = {
.name = "unphone",
Module cyd_2432s024c_module = {
.name = "cyd-2432s024c",
.start = start,
.stop = stop,
.symbols = nullptr,
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046 PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel
)
@@ -1,21 +0,0 @@
#include "devices/Display.h"
#include <Tactility/hal/Configuration.h>
#include <PwmBacklight.h>
using namespace tt::hal;
static bool initBoot() {
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static DeviceVector createDevices() {
return {
createDisplay()
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,46 +0,0 @@
#include "Display.h"
#include "Xpt2046Touch.h"
#include <Ili934xDisplay.h>
#include <PwmBacklight.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch(esp_lcd_spi_bus_handle_t spiDevice) {
auto configuration = std::make_unique<Xpt2046Touch::Configuration>(
spiDevice,
TOUCH_CS_PIN,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
true, // swapXY
false, // mirrorX
true // mirrorY
);
return std::make_shared<Xpt2046Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 40'000'000,
.transactionQueueDepth = 10
});
Ili934xDisplay::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = true,
.mirrorX = true,
.mirrorY = true,
.invertColor = false,
.swapBytes = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(spi_configuration->spiHostDevice),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = LCD_PIN_RST,
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB
};
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
}
@@ -1,28 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <memory>
// Display
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_PIN_RST = GPIO_NUM_NC; // tied to ESP32 RST
constexpr auto LCD_PIN_CLK = GPIO_NUM_14;
constexpr auto LCD_PIN_MOSI = GPIO_NUM_13;
constexpr auto LCD_PIN_MISO = GPIO_NUM_12;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
// Backlight
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
// Touch
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+78 -4
View File
@@ -1,22 +1,84 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <tactility/bindings/rgb_led_pwm.h>
#include <bindings/ili9341.h>
#include <bindings/xpt2046.h>
/ {
compatible = "root";
model = "CYD 2432S024R";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
};
rgb_led_channel_red {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 4 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <0>;
inverted;
};
rgb_led_channel_green {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 16 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <1>;
inverted;
};
rgb_led_channel_blue {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 17 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <2>;
inverted;
};
rgb_led_pwm {
compatible = "rgb-led-pwm";
pwm-red = <&rgb_led_channel_red>;
pwm-green = <&rgb_led_channel_green>;
pwm-blue = <&rgb_led_channel_blue>;
// Default is red, and we want to reset it to off by default
default-color = <0 0 0>;
enabled;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 27 GPIO_FLAG_NONE>;
period-ns = <1953125>;
ledc-timer = <1>;
ledc-channel = <3>;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
@@ -27,11 +89,23 @@
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
display@0 {
compatible = "display-placeholder";
compatible = "ilitek,ili9341";
horizontal-resolution = <240>;
vertical-resolution = <320>;
swap-xy;
mirror-x;
mirror-y;
pixel-clock-hz = <40000000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
touch@1 {
compatible = "touch-placeholder";
compatible = "xptek,xpt2046";
x-max = <240>;
y-max = <320>;
swap-xy;
mirror-y;
};
};
+14 -15
View File
@@ -1,19 +1,18 @@
[general]
vendor=CYD
name=2432S024R
general.vendor=CYD
general.name=2432S024R
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[display]
size=2.4"
shape=rectangle
dpi=167
dependencies.useDeprecatedHal=false
[lvgl]
colorDepth=16
storage.userDataLocation=SD
display.size=2.4"
display.shape=rectangle
display.dpi=167
lvgl.colorDepth=16
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/xpt2046-module
dts: cyd,2432s024r.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046SoftSPI PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel
)
@@ -1,32 +0,0 @@
#include "devices/Display.h"
#include <driver/gpio.h>
#include <Tactility/hal/Configuration.h>
#include <PwmBacklight.h>
using namespace tt::hal;
static bool initBoot() {
// Set the RGB LED Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
// 0 on, 1 off
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static DeviceVector createDevices() {
return {
createDisplay(),
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,49 +0,0 @@
#include "Display.h"
#include "Xpt2046SoftSpi.h"
#include <Ili934xDisplay.h>
#include <PwmBacklight.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto configuration = std::make_unique<Xpt2046SoftSpi::Configuration>(
TOUCH_MOSI_PIN,
TOUCH_MISO_PIN,
TOUCH_SCK_PIN,
TOUCH_CS_PIN,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
false, // swapXY
true, // mirrorX
false // mirrorY
);
return std::make_shared<Xpt2046SoftSpi>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
Ili934xDisplay::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = true,
.mirrorY = false,
.invertColor = false,
.swapBytes = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC,
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR
};
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 40'000'000,
.transactionQueueDepth = 10
});
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
}
@@ -1,27 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <memory>
// Display
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
// Display backlight (PWM)
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_21;
// Touch (Software SPI)
constexpr auto TOUCH_MISO_PIN = GPIO_NUM_39;
constexpr auto TOUCH_MOSI_PIN = GPIO_NUM_32;
constexpr auto TOUCH_SCK_PIN = GPIO_NUM_25;
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+84 -9
View File
@@ -1,18 +1,27 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <tactility/bindings/rgb_led_pwm.h>
#include <bindings/ili9341.h>
#include <bindings/xpt2046_softspi.h>
/ {
compatible = "root";
model = "CYD 2432S028R";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -26,21 +35,87 @@
pin-scl = <&gpio0 22 GPIO_FLAG_NONE>;
};
rgb_led_channel_red {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 4 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <0>;
inverted;
};
rgb_led_channel_green {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 16 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <1>;
inverted;
};
rgb_led_channel_blue {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 17 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <2>;
inverted;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 21 GPIO_FLAG_NONE>;
period-ns = <1953125>;
ledc-timer = <1>;
ledc-channel = <3>;
};
rgb_led_pwm {
compatible = "rgb-led-pwm";
pwm-red = <&rgb_led_channel_red>;
pwm-green = <&rgb_led_channel_green>;
pwm-blue = <&rgb_led_channel_blue>;
// Default is red, and we want to reset it to off by default
default-color = <0 0 0>;
enabled;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
touch {
compatible = "xptek,xpt2046-softspi";
pin-mosi = <&gpio0 32 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 39 GPIO_FLAG_NONE>;
pin-sck = <&gpio0 25 GPIO_FLAG_NONE>;
pin-cs = <&gpio0 33 GPIO_FLAG_NONE>;
x-max = <240>;
y-max = <320>;
mirror-x;
};
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>, // Display
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
display@0 {
compatible = "display-placeholder";
};
touch@1 {
compatible = "touch-placeholder";
compatible = "ilitek,ili9341";
horizontal-resolution = <240>;
vertical-resolution = <320>;
mirror-x;
bgr-order;
pixel-clock-hz = <40000000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
};
+18 -17
View File
@@ -1,22 +1,23 @@
[general]
vendor=CYD
name=2432S028R
general.vendor=CYD
general.name=2432S028R
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[display]
size=2.8"
shape=rectangle
dpi=143
dependencies.useDeprecatedHal=false
[cdn]
warningMessage=There are 3 hardware variants of this board. This build works on the original variant only ("v1").
storage.userDataLocation=SD
[lvgl]
colorDepth=16
display.size=2.8"
display.shape=rectangle
display.dpi=143
touch.calibrationSupported=true
touch.calibrationRequired=false
cdn.warningMessage=There are 3 hardware variants of this board. This build works on the original variant only ("v1").
lvgl.colorDepth=16
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/xpt2046-softspi-module
dts: cyd,2432s028r.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ST7789 XPT2046SoftSPI PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel
)
@@ -1,32 +0,0 @@
#include "devices/Display.h"
#include <driver/gpio.h>
#include <Tactility/hal/Configuration.h>
#include <PwmBacklight.h>
using namespace tt::hal;
static bool initBoot() {
// Set the RGB LED Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
// 0 on, 1 off
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static DeviceVector createDevices() {
return {
createDisplay(),
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,50 +0,0 @@
#include "Display.h"
#include "Xpt2046SoftSpi.h"
#include <St7789Display.h>
#include <PwmBacklight.h>
constexpr auto* TAG = "CYD";
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto configuration = std::make_unique<Xpt2046SoftSpi::Configuration>(
TOUCH_MOSI_PIN,
TOUCH_MISO_PIN,
TOUCH_SCK_PIN,
TOUCH_CS_PIN,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
false, // swapXY
true, // mirrorX
false // mirrorY
);
return std::make_shared<Xpt2046SoftSpi>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
St7789Display::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = false,
.mirrorX = false,
.mirrorY = false,
.invertColor = false,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC,
.lvglSwapBytes = false
};
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 62'500'000,
.transactionQueueDepth = 10
});
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
}
@@ -1,27 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <memory>
// Display
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_21;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
// Touch (Software SPI)
constexpr auto TOUCH_MISO_PIN = GPIO_NUM_39;
constexpr auto TOUCH_MOSI_PIN = GPIO_NUM_32;
constexpr auto TOUCH_SCK_PIN = GPIO_NUM_25;
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+82 -9
View File
@@ -1,18 +1,27 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <tactility/bindings/rgb_led_pwm.h>
#include <bindings/st7789.h>
#include <bindings/xpt2046_softspi.h>
/ {
compatible = "root";
model = "CYD 2432S028R v3";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -26,21 +35,85 @@
pin-scl = <&gpio0 22 GPIO_FLAG_NONE>;
};
rgb_led_channel_red {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 4 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <0>;
inverted;
};
rgb_led_channel_green {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 16 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <1>;
inverted;
};
rgb_led_channel_blue {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 17 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <2>;
inverted;
};
rgb_led_pwm {
compatible = "rgb-led-pwm";
pwm-red = <&rgb_led_channel_red>;
pwm-green = <&rgb_led_channel_green>;
pwm-blue = <&rgb_led_channel_blue>;
// Default is red, and we want to reset it to off by default
default-color = <0 0 0>;
enabled;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 21 GPIO_FLAG_NONE>;
period-ns = <1953125>;
ledc-timer = <1>;
ledc-channel = <3>;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
touch {
compatible = "xptek,xpt2046-softspi";
pin-mosi = <&gpio0 32 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 39 GPIO_FLAG_NONE>;
pin-sck = <&gpio0 25 GPIO_FLAG_NONE>;
pin-cs = <&gpio0 33 GPIO_FLAG_NONE>;
x-max = <240>;
y-max = <320>;
mirror-x;
};
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>, // Display
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
display@0 {
compatible = "display-placeholder";
};
touch@1 {
compatible = "touch-placeholder";
compatible = "sitronix,st7789";
horizontal-resolution = <240>;
vertical-resolution = <320>;
pixel-clock-hz = <62500000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
};
+18 -17
View File
@@ -1,22 +1,23 @@
[general]
vendor=CYD
name=2432S028R v3
general.vendor=CYD
general.name=2432S028R v3
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[display]
size=2.8"
shape=rectangle
dpi=143
dependencies.useDeprecatedHal=false
[cdn]
warningMessage=There are 3 hardware variants of this board. This build only supports board version 3.
storage.userDataLocation=SD
[lvgl]
colorDepth=16
display.size=2.8"
display.shape=rectangle
display.dpi=143
touch.calibrationSupported=true
touch.calibrationRequired=false
cdn.warningMessage=There are 3 hardware variants of this board. This build only supports board version 3.
lvgl.colorDepth=16
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/st7789-module
- Drivers/xpt2046-softspi-module
dts: cyd,2432s028rv3.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x GT911 PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel
)
@@ -1,47 +0,0 @@
#include "devices/Display.h"
#include <driver/gpio.h>
#include <Tactility/hal/Configuration.h>
#include <Tactility/kernel/SystemEvents.h>
#include <Tactility/lvgl/LvglSync.h>
#include <PwmBacklight.h>
static bool initBoot() {
if (!driver::pwmbacklight::init(LCD_PIN_BACKLIGHT)) {
return false;
}
// Set the RGB LED Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
// 0 on, 1 off
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
// This display has a weird glitch with gamma during boot, which results in uneven dark gray colours.
// Setting gamma curve index to 0 doesn't work at boot for an unknown reason, so we set the curve index to 1:
tt::kernel::subscribeSystemEvent(tt::kernel::SystemEvent::BootSplash, [](auto) {
auto display = tt::hal::findFirstDevice<tt::hal::display::DisplayDevice>(tt::hal::Device::Type::Display);
assert(display != nullptr);
tt::lvgl::lock(portMAX_DELAY);
display->setGammaCurve(1U);
tt::lvgl::unlock();
});
return true;
}
static tt::hal::DeviceVector createDevices() {
return {
createDisplay(),
};
}
extern const tt::hal::Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,48 +0,0 @@
#include "Display.h"
#include <Gt911Touch.h>
#include <Ili934xDisplay.h>
#include <PwmBacklight.h>
#include <tactility/check.h>
#include <tactility/device.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto* i2c = device_find_by_name("i2c0");
check(i2c);
auto configuration = std::make_unique<Gt911Touch::Configuration>(
i2c,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION
);
return std::make_shared<Gt911Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
Ili934xDisplay::Configuration panel_configuration = {
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
.verticalResolution = LCD_VERTICAL_RESOLUTION,
.gapX = 0,
.gapY = 0,
.swapXY = true,
.mirrorX = true,
.mirrorY = true,
.invertColor = true,
.swapBytes = true,
.bufferSize = LCD_BUFFER_SIZE,
.touch = createTouch(),
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
.resetPin = GPIO_NUM_NC,
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB
};
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
.spiHostDevice = LCD_SPI_HOST,
.csPin = LCD_PIN_CS,
.dcPin = LCD_PIN_DC,
.pixelClockFrequency = 40'000'000,
.transactionQueueDepth = 10
});
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
}
@@ -1,18 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <driver/gpio.h>
#include <driver/spi_common.h>
#include <memory>
// Display
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+84 -3
View File
@@ -1,16 +1,26 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <tactility/bindings/rgb_led_pwm.h>
#include <bindings/ili9341.h>
#include <bindings/gt911.h>
/ {
compatible = "root";
model = "CYD 2432S032C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -22,6 +32,66 @@
clock-frequency = <400000>;
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 32 GPIO_FLAG_NONE>;
touch {
compatible = "goodix,gt911";
reg = <0x5D>;
x-max = <240>;
y-max = <320>;
};
};
rgb_led_channel_red {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 4 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <0>;
inverted;
};
rgb_led_channel_green {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 16 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <1>;
inverted;
};
rgb_led_channel_blue {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 17 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <2>;
inverted;
};
rgb_led_pwm {
compatible = "rgb-led-pwm";
pwm-red = <&rgb_led_channel_red>;
pwm-green = <&rgb_led_channel_green>;
pwm-blue = <&rgb_led_channel_blue>;
// Default is red, and we want to reset it to off by default
default-color = <0 0 0>;
enabled;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 27 GPIO_FLAG_NONE>;
period-ns = <33333>;
ledc-timer = <1>;
ledc-channel = <3>;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
spi0 {
@@ -31,8 +101,19 @@
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
display {
compatible = "display-placeholder";
display@0 {
compatible = "ilitek,ili9341";
horizontal-resolution = <240>;
vertical-resolution = <320>;
swap-xy;
mirror-x;
mirror-y;
invert-color;
// Curve 0 doesn't apply cleanly at boot on this panel (uneven dark-gray gamma glitch); 1 does.
gamma-curve = <1>;
pixel-clock-hz = <40000000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
};
+14 -15
View File
@@ -1,19 +1,18 @@
[general]
vendor=CYD
name=2432S032C
general.vendor=CYD
general.name=2432S032C
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[display]
size=3.2"
shape=rectangle
dpi=125
dependencies.useDeprecatedHal=false
[lvgl]
colorDepth=16
storage.userDataLocation=SD
display.size=3.2"
display.shape=rectangle
display.dpi=125
lvgl.colorDepth=16
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/gt911-module
dts: cyd,2432s032c.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ST7796 GT911 PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel
)
@@ -1,32 +0,0 @@
#include "devices/Display.h"
#include <driver/gpio.h>
#include <PwmBacklight.h>
#include <Tactility/hal/Configuration.h>
using namespace tt::hal;
static bool initBoot() {
//Set the RGB Led Pins to output and turn them off
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); //Red
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); //Green
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); //Blue
//0 on, 1 off... yep it's backwards.
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); //Red
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); //Green
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); //Blue
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
}
static DeviceVector createDevices() {
return {
createDisplay(),
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,40 +0,0 @@
#include "Display.h"
#include <Gt911Touch.h>
#include <PwmBacklight.h>
#include <St7796Display.h>
#include <tactility/check.h>
#include <tactility/device.h>
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
auto* i2c = device_find_by_name("i2c0");
check(i2c);
auto configuration = std::make_unique<Gt911Touch::Configuration>(
i2c,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION
);
return std::make_shared<Gt911Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
auto configuration = std::make_unique<St7796Display::Configuration>(
LCD_SPI_HOST,
LCD_PIN_CS,
LCD_PIN_DC,
LCD_HORIZONTAL_RESOLUTION,
LCD_VERTICAL_RESOLUTION,
touch,
false,
true,
false,
false
);
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
auto display = std::make_shared<St7796Display>(std::move(configuration));
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
}
@@ -1,20 +0,0 @@
#pragma once
#include <Tactility/hal/display/DisplayDevice.h>
#include <memory>
#include <driver/gpio.h>
#include <driver/spi_common.h>
// Display backlight (PWM)
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
// Display
constexpr auto LCD_SPI_HOST = SPI2_HOST;
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
constexpr auto LCD_HORIZONTAL_RESOLUTION = 320;
constexpr auto LCD_VERTICAL_RESOLUTION = 480;
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
+79 -3
View File
@@ -1,17 +1,27 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <tactility/bindings/rgb_led_pwm.h>
#include <bindings/st7796.h>
#include <bindings/gt911.h>
/ {
compatible = "root";
model = "CYD 3248S035C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -23,6 +33,13 @@
clock-frequency = <400000>;
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 32 GPIO_FLAG_NONE>;
touch {
compatible = "goodix,gt911";
reg = <0x5D>;
x-max = <320>;
y-max = <480>;
};
};
// CN1 header
@@ -34,6 +51,59 @@
pin-scl = <&gpio0 22 GPIO_FLAG_NONE>;
};
rgb_led_channel_red {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 4 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <0>;
inverted;
};
rgb_led_channel_green {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 16 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <1>;
inverted;
};
rgb_led_channel_blue {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 17 GPIO_FLAG_NONE>;
period-ns = <500000>;
ledc-timer = <0>;
ledc-channel = <2>;
inverted;
};
rgb_led_pwm {
compatible = "rgb-led-pwm";
pwm-red = <&rgb_led_channel_red>;
pwm-green = <&rgb_led_channel_green>;
pwm-blue = <&rgb_led_channel_blue>;
// Default is red, and we want to reset it to off by default
default-color = <0 0 0>;
enabled;
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 27 GPIO_FLAG_NONE>;
period-ns = <33333>;
ledc-timer = <1>;
ledc-channel = <3>;
};
display_backlight {
compatible = "pwm-backlight";
// Off by default so display power-on won't show the screen from before the last power loss.
// The display backlight is turned on during the boot process.
status = "disabled";
pwm = <&display_backlight_pwm>;
};
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
@@ -41,8 +111,14 @@
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
display {
compatible = "display-placeholder";
display@0 {
compatible = "sitronix,st7796";
horizontal-resolution = <320>;
vertical-resolution = <480>;
mirror-x;
pixel-clock-hz = <80000000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
};
};
+14 -15
View File
@@ -1,19 +1,18 @@
[general]
vendor=CYD
name=3248S035C
general.vendor=CYD
general.name=3248S035C
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[display]
size=3.5"
shape=rectangle
dpi=165
dependencies.useDeprecatedHal=false
[lvgl]
colorDepth=16
storage.userDataLocation=SD
display.size=3.5"
display.shape=rectangle
display.dpi=165
lvgl.colorDepth=16
+3 -1
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Platforms/platform-esp32
- Drivers/st7796-module
- Drivers/gt911-module
dts: cyd,3248s035c.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility EspLcdCompat esp_lcd_st7701 esp_lcd_panel_io_additions GT911 PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel driver
)
@@ -1,21 +0,0 @@
#include "devices/St7701Display.h"
#include <Tactility/hal/Configuration.h>
#include <PwmBacklight.h>
using namespace tt::hal;
static bool initBoot() {
return driver::pwmbacklight::init(GPIO_NUM_38, 1000);
}
static DeviceVector createDevices() {
return {
std::make_shared<St7701Display>(),
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,242 +0,0 @@
#include "St7701Display.h"
#include <Gt911Touch.h>
#include <PwmBacklight.h>
#include <Tactility/Logger.h>
#include <tactility/check.h>
#include <tactility/device.h>
#include <driver/gpio.h>
#include <esp_err.h>
#include <esp_lcd_panel_rgb.h>
#include <esp_lcd_panel_ops.h>
#include <esp_lcd_panel_io_additions.h>
#include <esp_lcd_st7701.h>
static const auto LOGGER = tt::Logger("St7701Display");
static const st7701_lcd_init_cmd_t st7701_lcd_init_cmds[] = {
// {cmd, { data }, data_size, delay_ms}
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0},
{0xC0, (uint8_t[]) {0x3B, 0x00}, 2, 0},
{0xC1, (uint8_t[]) {0x0D, 0x02}, 2, 0},
{0xC2, (uint8_t[]) {0x31, 0x05}, 2, 0},
{0xCD, (uint8_t[]) {0x00}, 1, 0}, //0x08
//Positive Voltage Gamma Control
{0xB0, (uint8_t[]) {0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18}, 16, 0},
//Negative Voltage Gamma Control
{0xB1, (uint8_t[]) {0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18}, 16, 0},
//Page1
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x11}, 5, 0},
{0xB0, (uint8_t[]) {0x60}, 1, 0}, //Vop=4.7375v
{0xB1, (uint8_t[]) {0x32}, 1, 0}, //VCOM=32
{0xB2, (uint8_t[]) {0x07}, 1, 0}, //VGH=15v
{0xB3, (uint8_t[]) {0x80}, 1, 0},
{0xB5, (uint8_t[]) {0x49}, 1, 0}, //VGL=-10.17v
{0xB7, (uint8_t[]) {0x85}, 1, 0},
{0xB8, (uint8_t[]) {0x21}, 1, 0}, //AVDD=6.6 & AVCL=-4.6
{0xC1, (uint8_t[]) {0x78}, 1, 0},
{0xC2, (uint8_t[]) {0x78}, 1, 0},
{0xE0, (uint8_t[]) {0x00, 0x1B, 0x02}, 3, 0},
{0xE1, (uint8_t[]) {0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44}, 11, 0},
{0xE2, (uint8_t[]) {0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00}, 12, 0},
{0xE3, (uint8_t[]) {0x00, 0x00, 0x11, 0x11}, 4, 0},
{0xE4, (uint8_t[]) {0x44, 0x44}, 2, 0},
{0xE5, (uint8_t[]) {0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0}, 16, 0},
{0xE6, (uint8_t[]) {0x00, 0x00, 0x11, 0x11}, 4, 0},
{0xE7, (uint8_t[]) {0x44, 0x44}, 2, 0},
{0xE8, (uint8_t[]) {0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0}, 16, 0},
{0xEB, (uint8_t[]) {0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40}, 7, 0},
{0xEC, (uint8_t[]) {0x3C, 0x00}, 2, 0},
{0xED, (uint8_t[]) {0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA}, 16, 0},
//VAP & VAN
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x13}, 5, 0},
{0xE5, (uint8_t[]) {0xE4}, 1, 0},
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x00}, 5, 0},
{0x3A, (uint8_t[]) {0x60}, 1, 10}, //0x70 RGB888, 0x60 RGB666, 0x50 RGB565
{0x11, (uint8_t[]) {0x00}, 0, 120}, //Sleep Out
{0x29, (uint8_t[]) {0x00}, 0, 0}, //Display On
};
bool St7701Display::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
spi_line_config_t line_config = {
.cs_io_type = IO_TYPE_GPIO,
.cs_gpio_num = GPIO_NUM_39,
.scl_io_type = IO_TYPE_GPIO,
.scl_gpio_num = GPIO_NUM_48,
.sda_io_type = IO_TYPE_GPIO,
.sda_gpio_num = GPIO_NUM_47,
.io_expander = nullptr,
};
esp_lcd_panel_io_3wire_spi_config_t panel_io_config = ST7701_PANEL_IO_3WIRE_SPI_CONFIG(line_config, 0);
return esp_lcd_new_panel_io_3wire_spi(&panel_io_config, &outHandle) == ESP_OK;
}
bool St7701Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) {
const esp_lcd_rgb_panel_config_t rgb_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.timings = {
.pclk_hz = 14000000,
.h_res = 480,
.v_res = 480,
.hsync_pulse_width = 10,
.hsync_back_porch = 10,
.hsync_front_porch = 20,
.vsync_pulse_width = 10,
.vsync_back_porch = 10,
.vsync_front_porch = 10,
.flags = {
.hsync_idle_low = false,
.vsync_idle_low = false,
.de_idle_high = false,
.pclk_active_neg = false,
.pclk_idle_high = false
}
},
.data_width = 16,
.bits_per_pixel = 16,
.num_fbs = 2,
.bounce_buffer_size_px = 480 * 10,
.sram_trans_align = 8,
.psram_trans_align = 64,
.hsync_gpio_num = GPIO_NUM_16,
.vsync_gpio_num = GPIO_NUM_17,
.de_gpio_num = GPIO_NUM_18,
.pclk_gpio_num = GPIO_NUM_21,
.disp_gpio_num = GPIO_NUM_NC,
.data_gpio_nums = {
GPIO_NUM_4, // B1
GPIO_NUM_5, // B2
GPIO_NUM_6, // B3
GPIO_NUM_7, // B4
GPIO_NUM_15, // B5
GPIO_NUM_8, // G1
GPIO_NUM_20, // G2
GPIO_NUM_3, // G3
GPIO_NUM_46, // G4
GPIO_NUM_9, // G5
GPIO_NUM_10, // G6
GPIO_NUM_11, // R1
GPIO_NUM_12, // R2
GPIO_NUM_13, // R3
GPIO_NUM_14, // R4
GPIO_NUM_0 // R5
},
.flags = {
.disp_active_low = false,
.refresh_on_demand = false,
.fb_in_psram = true,
.double_fb = true,
.no_fb = false,
.bb_invalidate_cache = true
}
};
st7701_vendor_config_t vendor_config = {
.init_cmds = st7701_lcd_init_cmds,
.init_cmds_size = sizeof(st7701_lcd_init_cmds) / sizeof(st7701_lcd_init_cmd_t),
.rgb_config = &rgb_config,
.flags = {
.use_mipi_interface = 0,
.mirror_by_cmd = 1,
.auto_del_panel_io = 0,
},
};
const esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = GPIO_NUM_NC,
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
.bits_per_pixel = 16,
.flags = {
.reset_active_high = false,
},
.vendor_config = &vendor_config,
};
if (esp_lcd_new_panel_st7701(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
LOGGER.error("Failed to create panel");
return false;
}
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
LOGGER.error("Failed to reset panel");
return false;
}
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
LOGGER.error("Failed to init panel");
return false;
}
if (esp_lcd_panel_invert_color(panelHandle, false) != ESP_OK) {
LOGGER.error("Failed to invert color");
return false;
}
esp_lcd_panel_set_gap(panelHandle, 0, 0);
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
LOGGER.error("Failed to turn display on");
return false;
}
return true;
}
lvgl_port_display_cfg_t St7701Display::getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
return {
.io_handle = ioHandle,
.panel_handle = panelHandle,
.control_handle = nullptr,
.buffer_size = (480 * 480),
.double_buffer = true,
.trans_size = 0,
.hres = 480,
.vres = 480,
.monochrome = false,
.rotation = {
.swap_xy = false,
.mirror_x = false,
.mirror_y = false,
},
.color_format = LV_COLOR_FORMAT_RGB565,
.flags = {
.buff_dma = false,
.buff_spiram = true,
.sw_rotate = false,
.swap_bytes = false,
.full_refresh = false,
.direct_mode = false
}
};
}
lvgl_port_display_rgb_cfg_t St7701Display::getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
return {
.flags = {
.bb_mode = true,
.avoid_tearing = false
}
};
}
std::shared_ptr<tt::hal::touch::TouchDevice> St7701Display::getTouchDevice() {
if (touchDevice == nullptr) {
auto* i2c = device_find_by_name("i2c0");
check(i2c);
auto configuration = std::make_unique<Gt911Touch::Configuration>(
i2c,
480,
480
);
touchDevice = std::make_shared<Gt911Touch>(std::move(configuration));
}
return touchDevice;
}
void St7701Display::setBacklightDuty(uint8_t backlightDuty) {
driver::pwmbacklight::setBacklightDuty(backlightDuty);
}
@@ -1,36 +0,0 @@
#pragma once
#include <EspLcdDisplay.h>
#include <lvgl.h>
class St7701Display final : public EspLcdDisplay {
std::shared_ptr<tt::hal::touch::TouchDevice> touchDevice;
bool createIoHandle(esp_lcd_panel_io_handle_t& outHandle) override;
bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) override;
lvgl_port_display_cfg_t getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) override;
bool isRgbPanel() const override { return true; }
lvgl_port_display_rgb_cfg_t getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) override;
public:
St7701Display() : EspLcdDisplay() {}
std::string getName() const override { return "ST7701S"; }
std::string getDescription() const override { return "ST7701S RGB display"; }
std::shared_ptr<tt::hal::touch::TouchDevice> getTouchDevice() override;
void setBacklightDuty(uint8_t backlightDuty) override;
bool supportsBacklightDuty() const override { return true; }
// TODO: Find out why it crashes
bool supportsDisplayDriver() const override { return false; }
};
+130 -1
View File
@@ -2,17 +2,28 @@
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_ble.h>
#include <tactility/bindings/esp32_wifi_pinned.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_pwm_ledc.h>
#include <tactility/bindings/pwm_backlight.h>
#include <bindings/st7701.h>
#include <bindings/gt911.h>
/ {
compatible = "root";
model = "CYD 4848S040C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
ble0 {
compatible = "espressif,esp32-ble";
status = "disabled";
};
gpio0 {
@@ -26,6 +37,124 @@
clock-frequency = <400000>;
pin-sda = <&gpio0 19 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 45 GPIO_FLAG_NONE>;
touch0 {
// No reset/interrupt pin wired up here, matching the original deprecated-HAL
// config (Gt911Touch::Configuration was constructed with no reset/interrupt pin
// arguments on this board).
compatible = "goodix,gt911";
reg = <0x5D>;
x-max = <480>;
y-max = <480>;
};
};
display_backlight_pwm {
compatible = "espressif,esp32-pwm-ledc";
pin = <&gpio0 38 GPIO_FLAG_NONE>;
period-ns = <1000000>;
ledc-timer = <0>;
ledc-channel = <0>;
};
display_backlight {
compatible = "pwm-backlight";
pwm = <&display_backlight_pwm>;
};
display0 {
compatible = "sitronix,st7701";
horizontal-resolution = <480>;
vertical-resolution = <480>;
pixel-clock-hz = <14000000>;
hsync-pulse-width = <10>;
hsync-back-porch = <10>;
hsync-front-porch = <20>;
vsync-pulse-width = <10>;
vsync-back-porch = <10>;
vsync-front-porch = <10>;
num-fbs = <2>;
double-fb;
bounce-buffer-size-px = <4800>;
bb-invalidate-cache;
pin-hsync = <&gpio0 16 GPIO_FLAG_NONE>;
pin-vsync = <&gpio0 17 GPIO_FLAG_NONE>;
pin-de = <&gpio0 18 GPIO_FLAG_NONE>;
pin-pclk = <&gpio0 21 GPIO_FLAG_NONE>;
pin-data0 = <&gpio0 4 GPIO_FLAG_NONE>; // B1
pin-data1 = <&gpio0 5 GPIO_FLAG_NONE>; // B2
pin-data2 = <&gpio0 6 GPIO_FLAG_NONE>; // B3
pin-data3 = <&gpio0 7 GPIO_FLAG_NONE>; // B4
pin-data4 = <&gpio0 15 GPIO_FLAG_NONE>; // B5
pin-data5 = <&gpio0 8 GPIO_FLAG_NONE>; // G1
pin-data6 = <&gpio0 20 GPIO_FLAG_NONE>; // G2
pin-data7 = <&gpio0 3 GPIO_FLAG_NONE>; // G3
pin-data8 = <&gpio0 46 GPIO_FLAG_NONE>; // G4
pin-data9 = <&gpio0 9 GPIO_FLAG_NONE>; // G5
pin-data10 = <&gpio0 10 GPIO_FLAG_NONE>; // G6
pin-data11 = <&gpio0 11 GPIO_FLAG_NONE>; // R1
pin-data12 = <&gpio0 12 GPIO_FLAG_NONE>; // R2
pin-data13 = <&gpio0 13 GPIO_FLAG_NONE>; // R3
pin-data14 = <&gpio0 14 GPIO_FLAG_NONE>; // R4
pin-data15 = <&gpio0 0 GPIO_FLAG_NONE>; // R5
// 3-wire bit-banged command bus. GPIO47/48 are physically shared with this board's SD
// card SPI2 bus (MOSI/SCLK) - no alternate pins exist on this PCB. No SD card device is
// declared in this devicetree yet (CS/MISO pins are unverified), but if one is added on
// SPI2_HOST later, declare it *after* this node: starting that SPI bus unconditionally
// reprograms the GPIO matrix for its MOSI/SCLK pins (see esp32_spi.cpp's start()),
// which reclaims them from this display's bit-banged use without any extra code.
pin-cs = <&gpio0 39 GPIO_FLAG_NONE>;
pin-scl = <&gpio0 48 GPIO_FLAG_NONE>;
pin-sda = <&gpio0 47 GPIO_FLAG_NONE>;
mirror-by-cmd;
init-sequence = [
// Vendor bring-up sequence for this panel. Framing is
// [cmd, data-len, delay-ms, data-len bytes of data...] - see st7701-module's
// init-sequence binding property for the encoding.
0xFF 5 0 0x77 0x01 0x00 0x00 0x10
0xC0 2 0 0x3B 0x00
0xC1 2 0 0x0D 0x02
0xC2 2 0 0x31 0x05
0xCD 1 0 0x00
// Positive Voltage Gamma Control
0xB0 16 0 0x00 0x11 0x18 0x0E 0x11 0x06 0x07 0x08 0x07 0x22 0x04 0x12 0x0F 0xAA 0x31 0x18
// Negative Voltage Gamma Control
0xB1 16 0 0x00 0x11 0x19 0x0E 0x12 0x07 0x08 0x08 0x08 0x22 0x04 0x11 0x11 0xA9 0x32 0x18
// Page1
0xFF 5 0 0x77 0x01 0x00 0x00 0x11
0xB0 1 0 0x60 // Vop=4.7375v
0xB1 1 0 0x32 // VCOM=32
0xB2 1 0 0x07 // VGH=15v
0xB3 1 0 0x80
0xB5 1 0 0x49 // VGL=-10.17v
0xB7 1 0 0x85
0xB8 1 0 0x21 // AVDD=6.6 & AVCL=-4.6
0xC1 1 0 0x78
0xC2 1 0 0x78
0xE0 3 0 0x00 0x1B 0x02
0xE1 11 0 0x08 0xA0 0x00 0x00 0x07 0xA0 0x00 0x00 0x00 0x44 0x44
0xE2 12 0 0x11 0x11 0x44 0x44 0xED 0xA0 0x00 0x00 0xEC 0xA0 0x00 0x00
0xE3 4 0 0x00 0x00 0x11 0x11
0xE4 2 0 0x44 0x44
0xE5 16 0 0x0A 0xE9 0xD8 0xA0 0x0C 0xEB 0xD8 0xA0 0x0E 0xED 0xD8 0xA0 0x10 0xEF 0xD8 0xA0
0xE6 4 0 0x00 0x00 0x11 0x11
0xE7 2 0 0x44 0x44
0xE8 16 0 0x09 0xE8 0xD8 0xA0 0x0B 0xEA 0xD8 0xA0 0x0D 0xEC 0xD8 0xA0 0x0F 0xEE 0xD8 0xA0
0xEB 7 0 0x02 0x00 0xE4 0xE4 0x88 0x00 0x40
0xEC 2 0 0x3C 0x00
0xED 16 0 0xAB 0x89 0x76 0x54 0x02 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x20 0x45 0x67 0x98 0xBA
// VAP & VAN
0xFF 5 0 0x77 0x01 0x00 0x00 0x13
0xE5 1 0 0xE4
0xFF 5 0 0x77 0x01 0x00 0x00 0x00
0x3A 1 10 0x60 // 0x70 RGB888, 0x60 RGB666, 0x50 RGB565
0x11 0 120 // Sleep Out
0x29 0 0 // Display On
];
backlight = <&display_backlight>;
};
spi0 {
+17 -18
View File
@@ -1,22 +1,21 @@
[general]
vendor=CYD
name=4848S040C
general.vendor=CYD
general.name=4848S040C
[apps]
launcherAppId=Launcher
apps.launcherAppId=Launcher
[hardware]
target=ESP32S3
flashSize=16MB
spiRam=true
spiRamMode=OCT
spiRamSpeed=80M
bluetooth=true
hardware.target=ESP32S3
hardware.flashSize=16MB
hardware.spiRam=true
hardware.spiRamMode=OCT
hardware.spiRamSpeed=80M
hardware.bluetooth=true
[display]
size=4"
shape=rectangle
dpi=170
dependencies.useDeprecatedHal=false
[lvgl]
colorDepth=16
storage.userDataLocation=SD
display.size=4"
display.shape=rectangle
display.dpi=170
lvgl.colorDepth=16
+2
View File
@@ -1,3 +1,5 @@
dependencies:
- Platforms/platform-esp32
- Drivers/st7701-module
- Drivers/gt911-module
dts: cyd,4848s040c.dts
@@ -3,12 +3,10 @@
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
+2 -3
View File
@@ -1,7 +1,6 @@
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port esp_lcd RgbDisplay GT911 PwmBacklight driver vfs fatfs
REQUIRES TactilityKernel driver
)
@@ -1,22 +0,0 @@
#include "PwmBacklight.h"
#include "devices/Display.h"
#include <Tactility/hal/Configuration.h>
using namespace tt::hal;
static bool initBoot() {
// Display backlight
return driver::pwmbacklight::init(GPIO_NUM_2, 200);
}
static DeviceVector createDevices() {
return {
createDisplay(),
};
}
extern const Configuration hardwareConfiguration = {
.initBoot = initBoot,
.createDevices = createDevices
};
@@ -1,108 +0,0 @@
#include "Display.h"
#include <Gt911Touch.h>
#include <PwmBacklight.h>
#include <RgbDisplay.h>
#include <tactility/check.h>
#include <tactility/device.h>
std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
// Note for future changes: Reset pin is 38 and interrupt pin is 18
// or INT = NC, schematic and other info floating around is kinda conflicting...
auto* i2c = device_find_by_name("i2c_internal");
check(i2c);
auto configuration = std::make_unique<Gt911Touch::Configuration>(
i2c,
800,
480
);
return std::make_shared<Gt911Touch>(std::move(configuration));
}
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
auto touch = createTouch();
constexpr uint32_t bufferPixels = 800 * 10;
esp_lcd_rgb_panel_config_t rgb_panel_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.timings = {
.pclk_hz = 16000000,
.h_res = 800,
.v_res = 480,
.hsync_pulse_width = 4,
.hsync_back_porch = 8,
.hsync_front_porch = 8,
.vsync_pulse_width = 4,
.vsync_back_porch = 8,
.vsync_front_porch = 8,
.flags = {
.hsync_idle_low = false,
.vsync_idle_low = false,
.de_idle_high = false,
.pclk_active_neg = true,
.pclk_idle_high = false
}
},
.data_width = 16,
.bits_per_pixel = 0,
.num_fbs = 2,
.bounce_buffer_size_px = bufferPixels,
.sram_trans_align = 8,
.psram_trans_align = 64,
.hsync_gpio_num = GPIO_NUM_39,
.vsync_gpio_num = GPIO_NUM_41,
.de_gpio_num = GPIO_NUM_40 ,
.pclk_gpio_num = GPIO_NUM_42,
.disp_gpio_num = GPIO_NUM_NC,
.data_gpio_nums = {
GPIO_NUM_8, // B3
GPIO_NUM_3, // B4
GPIO_NUM_46, // B5
GPIO_NUM_9, // B6
GPIO_NUM_1, // B7
GPIO_NUM_5, // G2
GPIO_NUM_6, // G3
GPIO_NUM_7, // G4
GPIO_NUM_15, // G5
GPIO_NUM_16, // G6
GPIO_NUM_4, // G7
GPIO_NUM_45, // R3
GPIO_NUM_48, // R4
GPIO_NUM_47, // R5
GPIO_NUM_21, // R6
GPIO_NUM_14, // R7
},
.flags = {
.disp_active_low = false,
.refresh_on_demand = false,
.fb_in_psram = true,
.double_fb = true,
.no_fb = false,
.bb_invalidate_cache = false
}
};
RgbDisplay::BufferConfiguration buffer_config = {
.size = (800 * 480),
.useSpi = true,
.doubleBuffer = true,
.bounceBufferMode = true,
.avoidTearing = false
};
auto configuration = std::make_unique<RgbDisplay::Configuration>(
rgb_panel_config,
buffer_config,
touch,
LV_COLOR_FORMAT_RGB565,
false,
false,
false,
false,
driver::pwmbacklight::setBacklightDuty
);
return std::make_shared<RgbDisplay>(std::move(configuration));
}
@@ -1,5 +0,0 @@
#pragma once
#include "Tactility/hal/display/DisplayDevice.h"
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();

Some files were not shown because too many files have changed in this diff Show More