Compare commits

..

1 Commits

Author SHA1 Message Date
Adolfo Reyna 99ac246ab5 Associate .mp3 files with the Mp3Player application in Files browser 2026-06-28 22:24:45 -04:00
1646 changed files with 27089 additions and 70860 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ inputs:
runs:
using: "composite"
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
submodules: recursive
- name: 'Board select'
+1 -1
View File
@@ -11,7 +11,7 @@ inputs:
runs:
using: "composite"
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
with:
submodules: recursive
- name: 'Board select'
+1 -1
View File
@@ -15,7 +15,7 @@ runs:
using: "composite"
steps:
- name: "Checkout repo"
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Linux Dependencies for SDL
+2 -6
View File
@@ -10,9 +10,7 @@ jobs:
Linux:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: "Build"
uses: ./.github/actions/build-simulator
with:
@@ -22,9 +20,7 @@ jobs:
macOS:
runs-on: macos-latest
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: "Build"
uses: ./.github/actions/build-simulator
with:
+56 -26
View File
@@ -22,34 +22,66 @@ jobs:
]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: "Build SDK"
uses: ./.github/actions/build-sdk
with:
board_id: ${{ matrix.board.id }}
arch: ${{ matrix.board.arch }}
GenerateDeviceMatrix:
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 }
]
runs-on: ubuntu-latest
needs: [ BuildSdk ]
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- 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
- uses: actions/checkout@v4
- name: "Build Firmware"
uses: ./.github/actions/build-firmware
with:
@@ -62,9 +94,7 @@ jobs:
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: "Bundle Artifacts"
uses: ./.github/actions/bundle-artifacts
PublishFirmwareSnapshot:
@@ -72,7 +102,7 @@ jobs:
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: "Publish Firmware Snapshot"
env:
CDN_ID: ${{ secrets.CDN_ID }}
@@ -86,7 +116,7 @@ jobs:
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- name: "Publish Firmware Stable"
env:
CDN_ID: ${{ secrets.CDN_ID }}
@@ -100,7 +130,7 @@ jobs:
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- 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@v6
uses: actions/checkout@v4
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 Tactility Tests"
- name: "Run TactilityHeadless 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:
- uses: actions/checkout@v6
- name: "Checkout repo"
uses: actions/checkout@v4
with:
persist-credentials: false
submodules: recursive
- name: "Install Python Dependencies"
shell: bash
-1
View File
@@ -3,7 +3,6 @@
build/
buildsim/
build-*/
cmake-*/
CMakeCache.txt
*.cbp
+26 -21
View File
@@ -2,9 +2,11 @@ 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"
@@ -66,29 +68,32 @@ def exit_with_error(message):
sys.exit(1)
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
config = configparser.RawConfigParser()
# Don't convert keys to lowercase
config.optionxform = str
config.read(path)
return config
def get_property_or_none(properties: dict, group: str, key: str):
return properties.get(f"{group}.{key}")
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_boolean_property_or_false(properties: dict, group: str, key: str):
return properties.get(f"{group}.{key}") == "true"
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_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 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 read_device_properties(device_id):
mapping_file_path = os.path.join(DEVICES_FOLDER, device_id, "device.properties")
@@ -124,7 +129,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: dict, version: str):
def process_device(in_path: str, out_path: str, device_directory: str, device_id: str, device_properties: RawConfigParser, 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,8 +46,6 @@ 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,11 +79,6 @@ 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()
@@ -118,25 +113,6 @@ 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:
@@ -161,7 +137,7 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
node_name = get_device_node_name_safe(device)
result = []
array_decls = []
phandle_arrays = []
for binding_property in binding_properties:
device_property = find_device_property(device, binding_property.name)
@@ -172,35 +148,7 @@ 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)
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))
phandle_arrays.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:
@@ -215,7 +163,6 @@ 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,
@@ -232,20 +179,19 @@ 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, array_decls
return result, phandle_arrays
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, array_decls = resolve_parameters_from_bindings(device, bindings, devices)
config_params, phandle_arrays = resolve_parameters_from_bindings(device, bindings, devices)
# Write phandle-array/array variables before the config struct
for array_var, element_type, entries in array_decls:
# Write phandle-array variables before the config struct
for array_var, element_type, entries in phandle_arrays:
entries_str = ", ".join(entries)
file.write(f"static {element_type} {array_var}[] = {{ {entries_str} }};\n")
@@ -40,8 +40,6 @@ class BindingProperty:
description: str
default: object = None
element_type: str = None
min: object = None
max: object = None
@dataclass
class Binding:
@@ -76,225 +76,6 @@ 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:
@@ -315,14 +96,7 @@ if __name__ == "__main__":
tests = [
test_compile_success,
test_compile_invalid_dts,
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
test_compile_missing_config
]
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 -
+6 -1
View File
@@ -5,7 +5,12 @@ idf_component_register(
"Libraries/TactilityFreeRtos/include"
"Libraries/lvgl/include"
"Modules/lvgl-module/include"
# DRIVER_INCLUDE_DIRS_PLACEHOLDER
"Drivers/bm8563-module/include"
"Drivers/bmi270-module/include"
"Drivers/mpu6886-module/include"
"Drivers/pi4ioe5v6408-module/include"
"Drivers/qmi8658-module/include"
"Drivers/rx8130ce-module/include"
REQUIRES esp_timer
)
+6 -1
View File
@@ -25,7 +25,12 @@ macro(tactility_project project_name)
set(COMPONENTS
TactilityFreeRtos
# DRIVER_COMPONENTS_PLACEHOLDER
bm8563-module
bmi270-module
mpu6886-module
pi4ioe5v6408-module
qmi8658-module
rx8130ce-module
)
endmacro()
-135
View File
@@ -1,135 +0,0 @@
#!/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
@@ -1,57 +0,0 @@
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
@@ -1,126 +0,0 @@
#!/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()
+5 -11
View File
@@ -1,11 +1,4 @@
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
@@ -13,8 +6,6 @@ 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 ()
@@ -37,6 +28,7 @@ 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)
@@ -45,7 +37,9 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
continue()
endif ()
if (line MATCHES "^([^=]+)=(.*)$")
if (line MATCHES "^\\[.*\\]$")
set(current_section "${line}")
elseif (line MATCHES "^([^=]+)=(.*)$")
set(key "${CMAKE_MATCH_1}")
set(value "${CMAKE_MATCH_2}")
string(STRIP "${key}" key)
@@ -55,7 +49,7 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
set(value "${CMAKE_MATCH_1}")
endif ()
list(APPEND map_content "${key}" "${value}")
list(APPEND map_content "${current_section}${key}" "${value}")
endif ()
endforeach()
+10 -60
View File
@@ -88,17 +88,6 @@ 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)
@@ -111,44 +100,6 @@ 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]")
@@ -185,24 +136,23 @@ 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 - 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)
# 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")
# Output ESP-IDF SDK version to file
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
-84
View File
@@ -1,84 +0,0 @@
#!/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()
+1 -24
View File
@@ -9,8 +9,7 @@ CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
# EmbedTLS
# Use TLS 1.2 because 1.3 conflicts with MbedTLS dynamic buffer
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
# LVGL
CONFIG_LV_USE_USER_DATA=y
CONFIG_LV_USE_FS_STDIO=y
@@ -26,9 +25,6 @@ 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
@@ -44,22 +40,3 @@ 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
+2 -8
View File
@@ -43,6 +43,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
"TactilityKernel"
"Tactility"
"TactilityC"
"TactilityCore"
"TactilityFreeRtos"
"Libraries/elf_loader"
"Libraries/lv_screenshot"
@@ -69,17 +70,10 @@ 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)
@@ -87,6 +81,7 @@ 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)
@@ -98,7 +93,6 @@ 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 "")
@@ -0,0 +1 @@
enableOnBoot=false
@@ -0,0 +1 @@
enableOnBoot=false
@@ -0,0 +1 @@
enableOnBoot=false
+5
View File
@@ -0,0 +1,5 @@
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="" onkeydown="if(event.key==='Enter')refreshFiles()">
<input type="text" id="pathInput" value="/data" 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,6 +739,7 @@ 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
@@ -0,0 +1,63 @@
<!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
@@ -0,0 +1,3 @@
{
"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
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port esp_lcd RgbDisplay GT911 PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,31 @@
#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
};
@@ -0,0 +1,107 @@
#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));
}
@@ -12,8 +12,8 @@ static error_t stop() {
return ERROR_NONE;
}
struct Module lilygo_tdeck_max_module = {
.name = "lilygo-tdeck-max",
struct Module btt_panda_touch_module = {
.name = "btt-panda-touch",
.start = start,
.stop = stop,
.symbols = nullptr,
@@ -2,28 +2,17 @@
#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 {
@@ -37,15 +26,6 @@
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 {
@@ -56,57 +36,6 @@
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";
+21 -20
View File
@@ -1,24 +1,25 @@
general.vendor=BigTreeTech
general.name=Panda Touch,K Touch
[general]
vendor=BigTreeTech
name=Panda Touch,K Touch
apps.launcherAppId=Launcher
[apps]
launcherAppId=Launcher
hardware.target=ESP32S3
hardware.flashSize=16MB
hardware.spiRam=true
hardware.spiRamMode=OCT
hardware.spiRamSpeed=120M
hardware.esptoolFlashFreq=120M
hardware.bluetooth=true
hardware.usbHostEnabled=true
[hardware]
target=ESP32S3
flashSize=16MB
spiRam=true
spiRamMode=OCT
spiRamSpeed=120M
esptoolFlashFreq=120M
bluetooth=true
usbHostEnabled=true
dependencies.useDeprecatedHal=false
[display]
size=5"
shape=rectangle
dpi=187
storage.userDataLocation=Internal
display.size=5"
display.shape=rectangle
display.dpi=187
lvgl.colorDepth=16
lvgl.fontSize=18
[lvgl]
colorDepth=16
fontSize=18
-2
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/rgb-display-module
- Drivers/gt911-module
dts: bigtreetech,panda-touch.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module btt_panda_touch_module = {
.name = "btt-panda-touch",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x CST816S PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,30 @@
#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
};
@@ -0,0 +1,45 @@
#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);
}
@@ -0,0 +1,18 @@
#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();
+23
View File
@@ -0,0 +1,23 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module cyd_2432s024c_module = {
.name = "cyd-2432s024c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
+5 -83
View File
@@ -1,26 +1,16 @@
/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/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>
#include <tactility/bindings/display_placeholder.h>
/ {
compatible = "root";
model = "CYD 2432S024C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -32,66 +22,6 @@
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 {
@@ -100,16 +30,9 @@
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
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>;
display {
compatible = "display-placeholder";
};
};
@@ -120,8 +43,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";
frequency-khz = <20000>;
+15 -14
View File
@@ -1,18 +1,19 @@
general.vendor=CYD
general.name=2432S024C
[general]
vendor=CYD
name=2432S024C
apps.launcherAppId=Launcher
[apps]
launcherAppId=Launcher
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
dependencies.useDeprecatedHal=false
[display]
size=2.4"
shape=rectangle
dpi=167
storage.userDataLocation=SD
display.size=2.4"
display.shape=rectangle
display.dpi=167
lvgl.colorDepth=16
[lvgl]
colorDepth=16
-2
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/cst816s-module
dts: cyd,2432s024c.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_2432s024c_module = {
.name = "cyd-2432s024c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046 PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,21 @@
#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
};
@@ -0,0 +1,46 @@
#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);
}
@@ -0,0 +1,28 @@
#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();
+23
View File
@@ -0,0 +1,23 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module cyd_2432s024r_module = {
.name = "cyd-2432s024r",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
+5 -79
View File
@@ -1,84 +1,22 @@
/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>;
@@ -89,23 +27,11 @@
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
display@0 {
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>;
compatible = "display-placeholder";
};
touch@1 {
compatible = "xptek,xpt2046";
x-max = <240>;
y-max = <320>;
swap-xy;
mirror-y;
compatible = "touch-placeholder";
};
};
@@ -129,4 +55,4 @@
pin-tx = <&gpio0 1 GPIO_FLAG_NONE>;
pin-rx = <&gpio0 3 GPIO_FLAG_NONE>;
};
};
};
+15 -14
View File
@@ -1,18 +1,19 @@
general.vendor=CYD
general.name=2432S024R
[general]
vendor=CYD
name=2432S024R
apps.launcherAppId=Launcher
[apps]
launcherAppId=Launcher
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
dependencies.useDeprecatedHal=false
[display]
size=2.4"
shape=rectangle
dpi=167
storage.userDataLocation=SD
display.size=2.4"
display.shape=rectangle
display.dpi=167
lvgl.colorDepth=16
[lvgl]
colorDepth=16
-2
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/xpt2046-module
dts: cyd,2432s024r.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module cyd_2432s024r_module = {
.name = "cyd-2432s024r",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046SoftSPI PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,32 @@
#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
};
@@ -0,0 +1,49 @@
#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);
}
@@ -0,0 +1,27 @@
#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();
+23
View File
@@ -0,0 +1,23 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module cyd_2432s028r_module = {
.name = "cyd-2432s028r",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
+10 -85
View File
@@ -1,27 +1,18 @@
/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/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>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
/ {
compatible = "root";
model = "CYD 2432S028R";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -35,87 +26,21 @@
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>;
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>, // Display
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
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>;
compatible = "display-placeholder";
};
touch@1 {
compatible = "touch-placeholder";
};
};
+17 -18
View File
@@ -1,23 +1,22 @@
general.vendor=CYD
general.name=2432S028R
[general]
vendor=CYD
name=2432S028R
apps.launcherAppId=Launcher
[apps]
launcherAppId=Launcher
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
dependencies.useDeprecatedHal=false
[display]
size=2.8"
shape=rectangle
dpi=143
storage.userDataLocation=SD
[cdn]
warningMessage=There are 3 hardware variants of this board. This build works on the original variant only ("v1").
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
[lvgl]
colorDepth=16
-2
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/xpt2046-softspi-module
dts: cyd,2432s028r.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module cyd_2432s028r_module = {
.name = "cyd-2432s028r",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ST7789 XPT2046SoftSPI PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,32 @@
#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
};
@@ -0,0 +1,50 @@
#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);
}
@@ -0,0 +1,27 @@
#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();
+23
View File
@@ -0,0 +1,23 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module cyd_2432s028rv3_module = {
.name = "cyd-2432s028rv3",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
+11 -84
View File
@@ -1,27 +1,18 @@
/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/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>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
/ {
compatible = "root";
model = "CYD 2432S028R v3";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -35,85 +26,21 @@
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>;
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>, // Display
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
display@0 {
compatible = "sitronix,st7789";
horizontal-resolution = <240>;
vertical-resolution = <320>;
pixel-clock-hz = <62500000>;
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
backlight = <&display_backlight>;
compatible = "display-placeholder";
};
touch@1 {
compatible = "touch-placeholder";
};
};
@@ -124,7 +51,7 @@
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
compatible = "espressif,esp32-sdspi";
frequency-khz = <20000>;
+17 -18
View File
@@ -1,23 +1,22 @@
general.vendor=CYD
general.name=2432S028R v3
[general]
vendor=CYD
name=2432S028R v3
apps.launcherAppId=Launcher
[apps]
launcherAppId=Launcher
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
dependencies.useDeprecatedHal=false
[display]
size=2.8"
shape=rectangle
dpi=143
storage.userDataLocation=SD
[cdn]
warningMessage=There are 3 hardware variants of this board. This build only supports board version 3.
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
[lvgl]
colorDepth=16
-2
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/st7789-module
- Drivers/xpt2046-softspi-module
dts: cyd,2432s028rv3.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
struct Module cyd_2432s028rv3_module = {
.name = "cyd-2432s028rv3",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ILI934x GT911 PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,47 @@
#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
};
@@ -0,0 +1,48 @@
#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);
}
@@ -0,0 +1,18 @@
#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();
+23
View File
@@ -0,0 +1,23 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module cyd_2432s032c_module = {
.name = "cyd-2432s032c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
+4 -85
View File
@@ -1,26 +1,16 @@
/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/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>
#include <tactility/bindings/display_placeholder.h>
/ {
compatible = "root";
model = "CYD 2432S032C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -32,66 +22,6 @@
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 {
@@ -100,20 +30,9 @@
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
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>;
display {
compatible = "display-placeholder";
};
};
+15 -14
View File
@@ -1,18 +1,19 @@
general.vendor=CYD
general.name=2432S032C
[general]
vendor=CYD
name=2432S032C
apps.launcherAppId=Launcher
[apps]
launcherAppId=Launcher
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
dependencies.useDeprecatedHal=false
[display]
size=3.2"
shape=rectangle
dpi=125
storage.userDataLocation=SD
display.size=3.2"
display.shape=rectangle
display.dpi=125
lvgl.colorDepth=16
[lvgl]
colorDepth=16
-2
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/ili9341-module
- Drivers/gt911-module
dts: cyd,2432s032c.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_2432s032c_module = {
.name = "cyd-2432s032c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel
INCLUDE_DIRS "Source"
REQUIRES Tactility esp_lvgl_port ST7796 GT911 PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,32 @@
#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
};
@@ -0,0 +1,40 @@
#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);
}
@@ -0,0 +1,20 @@
#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();
+23
View File
@@ -0,0 +1,23 @@
#include <tactility/module.h>
extern "C" {
static error_t start() {
// Empty for now
return ERROR_NONE;
}
static error_t stop() {
// Empty for now
return ERROR_NONE;
}
struct Module cyd_3248s035c_module = {
.name = "cyd-3248s035c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
};
}
+4 -80
View File
@@ -1,27 +1,17 @@
/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/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>
#include <tactility/bindings/display_placeholder.h>
/ {
compatible = "root";
model = "CYD 3248S035C";
wifi0 {
compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
};
gpio0 {
compatible = "espressif,esp32-gpio";
gpio-count = <40>;
@@ -33,13 +23,6 @@
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
@@ -51,74 +34,15 @@
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>;
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
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>;
display {
compatible = "display-placeholder";
};
};
+19 -18
View File
@@ -1,18 +1,19 @@
general.vendor=CYD
general.name=3248S035C
apps.launcherAppId=Launcher
hardware.target=ESP32
hardware.flashSize=4MB
hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD
display.size=3.5"
display.shape=rectangle
display.dpi=165
lvgl.colorDepth=16
[general]
vendor=CYD
name=3248S035C
[apps]
launcherAppId=Launcher
[hardware]
target=ESP32
flashSize=4MB
spiRam=false
[display]
size=3.5"
shape=rectangle
dpi=165
[lvgl]
colorDepth=16
+1 -3
View File
@@ -1,5 +1,3 @@
dependencies:
- Platforms/platform-esp32
- Drivers/st7796-module
- Drivers/gt911-module
- Platforms/platform-esp32
dts: cyd,3248s035c.dts
-14
View File
@@ -1,14 +0,0 @@
#include <tactility/error.h>
#include <tactility/module.h>
extern "C" {
Module cyd_3248s035c_module = {
.name = "cyd-3248s035c",
.start = [] -> error_t { return ERROR_NONE; },
.stop = [] -> error_t { return ERROR_NONE; },
.symbols = nullptr,
.internal = nullptr
};
}
+3 -2
View File
@@ -1,6 +1,7 @@
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel driver
INCLUDE_DIRS "Source"
REQUIRES Tactility EspLcdCompat esp_lcd_st7701 esp_lcd_panel_io_additions GT911 PwmBacklight driver vfs fatfs
)
@@ -0,0 +1,21 @@
#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
};
@@ -0,0 +1,242 @@
#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);
}
@@ -0,0 +1,36 @@
#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; }
};

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