Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cd99a8d7c1 | |||
| 2720556d6a | |||
| 2fbc44466a | |||
| 2d768ef3a1 | |||
| bd30aa046a | |||
| f9453d8956 | |||
| 5f54f7ca3d | |||
| d896657bf9 | |||
| 3b5a401594 | |||
| 6fb2bb736c | |||
| bd8fdfd858 | |||
| 8af6204ba1 | |||
| 955416dac8 | |||
| fa4a6e255c | |||
| 50c0a14a93 | |||
| c4406b24ba | |||
| 0922c4d55b | |||
| 7a7f09be35 | |||
| 16a61a087c | |||
| 1c2806bddf | |||
| dbb96a891c | |||
| d6ac070e30 | |||
| f4f91f81d6 | |||
| cca7224252 | |||
| 66a4eb66d6 | |||
| dfaeb9a2d9 | |||
| 9d5993930d | |||
| ecad2248d9 | |||
| a323f8e148 | |||
| 05720821f8 | |||
| 90afba647e | |||
| 35fd7dd536 | |||
| cd07c64926 | |||
| 2f5e183f18 | |||
| d3439f6f45 |
@@ -11,7 +11,7 @@ inputs:
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: 'Board select'
|
- name: 'Board select'
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ inputs:
|
|||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: 'Board select'
|
- name: 'Board select'
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ runs:
|
|||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout repo"
|
- name: "Checkout repo"
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Install Linux Dependencies for SDL
|
- name: Install Linux Dependencies for SDL
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ jobs:
|
|||||||
Linux:
|
Linux:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Build"
|
- name: "Build"
|
||||||
uses: ./.github/actions/build-simulator
|
uses: ./.github/actions/build-simulator
|
||||||
with:
|
with:
|
||||||
@@ -20,7 +22,9 @@ jobs:
|
|||||||
macOS:
|
macOS:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Build"
|
- name: "Build"
|
||||||
uses: ./.github/actions/build-simulator
|
uses: ./.github/actions/build-simulator
|
||||||
with:
|
with:
|
||||||
|
|||||||
+26
-56
@@ -22,66 +22,34 @@ jobs:
|
|||||||
]
|
]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Build SDK"
|
- name: "Build SDK"
|
||||||
uses: ./.github/actions/build-sdk
|
uses: ./.github/actions/build-sdk
|
||||||
with:
|
with:
|
||||||
board_id: ${{ matrix.board.id }}
|
board_id: ${{ matrix.board.id }}
|
||||||
arch: ${{ matrix.board.arch }}
|
arch: ${{ matrix.board.arch }}
|
||||||
BuildFirmware:
|
GenerateDeviceMatrix:
|
||||||
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
|
runs-on: ubuntu-latest
|
||||||
needs: [ BuildSdk ]
|
needs: [ BuildSdk ]
|
||||||
|
outputs:
|
||||||
|
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- id: set-matrix
|
||||||
|
run: python3 Buildscripts/gh-generate-device-matrix.py
|
||||||
|
BuildFirmware:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: GenerateDeviceMatrix
|
||||||
|
strategy:
|
||||||
|
matrix: ${{ fromJSON(needs.GenerateDeviceMatrix.outputs.matrix) }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Build Firmware"
|
- name: "Build Firmware"
|
||||||
uses: ./.github/actions/build-firmware
|
uses: ./.github/actions/build-firmware
|
||||||
with:
|
with:
|
||||||
@@ -94,7 +62,9 @@ jobs:
|
|||||||
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
||||||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
|
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
- name: "Bundle Artifacts"
|
- name: "Bundle Artifacts"
|
||||||
uses: ./.github/actions/bundle-artifacts
|
uses: ./.github/actions/bundle-artifacts
|
||||||
PublishFirmwareSnapshot:
|
PublishFirmwareSnapshot:
|
||||||
@@ -102,7 +72,7 @@ jobs:
|
|||||||
needs: [ BundleArtifacts ]
|
needs: [ BundleArtifacts ]
|
||||||
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
|
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: "Publish Firmware Snapshot"
|
- name: "Publish Firmware Snapshot"
|
||||||
env:
|
env:
|
||||||
CDN_ID: ${{ secrets.CDN_ID }}
|
CDN_ID: ${{ secrets.CDN_ID }}
|
||||||
@@ -116,7 +86,7 @@ jobs:
|
|||||||
needs: [ BundleArtifacts ]
|
needs: [ BundleArtifacts ]
|
||||||
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
|
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: "Publish Firmware Stable"
|
- name: "Publish Firmware Stable"
|
||||||
env:
|
env:
|
||||||
CDN_ID: ${{ secrets.CDN_ID }}
|
CDN_ID: ${{ secrets.CDN_ID }}
|
||||||
@@ -130,7 +100,7 @@ jobs:
|
|||||||
needs: [ BundleArtifacts ]
|
needs: [ BundleArtifacts ]
|
||||||
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: "Publish SDKs"
|
- name: "Publish SDKs"
|
||||||
env:
|
env:
|
||||||
CDN_ID: ${{ secrets.CDN_ID }}
|
CDN_ID: ${{ secrets.CDN_ID }}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout repo"
|
- name: "Checkout repo"
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: "Configure Project"
|
- name: "Configure Project"
|
||||||
@@ -19,20 +19,20 @@ jobs:
|
|||||||
run: cmake -S ./ -B build
|
run: cmake -S ./ -B build
|
||||||
- name: "Build Tests"
|
- name: "Build Tests"
|
||||||
run: cmake --build build --target build-tests
|
run: cmake --build build --target build-tests
|
||||||
- name: "Run TactilityCore Tests"
|
|
||||||
run: build/Tests/TactilityCore/TactilityCoreTests
|
|
||||||
- name: "Run TactilityFreeRtos Tests"
|
- name: "Run TactilityFreeRtos Tests"
|
||||||
run: build/Tests/TactilityFreeRtos/TactilityFreeRtosTests
|
run: build/Tests/TactilityFreeRtos/TactilityFreeRtosTests
|
||||||
- name: "Run TactilityHeadless Tests"
|
- name: "Run Tactility Tests"
|
||||||
run: build/Tests/Tactility/TactilityTests
|
run: build/Tests/Tactility/TactilityTests
|
||||||
- name: "Run TactilityKernel Tests"
|
- name: "Run TactilityKernel Tests"
|
||||||
run: build/Tests/TactilityKernel/TactilityKernelTests
|
run: build/Tests/TactilityKernel/TactilityKernelTests
|
||||||
|
- name: "Run CryptModuleTests Tests"
|
||||||
|
run: build/Tests/crypt-module/CryptModuleTests
|
||||||
DevicetreeTests:
|
DevicetreeTests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout repo"
|
- uses: actions/checkout@v6
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
with:
|
||||||
|
persist-credentials: false
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: "Install Python Dependencies"
|
- name: "Install Python Dependencies"
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
build/
|
build/
|
||||||
buildsim/
|
buildsim/
|
||||||
|
build-*/
|
||||||
cmake-*/
|
cmake-*/
|
||||||
CMakeCache.txt
|
CMakeCache.txt
|
||||||
*.cbp
|
*.cbp
|
||||||
|
|||||||
@@ -2,11 +2,9 @@ import subprocess
|
|||||||
from datetime import datetime, UTC
|
from datetime import datetime, UTC
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import configparser
|
|
||||||
from dataclasses import dataclass, asdict
|
from dataclasses import dataclass, asdict
|
||||||
import json
|
import json
|
||||||
import shutil
|
import shutil
|
||||||
from configparser import RawConfigParser
|
|
||||||
|
|
||||||
VERBOSE = False
|
VERBOSE = False
|
||||||
DEVICES_FOLDER = "Devices"
|
DEVICES_FOLDER = "Devices"
|
||||||
@@ -68,32 +66,29 @@ def exit_with_error(message):
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def read_properties_file(path):
|
def read_properties_file(path):
|
||||||
config = configparser.RawConfigParser()
|
properties = {}
|
||||||
# Don't convert keys to lowercase
|
with open(path, "r") as file:
|
||||||
config.optionxform = str
|
for line in file:
|
||||||
config.read(path)
|
stripped = line.strip()
|
||||||
return config
|
if not stripped or stripped.startswith("#"):
|
||||||
|
continue
|
||||||
|
key, sep, value = line.partition("=")
|
||||||
|
if not sep:
|
||||||
|
continue
|
||||||
|
properties[key.strip()] = value.strip()
|
||||||
|
return properties
|
||||||
|
|
||||||
def get_property_or_none(properties: RawConfigParser, group: str, key: str):
|
def get_property_or_none(properties: dict, group: str, key: str):
|
||||||
if group not in properties.sections():
|
return properties.get(f"{group}.{key}")
|
||||||
return None
|
|
||||||
if key not in properties[group].keys():
|
|
||||||
return None
|
|
||||||
return properties[group][key]
|
|
||||||
|
|
||||||
def get_boolean_property_or_false(properties: RawConfigParser, group: str, key: str):
|
def get_boolean_property_or_false(properties: dict, group: str, key: str):
|
||||||
if group not in properties.sections():
|
return properties.get(f"{group}.{key}") == "true"
|
||||||
return False
|
|
||||||
if key not in properties[group].keys():
|
|
||||||
return False
|
|
||||||
return properties[group][key] == "true"
|
|
||||||
|
|
||||||
def get_property_or_exit(properties: RawConfigParser, group: str, key: str):
|
def get_property_or_exit(properties: dict, group: str, key: str):
|
||||||
if group not in properties.sections():
|
full_key = f"{group}.{key}"
|
||||||
exit_with_error(f"Device properties does not contain group: {group}")
|
if full_key not in properties:
|
||||||
if key not in properties[group].keys():
|
exit_with_error(f"Device properties does not contain key: {full_key}")
|
||||||
exit_with_error(f"Device properties does not contain key: {key}")
|
return properties[full_key]
|
||||||
return properties[group][key]
|
|
||||||
|
|
||||||
def read_device_properties(device_id):
|
def read_device_properties(device_id):
|
||||||
mapping_file_path = os.path.join(DEVICES_FOLDER, device_id, "device.properties")
|
mapping_file_path = os.path.join(DEVICES_FOLDER, device_id, "device.properties")
|
||||||
@@ -129,7 +124,7 @@ def to_manifest_chip_name(name):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def process_device(in_path: str, out_path: str, device_directory: str, device_id: str, device_properties: RawConfigParser, version: str):
|
def process_device(in_path: str, out_path: str, device_directory: str, device_id: str, device_properties: dict, version: str):
|
||||||
in_device_path = os.path.join(in_path, device_directory)
|
in_device_path = os.path.join(in_path, device_directory)
|
||||||
in_device_binaries_path = os.path.join(in_device_path, "Binaries")
|
in_device_binaries_path = os.path.join(in_device_path, "Binaries")
|
||||||
if not os.path.isdir(in_device_binaries_path):
|
if not os.path.isdir(in_device_binaries_path):
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding:
|
|||||||
description=details.get('description', '').strip(),
|
description=details.get('description', '').strip(),
|
||||||
default=details.get('default', None),
|
default=details.get('default', None),
|
||||||
element_type=details.get('element-type', None),
|
element_type=details.get('element-type', None),
|
||||||
|
min=details.get('min', None),
|
||||||
|
max=details.get('max', None),
|
||||||
)
|
)
|
||||||
properties_dict[name] = prop
|
properties_dict[name] = prop
|
||||||
filename = os.path.basename(file_path)
|
filename = os.path.basename(file_path)
|
||||||
|
|||||||
@@ -79,6 +79,11 @@ def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
|
|||||||
value_list.append(str(item))
|
value_list.append(str(item))
|
||||||
return "{ " + ",".join(value_list) + " }"
|
return "{ " + ",".join(value_list) + " }"
|
||||||
elif type == "phandle":
|
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)
|
return find_phandle(devices, property.value)
|
||||||
elif type == "phandles":
|
elif type == "phandles":
|
||||||
value_list = list()
|
value_list = list()
|
||||||
@@ -113,6 +118,25 @@ def resolve_phandle_array_entries(device_property, devices):
|
|||||||
entries.append(str(item))
|
entries.append(str(item))
|
||||||
return entries
|
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:
|
def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], devices: list[Device]) -> list:
|
||||||
compatible_property = find_device_property(device, "compatible")
|
compatible_property = find_device_property(device, "compatible")
|
||||||
if compatible_property is None:
|
if compatible_property is None:
|
||||||
@@ -137,7 +161,7 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
|
|||||||
|
|
||||||
node_name = get_device_node_name_safe(device)
|
node_name = get_device_node_name_safe(device)
|
||||||
result = []
|
result = []
|
||||||
phandle_arrays = []
|
array_decls = []
|
||||||
for binding_property in binding_properties:
|
for binding_property in binding_properties:
|
||||||
device_property = find_device_property(device, binding_property.name)
|
device_property = find_device_property(device, binding_property.name)
|
||||||
|
|
||||||
@@ -148,7 +172,35 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
|
|||||||
array_var = f"{node_name}_{prop_safe}"
|
array_var = f"{node_name}_{prop_safe}"
|
||||||
if device_property is not None:
|
if device_property is not None:
|
||||||
entries = resolve_phandle_array_entries(device_property, devices)
|
entries = resolve_phandle_array_entries(device_property, devices)
|
||||||
phandle_arrays.append((array_var, binding_property.element_type, entries))
|
array_decls.append((array_var, binding_property.element_type, entries))
|
||||||
|
result.append(f"({binding_property.element_type}*){array_var}")
|
||||||
|
result.append(str(len(entries)))
|
||||||
|
elif binding_property.default is not None:
|
||||||
|
result.append("NULL")
|
||||||
|
result.append("0")
|
||||||
|
elif binding_property.required:
|
||||||
|
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
|
||||||
|
else:
|
||||||
|
result.append("NULL")
|
||||||
|
result.append("0")
|
||||||
|
continue
|
||||||
|
|
||||||
|
if binding_property.type == "array":
|
||||||
|
# A flat literal array (DTS `[ ... ]` syntax, e.g. a byte blob), as opposed to
|
||||||
|
# phandle-array's list of resolved device references. Emits the same
|
||||||
|
# (pointer, length) parameter pair, backed by a plain data array instead of one
|
||||||
|
# holding phandle-derived initializers.
|
||||||
|
if binding_property.element_type is None:
|
||||||
|
raise DevicetreeException(f"array property '{binding_property.name}' requires 'element-type' in binding")
|
||||||
|
prop_safe = binding_property.name.replace("-", "_")
|
||||||
|
array_var = f"{node_name}_{prop_safe}"
|
||||||
|
if device_property is not None:
|
||||||
|
if device_property.type != "array":
|
||||||
|
raise DevicetreeException(
|
||||||
|
f"Device '{device.node_name}' property '{binding_property.name}' must use '[ ... ]' array syntax"
|
||||||
|
)
|
||||||
|
entries = [str(value) for value in device_property.value]
|
||||||
|
array_decls.append((array_var, binding_property.element_type, entries))
|
||||||
result.append(f"({binding_property.element_type}*){array_var}")
|
result.append(f"({binding_property.element_type}*){array_var}")
|
||||||
result.append(str(len(entries)))
|
result.append(str(len(entries)))
|
||||||
elif binding_property.default is not None:
|
elif binding_property.default is not None:
|
||||||
@@ -163,6 +215,7 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
|
|||||||
|
|
||||||
if device_property is None:
|
if device_property is None:
|
||||||
if binding_property.default is not None:
|
if binding_property.default is not None:
|
||||||
|
validate_property_range(device, binding_property, binding_property.default)
|
||||||
temp_prop = DeviceProperty(
|
temp_prop = DeviceProperty(
|
||||||
name=binding_property.name,
|
name=binding_property.name,
|
||||||
type=binding_property.type,
|
type=binding_property.type,
|
||||||
@@ -179,19 +232,20 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
|
|||||||
else:
|
else:
|
||||||
raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set")
|
raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set")
|
||||||
else:
|
else:
|
||||||
|
validate_property_range(device, binding_property, device_property.value)
|
||||||
result.append(property_to_string(device_property, devices))
|
result.append(property_to_string(device_property, devices))
|
||||||
|
|
||||||
return result, phandle_arrays
|
return result, array_decls
|
||||||
|
|
||||||
def write_config(file, device: Device, bindings: list[Binding], devices: list[Device], type_name: str):
|
def write_config(file, device: Device, bindings: list[Binding], devices: list[Device], type_name: str):
|
||||||
node_name = get_device_node_name_safe(device)
|
node_name = get_device_node_name_safe(device)
|
||||||
config_type = f"{type_name}_config_dt"
|
config_type = f"{type_name}_config_dt"
|
||||||
config_variable_name = f"{node_name}_config"
|
config_variable_name = f"{node_name}_config"
|
||||||
|
|
||||||
config_params, phandle_arrays = resolve_parameters_from_bindings(device, bindings, devices)
|
config_params, array_decls = resolve_parameters_from_bindings(device, bindings, devices)
|
||||||
|
|
||||||
# Write phandle-array variables before the config struct
|
# Write phandle-array/array variables before the config struct
|
||||||
for array_var, element_type, entries in phandle_arrays:
|
for array_var, element_type, entries in array_decls:
|
||||||
entries_str = ", ".join(entries)
|
entries_str = ", ".join(entries)
|
||||||
file.write(f"static {element_type} {array_var}[] = {{ {entries_str} }};\n")
|
file.write(f"static {element_type} {array_var}[] = {{ {entries_str} }};\n")
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ class BindingProperty:
|
|||||||
description: str
|
description: str
|
||||||
default: object = None
|
default: object = None
|
||||||
element_type: str = None
|
element_type: str = None
|
||||||
|
min: object = None
|
||||||
|
max: object = None
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Binding:
|
class Binding:
|
||||||
|
|||||||
@@ -76,6 +76,225 @@ def test_compile_invalid_dts():
|
|||||||
print("PASSED")
|
print("PASSED")
|
||||||
return True
|
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():
|
def test_compile_missing_config():
|
||||||
print("Running test_compile_missing_config...")
|
print("Running test_compile_missing_config...")
|
||||||
with tempfile.TemporaryDirectory() as output_dir:
|
with tempfile.TemporaryDirectory() as output_dir:
|
||||||
@@ -96,7 +315,14 @@ if __name__ == "__main__":
|
|||||||
tests = [
|
tests = [
|
||||||
test_compile_success,
|
test_compile_success,
|
||||||
test_compile_invalid_dts,
|
test_compile_invalid_dts,
|
||||||
test_compile_missing_config
|
test_compile_missing_config,
|
||||||
|
test_minmax_within_range_succeeds,
|
||||||
|
test_minmax_below_minimum_fails,
|
||||||
|
test_minmax_above_maximum_fails,
|
||||||
|
test_minmax_out_of_range_default_fails,
|
||||||
|
test_minmax_symbolic_value_skips_validation,
|
||||||
|
test_array_property_generates_static_array_and_length,
|
||||||
|
test_array_property_defaults_to_null_when_absent
|
||||||
]
|
]
|
||||||
|
|
||||||
failed = 0
|
failed = 0
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ $jsonClean = $json.flash_files -replace '[\{\}\@\;]', ''
|
|||||||
$jsonClean = $jsonClean -replace '[\=]', ' '
|
$jsonClean = $jsonClean -replace '[\=]', ' '
|
||||||
|
|
||||||
cd Binaries
|
cd Binaries
|
||||||
$command = "esptool --port $port erase_flash"
|
$command = "esptool --port $port erase-flash"
|
||||||
Invoke-Expression $command
|
Invoke-Expression $command
|
||||||
$command = "esptool --port $port write_flash $jsonClean"
|
$command = "esptool --port $port write-flash $jsonClean"
|
||||||
Invoke-Expression $command
|
Invoke-Expression $command
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ fi
|
|||||||
# Take the flash_arg file contents and join each line in the file into a single line
|
# 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=' '`
|
flash_args=`grep \n Binaries/flash_args | awk '{print}' ORS=' '`
|
||||||
cd Binaries
|
cd Binaries
|
||||||
$esptoolPath --port $1 erase_flash
|
$esptoolPath --port $1 erase-flash
|
||||||
$esptoolPath --port $1 write_flash $flash_args
|
$esptoolPath --port $1 write-flash $flash_args
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,7 @@ idf_component_register(
|
|||||||
"Libraries/TactilityFreeRtos/include"
|
"Libraries/TactilityFreeRtos/include"
|
||||||
"Libraries/lvgl/include"
|
"Libraries/lvgl/include"
|
||||||
"Modules/lvgl-module/include"
|
"Modules/lvgl-module/include"
|
||||||
"Drivers/bm8563-module/include"
|
# DRIVER_INCLUDE_DIRS_PLACEHOLDER
|
||||||
"Drivers/bmi270-module/include"
|
|
||||||
"Drivers/mpu6886-module/include"
|
|
||||||
"Drivers/pi4ioe5v6408-module/include"
|
|
||||||
"Drivers/qmi8658-module/include"
|
|
||||||
"Drivers/rx8130ce-module/include"
|
|
||||||
REQUIRES esp_timer
|
REQUIRES esp_timer
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -25,12 +25,7 @@ macro(tactility_project project_name)
|
|||||||
|
|
||||||
set(COMPONENTS
|
set(COMPONENTS
|
||||||
TactilityFreeRtos
|
TactilityFreeRtos
|
||||||
bm8563-module
|
# DRIVER_COMPONENTS_PLACEHOLDER
|
||||||
bmi270-module
|
|
||||||
mpu6886-module
|
|
||||||
pi4ioe5v6408-module
|
|
||||||
qmi8658-module
|
|
||||||
rx8130ce-module
|
|
||||||
)
|
)
|
||||||
|
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|||||||
Executable
+135
@@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Download all artifacts from a GitHub Actions workflow run."""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import zipfile
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
API_URL = "https://api.github.com"
|
||||||
|
|
||||||
|
|
||||||
|
def get_token(cli_token: str | None) -> str:
|
||||||
|
if cli_token:
|
||||||
|
return cli_token
|
||||||
|
env_token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
||||||
|
if env_token:
|
||||||
|
return env_token
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["gh", "auth", "token"], capture_output=True, text=True, check=True
|
||||||
|
)
|
||||||
|
return result.stdout.strip()
|
||||||
|
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||||
|
sys.exit(
|
||||||
|
"No token found. Pass --token, set GITHUB_TOKEN/GH_TOKEN, or run `gh auth login`."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_repo(cli_repo: str | None) -> str:
|
||||||
|
if cli_repo:
|
||||||
|
return cli_repo
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["git", "remote", "get-url", "origin"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
url = result.stdout.strip()
|
||||||
|
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||||
|
sys.exit("Could not detect repo from git remote. Pass --repo owner/name.")
|
||||||
|
|
||||||
|
# Handle both SSH and HTTPS remote URLs.
|
||||||
|
if url.startswith("git@"):
|
||||||
|
path = url.split(":", 1)[1]
|
||||||
|
else:
|
||||||
|
path = url.split("github.com/", 1)[-1]
|
||||||
|
return path.removesuffix(".git")
|
||||||
|
|
||||||
|
|
||||||
|
def download_artifacts(repo: str, run_id: str, token: str, out_dir: Path):
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Accept": "application/vnd.github+json",
|
||||||
|
"X-GitHub-Api-Version": "2022-11-28",
|
||||||
|
}
|
||||||
|
|
||||||
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
url = f"{API_URL}/repos/{repo}/actions/runs/{run_id}/artifacts"
|
||||||
|
artifacts = []
|
||||||
|
while url:
|
||||||
|
resp = requests.get(url, headers=headers, params={"per_page": 100})
|
||||||
|
resp.raise_for_status()
|
||||||
|
data = resp.json()
|
||||||
|
artifacts.extend(data["artifacts"])
|
||||||
|
url = resp.links.get("next", {}).get("url")
|
||||||
|
|
||||||
|
if not artifacts:
|
||||||
|
print(f"No artifacts found for run {run_id}.")
|
||||||
|
return
|
||||||
|
|
||||||
|
for artifact in artifacts:
|
||||||
|
name = artifact["name"]
|
||||||
|
if name == "all-artifacts":
|
||||||
|
print(f"Skipping {name}")
|
||||||
|
continue
|
||||||
|
if artifact.get("expired"):
|
||||||
|
print(f"Skipping expired artifact: {name}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
print(f"Downloading {name} ({artifact['size_in_bytes']} bytes)...")
|
||||||
|
download_url = artifact["archive_download_url"]
|
||||||
|
resp = requests.get(download_url, headers=headers, stream=True)
|
||||||
|
resp.raise_for_status()
|
||||||
|
|
||||||
|
zip_path = out_dir / f"{name}.zip"
|
||||||
|
with open(zip_path, "wb") as f:
|
||||||
|
for chunk in resp.iter_content(chunk_size=8192):
|
||||||
|
f.write(chunk)
|
||||||
|
|
||||||
|
if name.endswith(".bin"):
|
||||||
|
with zipfile.ZipFile(zip_path) as zf:
|
||||||
|
zf.extractall(out_dir)
|
||||||
|
zip_path.unlink()
|
||||||
|
print(f" Extracted to {out_dir}")
|
||||||
|
else:
|
||||||
|
print(f" Saved to {zip_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("run_id", help="GitHub Actions run ID")
|
||||||
|
parser.add_argument(
|
||||||
|
"--repo",
|
||||||
|
help="owner/repo (default: detected from git remote 'origin')",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--token",
|
||||||
|
help="GitHub token (default: $GITHUB_TOKEN, $GH_TOKEN, or `gh auth token`)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--out",
|
||||||
|
default="artifacts",
|
||||||
|
help="Output directory (default: ./artifacts)",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
repo = get_repo(args.repo)
|
||||||
|
token = get_token(args.token)
|
||||||
|
out_dir = Path(args.out)
|
||||||
|
|
||||||
|
print(f"Repo: {repo}")
|
||||||
|
print(f"Run ID: {args.run_id}")
|
||||||
|
print(f"Output: {out_dir.resolve()}")
|
||||||
|
|
||||||
|
download_artifacts(repo, args.run_id, token, out_dir)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import fnmatch
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
DEVICES_DIRECTORY = os.path.join(os.path.dirname(__file__), "..", "Devices")
|
||||||
|
|
||||||
|
IGNORE_LIST = {
|
||||||
|
"simulator",
|
||||||
|
"generic-*",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def is_ignored(device_id):
|
||||||
|
return any(fnmatch.fnmatch(device_id, pattern) for pattern in IGNORE_LIST)
|
||||||
|
|
||||||
|
def read_properties_file(path):
|
||||||
|
properties = {}
|
||||||
|
with open(path, "r") as file:
|
||||||
|
for line in file:
|
||||||
|
stripped = line.strip()
|
||||||
|
if not stripped or stripped.startswith("#"):
|
||||||
|
continue
|
||||||
|
key, sep, value = line.partition("=")
|
||||||
|
if not sep:
|
||||||
|
continue
|
||||||
|
properties[key.strip()] = value.strip()
|
||||||
|
return properties
|
||||||
|
|
||||||
|
def get_board_entries():
|
||||||
|
boards = []
|
||||||
|
for device_id in sorted(os.listdir(DEVICES_DIRECTORY)):
|
||||||
|
if is_ignored(device_id):
|
||||||
|
continue
|
||||||
|
device_dir = os.path.join(DEVICES_DIRECTORY, device_id)
|
||||||
|
properties_path = os.path.join(device_dir, "device.properties")
|
||||||
|
if not os.path.isdir(device_dir) or not os.path.isfile(properties_path):
|
||||||
|
continue
|
||||||
|
properties = read_properties_file(properties_path)
|
||||||
|
target = properties.get("hardware.target")
|
||||||
|
if not target:
|
||||||
|
sys.exit(f"ERROR: {properties_path} has no hardware.target property")
|
||||||
|
boards.append({"id": device_id, "arch": target.lower()})
|
||||||
|
return boards
|
||||||
|
|
||||||
|
def main():
|
||||||
|
matrix_json = json.dumps({"board": get_board_entries()})
|
||||||
|
|
||||||
|
github_output = os.environ.get("GITHUB_OUTPUT")
|
||||||
|
if github_output:
|
||||||
|
with open(github_output, "a") as file:
|
||||||
|
file.write(f"matrix={matrix_json}\n")
|
||||||
|
else:
|
||||||
|
print(matrix_json)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Executable
+126
@@ -0,0 +1,126 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Summarize commits between the last 2 pushed git tags into commits.md and pull-requests.md."""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
PR_REF_RE = re.compile(r"#(\d+)")
|
||||||
|
|
||||||
|
|
||||||
|
def get_repo(cli_repo: str | None) -> str:
|
||||||
|
if cli_repo:
|
||||||
|
return cli_repo
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["git", "remote", "get-url", "origin"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
url = result.stdout.strip()
|
||||||
|
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||||
|
sys.exit("Could not detect repo from git remote. Pass --repo owner/name.")
|
||||||
|
|
||||||
|
if url.startswith("git@"):
|
||||||
|
path = url.split(":", 1)[1]
|
||||||
|
else:
|
||||||
|
path = url.split("github.com/", 1)[-1]
|
||||||
|
return path.removesuffix(".git")
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_two_tags() -> tuple[str, str]:
|
||||||
|
result = subprocess.run(
|
||||||
|
["git", "tag", "--sort=-creatordate"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
tags = [t for t in result.stdout.splitlines() if t]
|
||||||
|
if len(tags) < 2:
|
||||||
|
sys.exit(f"Need at least 2 tags, found {len(tags)}.")
|
||||||
|
return tags[1], tags[0] # previous, latest
|
||||||
|
|
||||||
|
|
||||||
|
def get_commits(prev_tag: str, latest_tag: str) -> list[tuple[str, str]]:
|
||||||
|
result = subprocess.run(
|
||||||
|
[
|
||||||
|
"git",
|
||||||
|
"log",
|
||||||
|
"--pretty=format:%H\x1f%s",
|
||||||
|
f"{prev_tag}..{latest_tag}",
|
||||||
|
],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
commits = []
|
||||||
|
for line in result.stdout.splitlines():
|
||||||
|
if not line:
|
||||||
|
continue
|
||||||
|
sha, subject = line.split("\x1f", 1)
|
||||||
|
commits.append((sha, subject))
|
||||||
|
return commits
|
||||||
|
|
||||||
|
|
||||||
|
def write_commits_md(path: Path, repo: str, prev_tag: str, latest_tag: str, commits: list[tuple[str, str]]):
|
||||||
|
lines = [f"# Commits: {prev_tag}..{latest_tag}", ""]
|
||||||
|
for sha, subject in commits:
|
||||||
|
link = f"https://github.com/{repo}/commit/{sha}"
|
||||||
|
lines.append(f"- [{subject}]({link})")
|
||||||
|
path.write_text("\n".join(lines) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
def write_pull_requests_md(path: Path, repo: str, commits: list[tuple[str, str]]):
|
||||||
|
pr_numbers = []
|
||||||
|
seen = set()
|
||||||
|
for _, subject in commits:
|
||||||
|
for match in PR_REF_RE.finditer(subject):
|
||||||
|
number = match.group(1)
|
||||||
|
if number not in seen:
|
||||||
|
seen.add(number)
|
||||||
|
pr_numbers.append(number)
|
||||||
|
|
||||||
|
lines = ["# Pull Requests", ""]
|
||||||
|
for number in pr_numbers:
|
||||||
|
lines.append(f"- https://github.com/{repo}/pull/{number}")
|
||||||
|
path.write_text("\n".join(lines) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument(
|
||||||
|
"--repo",
|
||||||
|
help="owner/repo (default: detected from git remote 'origin')",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--out",
|
||||||
|
default=".",
|
||||||
|
help="Output directory for commits.md and pull-requests.md (default: current directory)",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
repo = get_repo(args.repo)
|
||||||
|
prev_tag, latest_tag = get_last_two_tags()
|
||||||
|
commits = get_commits(prev_tag, latest_tag)
|
||||||
|
|
||||||
|
out_dir = Path(args.out)
|
||||||
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
commits_path = out_dir / "release-commits.md"
|
||||||
|
prs_path = out_dir / "release-pull-requests.md"
|
||||||
|
|
||||||
|
write_commits_md(commits_path, repo, prev_tag, latest_tag, commits)
|
||||||
|
write_pull_requests_md(prs_path, repo, commits)
|
||||||
|
|
||||||
|
print(f"Repo: {repo}")
|
||||||
|
print(f"Tags: {prev_tag}..{latest_tag}")
|
||||||
|
print(f"Commits: {len(commits)}")
|
||||||
|
print(f"Wrote {commits_path}")
|
||||||
|
print(f"Wrote {prs_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,4 +1,11 @@
|
|||||||
function(GET_PROPERTY_VALUE PROPERTIES_CONTENT_VAR KEY_NAME RESULT_VAR)
|
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
|
# Search for the key and its value in the properties content
|
||||||
# Supports KEY=VALUE, KEY="VALUE", and optional spaces around =
|
# Supports KEY=VALUE, KEY="VALUE", and optional spaces around =
|
||||||
# Use parentheses to capture the value
|
# Use parentheses to capture the value
|
||||||
@@ -6,6 +13,8 @@ function(GET_PROPERTY_VALUE PROPERTIES_CONTENT_VAR KEY_NAME RESULT_VAR)
|
|||||||
# So we look for the key at the beginning of the string or after a newline.
|
# 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\"]*)\"?")
|
if ("${${PROPERTIES_CONTENT_VAR}}" MATCHES "(^|\n)${KEY_NAME}[ \t]*=[ \t]*\"?([^\n\"]*)\"?")
|
||||||
set(${RESULT_VAR} "${CMAKE_MATCH_2}" PARENT_SCOPE)
|
set(${RESULT_VAR} "${CMAKE_MATCH_2}" PARENT_SCOPE)
|
||||||
|
elseif (has_default)
|
||||||
|
set(${RESULT_VAR} "${default_value}" PARENT_SCOPE)
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Property '${KEY_NAME}' not found in the properties content.")
|
message(FATAL_ERROR "Property '${KEY_NAME}' not found in the properties content.")
|
||||||
endif ()
|
endif ()
|
||||||
@@ -28,7 +37,6 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
file(STRINGS ${PROPERTY_FILE_ABS} lines)
|
file(STRINGS ${PROPERTY_FILE_ABS} lines)
|
||||||
set(current_section "")
|
|
||||||
set(map_content "")
|
set(map_content "")
|
||||||
|
|
||||||
foreach(line IN LISTS lines)
|
foreach(line IN LISTS lines)
|
||||||
@@ -37,9 +45,7 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
|
|||||||
continue()
|
continue()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (line MATCHES "^\\[.*\\]$")
|
if (line MATCHES "^([^=]+)=(.*)$")
|
||||||
set(current_section "${line}")
|
|
||||||
elseif (line MATCHES "^([^=]+)=(.*)$")
|
|
||||||
set(key "${CMAKE_MATCH_1}")
|
set(key "${CMAKE_MATCH_1}")
|
||||||
set(value "${CMAKE_MATCH_2}")
|
set(value "${CMAKE_MATCH_2}")
|
||||||
string(STRIP "${key}" key)
|
string(STRIP "${key}" key)
|
||||||
@@ -49,7 +55,7 @@ function(READ_PROPERTIES_TO_MAP PROPERTY_FILE RESULT_VAR)
|
|||||||
set(value "${CMAKE_MATCH_1}")
|
set(value "${CMAKE_MATCH_1}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
list(APPEND map_content "${current_section}${key}" "${value}")
|
list(APPEND map_content "${key}" "${value}")
|
||||||
endif ()
|
endif ()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
|||||||
+60
-10
@@ -88,6 +88,17 @@ def write_module_cmakelists(path, content):
|
|||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
f.write(content)
|
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):
|
def add_driver(target_path, driver_name):
|
||||||
mappings = get_driver_mappings(driver_name)
|
mappings = get_driver_mappings(driver_name)
|
||||||
map_copy(mappings, target_path)
|
map_copy(mappings, target_path)
|
||||||
@@ -100,6 +111,44 @@ def add_module(target_path, module_name):
|
|||||||
cmakelists_content = create_module_cmakelists(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)
|
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():
|
def main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print("Usage: release-sdk.py [target_path]")
|
print("Usage: release-sdk.py [target_path]")
|
||||||
@@ -136,23 +185,24 @@ def main():
|
|||||||
# elf_loader
|
# elf_loader
|
||||||
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
|
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
|
||||||
{'src': 'Libraries/elf_loader/license.txt', '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)
|
map_copy(mappings, target_path)
|
||||||
|
|
||||||
# Modules
|
# Modules
|
||||||
add_module(target_path, "lvgl-module")
|
add_module(target_path, "lvgl-module")
|
||||||
|
add_module(target_path, "crypt-module")
|
||||||
|
|
||||||
# Drivers
|
# Drivers - only ones actually built for this target (chip-restricted drivers like
|
||||||
add_driver(target_path, "bm8563-module")
|
# sc2356-module won't have a .a outside ESP32-P4)
|
||||||
add_driver(target_path, "bmi270-module")
|
available_drivers = [d for d in discover_all_drivers() if driver_is_available(d)]
|
||||||
add_driver(target_path, "mpu6886-module")
|
for driver_name in available_drivers:
|
||||||
add_driver(target_path, "pi4ioe5v6408-module")
|
add_driver(target_path, driver_name)
|
||||||
add_driver(target_path, "qmi8658-module")
|
|
||||||
add_driver(target_path, "rx8130ce-module")
|
# Final scripts - generated (not copied verbatim) so COMPONENTS/INCLUDE_DIRS only list
|
||||||
|
# drivers actually available for this target
|
||||||
|
generate_tactility_sdk_cmake(target_path, available_drivers)
|
||||||
|
generate_tactility_sdk_top_cmakelists(target_path, available_drivers)
|
||||||
|
|
||||||
# Output ESP-IDF SDK version to file
|
# Output ESP-IDF SDK version to file
|
||||||
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
|
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
|
||||||
|
|||||||
Executable
+84
@@ -0,0 +1,84 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Generate a release summary markdown by combining gh-release-summary.py output with Claude."""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||||
|
|
||||||
|
SECTIONS = [
|
||||||
|
"New Devices",
|
||||||
|
"New Features",
|
||||||
|
"New Apps",
|
||||||
|
"Improvements & Fixes",
|
||||||
|
"Other Changes",
|
||||||
|
"TactilitySDK",
|
||||||
|
"Known Issues",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def run_gh_release_summary(out_dir: Path, repo: str | None):
|
||||||
|
cmd = [sys.executable, str(SCRIPT_DIR / "gh-release-summary.py"), "--out", str(out_dir)]
|
||||||
|
if repo:
|
||||||
|
cmd += ["--repo", repo]
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def build_prompt() -> str:
|
||||||
|
section_list = "\n".join(f"- {s}" for s in SECTIONS)
|
||||||
|
return (
|
||||||
|
"You are given a list of commits (with GitHub commit links) and a list of pull "
|
||||||
|
"request links from a software release. Write a release summary in Markdown, "
|
||||||
|
"organizing changes into these sections (omit a section if it has no relevant "
|
||||||
|
"changes):\n\n"
|
||||||
|
f"{section_list}\n\n"
|
||||||
|
"Use concise bullet points. Base every bullet strictly on the given commits and "
|
||||||
|
"pull requests, referencing the pull request link where applicable. Output only "
|
||||||
|
"the Markdown, no commentary before or after it."
|
||||||
|
"If a pull request or commit has multiple changes add them as separate entries."
|
||||||
|
"Ignore irrelevant changes: documentation, minor fixes, non-descript fixes, scripts, github workflows."
|
||||||
|
"For 'New Devices': only mention the device name, don't like pull request."
|
||||||
|
"For 'Improvements & Fixes': Avoid non-descript entries, write specifics."
|
||||||
|
"For 'TactilitySDK': Avoid generic changes, be specific. Mention API changes."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def run_claude(commits_md: str, prs_md: str) -> str:
|
||||||
|
prompt = build_prompt()
|
||||||
|
stdin_content = f"## Commits\n\n{commits_md}\n\n## Pull Requests\n\n{prs_md}"
|
||||||
|
result = subprocess.run(
|
||||||
|
["claude", "-p", prompt],
|
||||||
|
input=stdin_content,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
return result.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||||||
|
parser.add_argument("--repo", help="owner/repo (default: detected from git remote 'origin')")
|
||||||
|
parser.add_argument("--out", default=".", help="Output directory (default: current directory)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
out_dir = Path(args.out)
|
||||||
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
run_gh_release_summary(out_dir, args.repo)
|
||||||
|
|
||||||
|
commits_md = (out_dir / "release-commits.md").read_text()
|
||||||
|
prs_md = (out_dir / "release-pull-requests.md").read_text()
|
||||||
|
|
||||||
|
print("Generating release summary via claude...")
|
||||||
|
summary = run_claude(commits_md, prs_md)
|
||||||
|
|
||||||
|
summary_path = out_dir / "release-summary.md"
|
||||||
|
summary_path.write_text(summary)
|
||||||
|
print(f"Wrote {summary_path}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -9,7 +9,8 @@ CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
|
|||||||
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
|
CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y
|
||||||
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
|
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
|
||||||
# EmbedTLS
|
# EmbedTLS
|
||||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3=y
|
# Use TLS 1.2 because 1.3 conflicts with MbedTLS dynamic buffer
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
|
||||||
# LVGL
|
# LVGL
|
||||||
CONFIG_LV_USE_USER_DATA=y
|
CONFIG_LV_USE_USER_DATA=y
|
||||||
CONFIG_LV_USE_FS_STDIO=y
|
CONFIG_LV_USE_FS_STDIO=y
|
||||||
@@ -25,6 +26,9 @@ CONFIG_LV_USE_WIN=n
|
|||||||
CONFIG_LV_USE_SNAPSHOT=y
|
CONFIG_LV_USE_SNAPSHOT=y
|
||||||
CONFIG_LV_BUILD_EXAMPLES=n
|
CONFIG_LV_BUILD_EXAMPLES=n
|
||||||
CONFIG_LV_BUILD_DEMOS=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_HZ=1000
|
||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
@@ -40,3 +44,22 @@ CONFIG_WL_SECTOR_MODE_SAFE=y
|
|||||||
CONFIG_WL_SECTOR_MODE=1
|
CONFIG_WL_SECTOR_MODE=1
|
||||||
# Allow new i2c_master API (used by Tab5Keyboard for LP_I2C_NUM_0) to coexist with legacy i2c driver
|
# 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
|
CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK=y
|
||||||
|
# Allow new adc_oneshot API (esp32_adc_oneshot kernel driver, linked into every device via
|
||||||
|
# platform-esp32) to coexist with boards still reading battery voltage via the legacy ADC driver
|
||||||
|
# (e.g. m5stack-cardputer, m5stack-cardputer-adv, lilygo-thmi). Only one API is ever actually used
|
||||||
|
# per board at runtime, so this just bypasses ESP-IDF's link-time-only conflict abort.
|
||||||
|
CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK=y
|
||||||
|
# Wi-Fi memory optimizations
|
||||||
|
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=3
|
||||||
|
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=5
|
||||||
|
CONFIG_ESP_WIFI_STATIC_TX_BUFFER=y
|
||||||
|
CONFIG_ESP_WIFI_TX_BUFFER_TYPE=0
|
||||||
|
CONFIG_ESP_WIFI_STATIC_TX_BUFFER_NUM=5
|
||||||
|
CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=5
|
||||||
|
CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y
|
||||||
|
CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0
|
||||||
|
CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5
|
||||||
|
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
|
||||||
|
CONFIG_ESP_WIFI_TX_BA_WIN=5
|
||||||
|
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
|
||||||
|
CONFIG_ESP_WIFI_RX_BA_WIN=5
|
||||||
|
|||||||
+8
-2
@@ -43,7 +43,6 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
"TactilityKernel"
|
"TactilityKernel"
|
||||||
"Tactility"
|
"Tactility"
|
||||||
"TactilityC"
|
"TactilityC"
|
||||||
"TactilityCore"
|
|
||||||
"TactilityFreeRtos"
|
"TactilityFreeRtos"
|
||||||
"Libraries/elf_loader"
|
"Libraries/elf_loader"
|
||||||
"Libraries/lv_screenshot"
|
"Libraries/lv_screenshot"
|
||||||
@@ -70,10 +69,17 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
|
|
||||||
else ()
|
else ()
|
||||||
message("Building for sim target")
|
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_ID="simulator")
|
||||||
add_compile_definitions(CONFIG_TT_DEVICE_NAME="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_LAUNCHER_APP_ID="Launcher")
|
||||||
add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="")
|
add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="")
|
||||||
|
add_compile_definitions(CONFIG_TT_USER_DATA_LOCATION_INTERNAL)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
project(Tactility)
|
project(Tactility)
|
||||||
@@ -81,7 +87,6 @@ project(Tactility)
|
|||||||
# Defined as regular project for PC and component for ESP
|
# Defined as regular project for PC and component for ESP
|
||||||
if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
||||||
add_subdirectory(Tactility)
|
add_subdirectory(Tactility)
|
||||||
add_subdirectory(TactilityCore)
|
|
||||||
add_subdirectory(TactilityFreeRtos)
|
add_subdirectory(TactilityFreeRtos)
|
||||||
add_subdirectory(TactilityKernel)
|
add_subdirectory(TactilityKernel)
|
||||||
add_subdirectory(Platforms/platform-posix)
|
add_subdirectory(Platforms/platform-posix)
|
||||||
@@ -93,6 +98,7 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
add_subdirectory(Libraries/minmea)
|
add_subdirectory(Libraries/minmea)
|
||||||
add_subdirectory(Modules/hal-device-module)
|
add_subdirectory(Modules/hal-device-module)
|
||||||
add_subdirectory(Modules/lvgl-module)
|
add_subdirectory(Modules/lvgl-module)
|
||||||
|
add_subdirectory(Modules/crypt-module)
|
||||||
|
|
||||||
# FreeRTOS
|
# FreeRTOS
|
||||||
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
|
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
enableOnBoot=false
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
enableOnBoot=false
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
enableOnBoot=false
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
language=en-US
|
|
||||||
timeFormat24h=true
|
|
||||||
dateFormat=DD/MM/YYYY
|
|
||||||
region=EU
|
|
||||||
timezone=Europe/Amsterdam
|
|
||||||
@@ -485,7 +485,7 @@
|
|||||||
<button class="btn btn-secondary btn-sm" onclick="goUp()" id="upBtn">Up</button>
|
<button class="btn btn-secondary btn-sm" onclick="goUp()" id="upBtn">Up</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar-sep"></div>
|
<div class="toolbar-sep"></div>
|
||||||
<input type="text" id="pathInput" value="/data" onkeydown="if(event.key==='Enter')refreshFiles()">
|
<input type="text" id="pathInput" value="" onkeydown="if(event.key==='Enter')refreshFiles()">
|
||||||
<button class="btn btn-primary btn-sm" onclick="refreshFiles()">Go</button>
|
<button class="btn btn-primary btn-sm" onclick="refreshFiles()">Go</button>
|
||||||
<div class="toolbar-sep"></div>
|
<div class="toolbar-sep"></div>
|
||||||
<div class="toolbar-group">
|
<div class="toolbar-group">
|
||||||
@@ -739,7 +739,6 @@ function renderDashboard(data) {
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<h2>Quick Actions</h2>
|
<h2>Quick Actions</h2>
|
||||||
<div class="actions">
|
<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>' : ''}
|
${data.features_enabled?.screenshot ? '<button class="btn btn-secondary" onclick="captureScreenshot(this)">Screenshot</button>' : ''}
|
||||||
<button class="btn btn-danger" onclick="rebootDevice(this)">Reboot</button>
|
<button class="btn btn-danger" onclick="rebootDevice(this)">Reboot</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Tactility Dashboard</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 20px auto;
|
|
||||||
padding: 20px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: #333;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.placeholder {
|
|
||||||
background: white;
|
|
||||||
padding: 40px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
||||||
text-align: center;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.placeholder h2 {
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
.placeholder p {
|
|
||||||
color: #666;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #007bff;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Tactility Default Dashboard</h1>
|
|
||||||
|
|
||||||
<div class="placeholder">
|
|
||||||
<h2>Version 0 - Default Placeholder</h2>
|
|
||||||
<p>This is the default dashboard bundled with firmware.</p>
|
|
||||||
<p>To customize this interface:</p>
|
|
||||||
<ol style="text-align: left; display: inline-block;">
|
|
||||||
<li>Create your custom dashboard HTML/CSS/JS files</li>
|
|
||||||
<li>Add them to <code>/sdcard/tactility/webserver/</code></li>
|
|
||||||
<li>Create <code>version.json</code> with <code>{"version": 1}</code> or higher</li>
|
|
||||||
<li>Reboot or click "Sync Assets" on the <a href="/">Core Interface</a></li>
|
|
||||||
</ol>
|
|
||||||
<p><strong>Your custom assets will automatically replace this page!</strong></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="placeholder">
|
|
||||||
<p><a href="/">← Back to Core Interface</a></p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 0
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
INCLUDE_DIRS "source"
|
||||||
REQUIRES Tactility esp_lvgl_port esp_lcd RgbDisplay GT911 PwmBacklight driver vfs fatfs
|
REQUIRES Tactility
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
#include <PwmBacklight.h>
|
|
||||||
#include "devices/Display.h"
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
#include <freertos/task.h>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
//Display Reset
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_46, GPIO_MODE_OUTPUT));
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_46, 0));
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_46, 1));
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
|
|
||||||
return driver::pwmbacklight::init(GPIO_NUM_21);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
|
|
||||||
#include <Gt911Touch.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
#include <RgbDisplay.h>
|
|
||||||
#include <tactility/check.h>
|
|
||||||
#include <tactility/device.h>
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
|
||||||
// Note for future changes: Reset pin is 41 and interrupt pin is 40
|
|
||||||
auto* i2c = device_find_by_name("i2c0");
|
|
||||||
check(i2c);
|
|
||||||
auto configuration = std::make_unique<Gt911Touch::Configuration>(
|
|
||||||
i2c,
|
|
||||||
800,
|
|
||||||
480
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<Gt911Touch>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
auto touch = createTouch();
|
|
||||||
|
|
||||||
constexpr uint32_t bufferPixels = 800 * 10;
|
|
||||||
|
|
||||||
esp_lcd_rgb_panel_config_t rgb_panel_config = {
|
|
||||||
.clk_src = LCD_CLK_SRC_DEFAULT,
|
|
||||||
.timings = {
|
|
||||||
.pclk_hz = 14000000,
|
|
||||||
.h_res = 800,
|
|
||||||
.v_res = 480,
|
|
||||||
.hsync_pulse_width = 4,
|
|
||||||
.hsync_back_porch = 8,
|
|
||||||
.hsync_front_porch = 8,
|
|
||||||
.vsync_pulse_width = 4,
|
|
||||||
.vsync_back_porch = 16,
|
|
||||||
.vsync_front_porch = 16,
|
|
||||||
.flags = {
|
|
||||||
.hsync_idle_low = false,
|
|
||||||
.vsync_idle_low = false,
|
|
||||||
.de_idle_high = false,
|
|
||||||
.pclk_active_neg = true,
|
|
||||||
.pclk_idle_high = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.data_width = 16,
|
|
||||||
.bits_per_pixel = 0,
|
|
||||||
.num_fbs = 2,
|
|
||||||
.bounce_buffer_size_px = bufferPixels,
|
|
||||||
.sram_trans_align = 8,
|
|
||||||
.psram_trans_align = 64,
|
|
||||||
.hsync_gpio_num = GPIO_NUM_NC,
|
|
||||||
.vsync_gpio_num = GPIO_NUM_NC,
|
|
||||||
.de_gpio_num = GPIO_NUM_38,
|
|
||||||
.pclk_gpio_num = GPIO_NUM_5,
|
|
||||||
.disp_gpio_num = GPIO_NUM_NC,
|
|
||||||
.data_gpio_nums = {
|
|
||||||
GPIO_NUM_17, // B
|
|
||||||
GPIO_NUM_18, // B
|
|
||||||
GPIO_NUM_48, // B
|
|
||||||
GPIO_NUM_47, // B
|
|
||||||
GPIO_NUM_39, // B
|
|
||||||
GPIO_NUM_11, // G
|
|
||||||
GPIO_NUM_12, // G
|
|
||||||
GPIO_NUM_13, // G
|
|
||||||
GPIO_NUM_14, // G
|
|
||||||
GPIO_NUM_15, // G
|
|
||||||
GPIO_NUM_16, // G
|
|
||||||
GPIO_NUM_6, // R
|
|
||||||
GPIO_NUM_7, // R
|
|
||||||
GPIO_NUM_8, // R
|
|
||||||
GPIO_NUM_9, // R
|
|
||||||
GPIO_NUM_10, // R
|
|
||||||
},
|
|
||||||
.flags = {
|
|
||||||
.disp_active_low = false,
|
|
||||||
.refresh_on_demand = false,
|
|
||||||
.fb_in_psram = true,
|
|
||||||
.double_fb = true,
|
|
||||||
.no_fb = false,
|
|
||||||
.bb_invalidate_cache = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
RgbDisplay::BufferConfiguration buffer_config = {
|
|
||||||
.size = (800 * 480),
|
|
||||||
.useSpi = true,
|
|
||||||
.doubleBuffer = true,
|
|
||||||
.bounceBufferMode = true,
|
|
||||||
.avoidTearing = false
|
|
||||||
};
|
|
||||||
|
|
||||||
auto configuration = std::make_unique<RgbDisplay::Configuration>(
|
|
||||||
rgb_panel_config,
|
|
||||||
buffer_config,
|
|
||||||
touch,
|
|
||||||
LV_COLOR_FORMAT_RGB565,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
driver::pwmbacklight::setBacklightDuty
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<RgbDisplay>(std::move(configuration));
|
|
||||||
}
|
|
||||||
@@ -2,17 +2,28 @@
|
|||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
#include <tactility/bindings/esp32_ble.h>
|
#include <tactility/bindings/esp32_ble.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_usbhost.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
|
// Reference: https://github.com/bigtreetech/PandaTouch_PlatformIO/blob/master/docs/PINOUT.md
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "BigTreeTech Panda Touch";
|
model = "BigTreeTech Panda Touch";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
ble0 {
|
ble0 {
|
||||||
compatible = "espressif,esp32-ble";
|
compatible = "espressif,esp32-ble";
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
@@ -26,6 +37,15 @@
|
|||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
pin-sda = <&gpio0 2 GPIO_FLAG_NONE>;
|
pin-sda = <&gpio0 2 GPIO_FLAG_NONE>;
|
||||||
pin-scl = <&gpio0 1 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 {
|
i2c_external: i2c1 {
|
||||||
@@ -36,6 +56,57 @@
|
|||||||
pin-scl = <&gpio0 3 GPIO_FLAG_NONE>;
|
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 {
|
usbhost0 {
|
||||||
compatible = "espressif,esp32-usbhost";
|
compatible = "espressif,esp32-usbhost";
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
[general]
|
general.vendor=BigTreeTech
|
||||||
vendor=BigTreeTech
|
general.name=Panda Touch,K Touch
|
||||||
name=Panda Touch,K Touch
|
|
||||||
|
|
||||||
[apps]
|
apps.launcherAppId=Launcher
|
||||||
launcherAppId=Launcher
|
|
||||||
|
|
||||||
[hardware]
|
hardware.target=ESP32S3
|
||||||
target=ESP32S3
|
hardware.flashSize=16MB
|
||||||
flashSize=16MB
|
hardware.spiRam=true
|
||||||
spiRam=true
|
hardware.spiRamMode=OCT
|
||||||
spiRamMode=OCT
|
hardware.spiRamSpeed=120M
|
||||||
spiRamSpeed=120M
|
hardware.esptoolFlashFreq=120M
|
||||||
esptoolFlashFreq=120M
|
hardware.bluetooth=true
|
||||||
bluetooth=true
|
hardware.usbHostEnabled=true
|
||||||
usbHostEnabled=true
|
|
||||||
|
|
||||||
[display]
|
dependencies.useDeprecatedHal=false
|
||||||
size=5"
|
|
||||||
shape=rectangle
|
|
||||||
dpi=187
|
|
||||||
|
|
||||||
[lvgl]
|
storage.userDataLocation=Internal
|
||||||
colorDepth=16
|
|
||||||
fontSize=18
|
display.size=5"
|
||||||
|
display.shape=rectangle
|
||||||
|
display.dpi=187
|
||||||
|
|
||||||
|
lvgl.colorDepth=16
|
||||||
|
lvgl.fontSize=18
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/rgb-display-module
|
||||||
|
- Drivers/gt911-module
|
||||||
dts: bigtreetech,panda-touch.dts
|
dts: bigtreetech,panda-touch.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel
|
||||||
REQUIRES Tactility esp_lvgl_port ILI934x CST816S PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
#include "devices/Display.h"
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
// Set the RGB LED Pins to output and turn them off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
|
|
||||||
|
|
||||||
// 0 on, 1 off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
|
|
||||||
|
|
||||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static tt::hal::DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
#include "Cst816Touch.h"
|
|
||||||
|
|
||||||
#include <Ili934xDisplay.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
|
||||||
// Note: GPIO 25 for reset and GPIO 21 for interrupt?
|
|
||||||
auto configuration = std::make_unique<Cst816sTouch::Configuration>(
|
|
||||||
I2C_NUM_0,
|
|
||||||
240,
|
|
||||||
320
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<Cst816sTouch>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
Ili934xDisplay::Configuration panel_configuration = {
|
|
||||||
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
|
||||||
.gapX = 0,
|
|
||||||
.gapY = 0,
|
|
||||||
.swapXY = false,
|
|
||||||
.mirrorX = true,
|
|
||||||
.mirrorY = false,
|
|
||||||
.invertColor = false,
|
|
||||||
.swapBytes = true,
|
|
||||||
.bufferSize = LCD_BUFFER_SIZE,
|
|
||||||
.touch = createTouch(),
|
|
||||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
|
||||||
.resetPin = GPIO_NUM_NC,
|
|
||||||
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR
|
|
||||||
};
|
|
||||||
|
|
||||||
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
|
|
||||||
.spiHostDevice = LCD_SPI_HOST,
|
|
||||||
.csPin = LCD_PIN_CS,
|
|
||||||
.dcPin = LCD_PIN_DC,
|
|
||||||
.pixelClockFrequency = 40'000'000,
|
|
||||||
.transactionQueueDepth = 10
|
|
||||||
});
|
|
||||||
|
|
||||||
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Display
|
|
||||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
|
|
||||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
|
||||||
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
|
|
||||||
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
|
|
||||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
|
|
||||||
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
|
|
||||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
|
||||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,26 @@
|
|||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
#include <tactility/bindings/esp32_sdspi.h>
|
#include <tactility/bindings/esp32_sdspi.h>
|
||||||
#include <tactility/bindings/display_placeholder.h>
|
#include <tactility/bindings/esp32_pwm_ledc.h>
|
||||||
|
#include <tactility/bindings/pwm_backlight.h>
|
||||||
|
#include <tactility/bindings/rgb_led_pwm.h>
|
||||||
|
#include <bindings/ili9341.h>
|
||||||
|
#include <bindings/cst816s.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "CYD 2432S024C";
|
model = "CYD 2432S024C";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
compatible = "espressif,esp32-gpio";
|
compatible = "espressif,esp32-gpio";
|
||||||
gpio-count = <40>;
|
gpio-count = <40>;
|
||||||
@@ -22,6 +32,66 @@
|
|||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
|
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
|
||||||
pin-scl = <&gpio0 32 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 {
|
spi0 {
|
||||||
@@ -30,9 +100,16 @@
|
|||||||
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
||||||
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
display {
|
display@0 {
|
||||||
compatible = "display-placeholder";
|
compatible = "ilitek,ili9341";
|
||||||
|
horizontal-resolution = <240>;
|
||||||
|
vertical-resolution = <320>;
|
||||||
|
mirror-x;
|
||||||
|
bgr-order;
|
||||||
|
pixel-clock-hz = <40000000>;
|
||||||
|
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
|
||||||
|
backlight = <&display_backlight>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,7 +120,8 @@
|
|||||||
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
|
||||||
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
|
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
|
||||||
|
miso-pull-up;
|
||||||
|
|
||||||
sdcard@0 {
|
sdcard@0 {
|
||||||
compatible = "espressif,esp32-sdspi";
|
compatible = "espressif,esp32-sdspi";
|
||||||
frequency-khz = <20000>;
|
frequency-khz = <20000>;
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
[general]
|
general.vendor=CYD
|
||||||
vendor=CYD
|
general.name=2432S024C
|
||||||
name=2432S024C
|
|
||||||
|
|
||||||
[apps]
|
apps.launcherAppId=Launcher
|
||||||
launcherAppId=Launcher
|
|
||||||
|
|
||||||
[hardware]
|
hardware.target=ESP32
|
||||||
target=ESP32
|
hardware.flashSize=4MB
|
||||||
flashSize=4MB
|
hardware.spiRam=false
|
||||||
spiRam=false
|
|
||||||
|
|
||||||
[display]
|
dependencies.useDeprecatedHal=false
|
||||||
size=2.4"
|
|
||||||
shape=rectangle
|
|
||||||
dpi=167
|
|
||||||
|
|
||||||
[lvgl]
|
storage.userDataLocation=SD
|
||||||
colorDepth=16
|
|
||||||
|
display.size=2.4"
|
||||||
|
display.shape=rectangle
|
||||||
|
display.dpi=167
|
||||||
|
|
||||||
|
lvgl.colorDepth=16
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/ili9341-module
|
||||||
|
- Drivers/cst816s-module
|
||||||
dts: cyd,2432s024c.dts
|
dts: cyd,2432s024c.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel
|
||||||
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046 PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#include "devices/Display.h"
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
#include "Xpt2046Touch.h"
|
|
||||||
#include <Ili934xDisplay.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch(esp_lcd_spi_bus_handle_t spiDevice) {
|
|
||||||
auto configuration = std::make_unique<Xpt2046Touch::Configuration>(
|
|
||||||
spiDevice,
|
|
||||||
TOUCH_CS_PIN,
|
|
||||||
LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
LCD_VERTICAL_RESOLUTION,
|
|
||||||
true, // swapXY
|
|
||||||
false, // mirrorX
|
|
||||||
true // mirrorY
|
|
||||||
);
|
|
||||||
return std::make_shared<Xpt2046Touch>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
|
|
||||||
.spiHostDevice = LCD_SPI_HOST,
|
|
||||||
.csPin = LCD_PIN_CS,
|
|
||||||
.dcPin = LCD_PIN_DC,
|
|
||||||
.pixelClockFrequency = 40'000'000,
|
|
||||||
.transactionQueueDepth = 10
|
|
||||||
});
|
|
||||||
|
|
||||||
Ili934xDisplay::Configuration panel_configuration = {
|
|
||||||
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
|
||||||
.gapX = 0,
|
|
||||||
.gapY = 0,
|
|
||||||
.swapXY = true,
|
|
||||||
.mirrorX = true,
|
|
||||||
.mirrorY = true,
|
|
||||||
.invertColor = false,
|
|
||||||
.swapBytes = true,
|
|
||||||
.bufferSize = LCD_BUFFER_SIZE,
|
|
||||||
.touch = createTouch(spi_configuration->spiHostDevice),
|
|
||||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
|
||||||
.resetPin = LCD_PIN_RST,
|
|
||||||
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB
|
|
||||||
};
|
|
||||||
|
|
||||||
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Display
|
|
||||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
|
||||||
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
|
|
||||||
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
|
|
||||||
constexpr auto LCD_PIN_RST = GPIO_NUM_NC; // tied to ESP32 RST
|
|
||||||
constexpr auto LCD_PIN_CLK = GPIO_NUM_14;
|
|
||||||
constexpr auto LCD_PIN_MOSI = GPIO_NUM_13;
|
|
||||||
constexpr auto LCD_PIN_MISO = GPIO_NUM_12;
|
|
||||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
|
|
||||||
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
|
|
||||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
|
||||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
|
||||||
|
|
||||||
// Backlight
|
|
||||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
|
|
||||||
|
|
||||||
// Touch
|
|
||||||
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
|
|
||||||
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +1,84 @@
|
|||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
#include <tactility/bindings/esp32_sdspi.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_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";
|
compatible = "root";
|
||||||
model = "CYD 2432S024R";
|
model = "CYD 2432S024R";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
compatible = "espressif,esp32-gpio";
|
compatible = "espressif,esp32-gpio";
|
||||||
gpio-count = <40>;
|
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 {
|
spi0 {
|
||||||
compatible = "espressif,esp32-spi";
|
compatible = "espressif,esp32-spi";
|
||||||
host = <SPI2_HOST>;
|
host = <SPI2_HOST>;
|
||||||
@@ -27,11 +89,23 @@
|
|||||||
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
|
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
|
||||||
|
|
||||||
display@0 {
|
display@0 {
|
||||||
compatible = "display-placeholder";
|
compatible = "ilitek,ili9341";
|
||||||
|
horizontal-resolution = <240>;
|
||||||
|
vertical-resolution = <320>;
|
||||||
|
swap-xy;
|
||||||
|
mirror-x;
|
||||||
|
mirror-y;
|
||||||
|
pixel-clock-hz = <40000000>;
|
||||||
|
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
|
||||||
|
backlight = <&display_backlight>;
|
||||||
};
|
};
|
||||||
|
|
||||||
touch@1 {
|
touch@1 {
|
||||||
compatible = "touch-placeholder";
|
compatible = "xptek,xpt2046";
|
||||||
|
x-max = <240>;
|
||||||
|
y-max = <320>;
|
||||||
|
swap-xy;
|
||||||
|
mirror-y;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,4 +129,4 @@
|
|||||||
pin-tx = <&gpio0 1 GPIO_FLAG_NONE>;
|
pin-tx = <&gpio0 1 GPIO_FLAG_NONE>;
|
||||||
pin-rx = <&gpio0 3 GPIO_FLAG_NONE>;
|
pin-rx = <&gpio0 3 GPIO_FLAG_NONE>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
[general]
|
general.vendor=CYD
|
||||||
vendor=CYD
|
general.name=2432S024R
|
||||||
name=2432S024R
|
|
||||||
|
|
||||||
[apps]
|
apps.launcherAppId=Launcher
|
||||||
launcherAppId=Launcher
|
|
||||||
|
|
||||||
[hardware]
|
hardware.target=ESP32
|
||||||
target=ESP32
|
hardware.flashSize=4MB
|
||||||
flashSize=4MB
|
hardware.spiRam=false
|
||||||
spiRam=false
|
|
||||||
|
|
||||||
[display]
|
dependencies.useDeprecatedHal=false
|
||||||
size=2.4"
|
|
||||||
shape=rectangle
|
|
||||||
dpi=167
|
|
||||||
|
|
||||||
[lvgl]
|
storage.userDataLocation=SD
|
||||||
colorDepth=16
|
|
||||||
|
display.size=2.4"
|
||||||
|
display.shape=rectangle
|
||||||
|
display.dpi=167
|
||||||
|
|
||||||
|
lvgl.colorDepth=16
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/ili9341-module
|
||||||
|
- Drivers/xpt2046-module
|
||||||
dts: cyd,2432s024r.dts
|
dts: cyd,2432s024r.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel
|
||||||
REQUIRES Tactility esp_lvgl_port ILI934x XPT2046SoftSPI PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
#include "devices/Display.h"
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
// Set the RGB LED Pins to output and turn them off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
|
|
||||||
|
|
||||||
// 0 on, 1 off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
|
|
||||||
|
|
||||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
#include "Xpt2046SoftSpi.h"
|
|
||||||
#include <Ili934xDisplay.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
|
||||||
auto configuration = std::make_unique<Xpt2046SoftSpi::Configuration>(
|
|
||||||
TOUCH_MOSI_PIN,
|
|
||||||
TOUCH_MISO_PIN,
|
|
||||||
TOUCH_SCK_PIN,
|
|
||||||
TOUCH_CS_PIN,
|
|
||||||
LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
LCD_VERTICAL_RESOLUTION,
|
|
||||||
false, // swapXY
|
|
||||||
true, // mirrorX
|
|
||||||
false // mirrorY
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<Xpt2046SoftSpi>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
Ili934xDisplay::Configuration panel_configuration = {
|
|
||||||
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
|
||||||
.gapX = 0,
|
|
||||||
.gapY = 0,
|
|
||||||
.swapXY = false,
|
|
||||||
.mirrorX = true,
|
|
||||||
.mirrorY = false,
|
|
||||||
.invertColor = false,
|
|
||||||
.swapBytes = true,
|
|
||||||
.bufferSize = LCD_BUFFER_SIZE,
|
|
||||||
.touch = createTouch(),
|
|
||||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
|
||||||
.resetPin = GPIO_NUM_NC,
|
|
||||||
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR
|
|
||||||
};
|
|
||||||
|
|
||||||
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
|
|
||||||
.spiHostDevice = LCD_SPI_HOST,
|
|
||||||
.csPin = LCD_PIN_CS,
|
|
||||||
.dcPin = LCD_PIN_DC,
|
|
||||||
.pixelClockFrequency = 40'000'000,
|
|
||||||
.transactionQueueDepth = 10
|
|
||||||
});
|
|
||||||
|
|
||||||
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Display
|
|
||||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
|
||||||
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
|
|
||||||
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
|
|
||||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
|
|
||||||
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
|
|
||||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
|
||||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
|
||||||
|
|
||||||
// Display backlight (PWM)
|
|
||||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_21;
|
|
||||||
|
|
||||||
// Touch (Software SPI)
|
|
||||||
constexpr auto TOUCH_MISO_PIN = GPIO_NUM_39;
|
|
||||||
constexpr auto TOUCH_MOSI_PIN = GPIO_NUM_32;
|
|
||||||
constexpr auto TOUCH_SCK_PIN = GPIO_NUM_25;
|
|
||||||
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
|
|
||||||
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,27 @@
|
|||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
#include <tactility/bindings/esp32_uart.h>
|
#include <tactility/bindings/esp32_uart.h>
|
||||||
#include <tactility/bindings/esp32_sdspi.h>
|
#include <tactility/bindings/esp32_sdspi.h>
|
||||||
#include <tactility/bindings/display_placeholder.h>
|
#include <tactility/bindings/esp32_pwm_ledc.h>
|
||||||
#include <tactility/bindings/touch_placeholder.h>
|
#include <tactility/bindings/pwm_backlight.h>
|
||||||
|
#include <tactility/bindings/rgb_led_pwm.h>
|
||||||
|
#include <bindings/ili9341.h>
|
||||||
|
#include <bindings/xpt2046_softspi.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "CYD 2432S028R";
|
model = "CYD 2432S028R";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
compatible = "espressif,esp32-gpio";
|
compatible = "espressif,esp32-gpio";
|
||||||
gpio-count = <40>;
|
gpio-count = <40>;
|
||||||
@@ -26,21 +35,87 @@
|
|||||||
pin-scl = <&gpio0 22 GPIO_FLAG_NONE>;
|
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 {
|
spi0 {
|
||||||
compatible = "espressif,esp32-spi";
|
compatible = "espressif,esp32-spi";
|
||||||
host = <SPI2_HOST>;
|
host = <SPI2_HOST>;
|
||||||
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>, // Display
|
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
||||||
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
|
|
||||||
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
||||||
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
|
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
display@0 {
|
|
||||||
compatible = "display-placeholder";
|
|
||||||
};
|
|
||||||
|
|
||||||
touch@1 {
|
display@0 {
|
||||||
compatible = "touch-placeholder";
|
compatible = "ilitek,ili9341";
|
||||||
|
horizontal-resolution = <240>;
|
||||||
|
vertical-resolution = <320>;
|
||||||
|
mirror-x;
|
||||||
|
bgr-order;
|
||||||
|
pixel-clock-hz = <40000000>;
|
||||||
|
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
|
||||||
|
backlight = <&display_backlight>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
[general]
|
general.vendor=CYD
|
||||||
vendor=CYD
|
general.name=2432S028R
|
||||||
name=2432S028R
|
|
||||||
|
|
||||||
[apps]
|
apps.launcherAppId=Launcher
|
||||||
launcherAppId=Launcher
|
|
||||||
|
|
||||||
[hardware]
|
hardware.target=ESP32
|
||||||
target=ESP32
|
hardware.flashSize=4MB
|
||||||
flashSize=4MB
|
hardware.spiRam=false
|
||||||
spiRam=false
|
|
||||||
|
|
||||||
[display]
|
dependencies.useDeprecatedHal=false
|
||||||
size=2.8"
|
|
||||||
shape=rectangle
|
|
||||||
dpi=143
|
|
||||||
|
|
||||||
[cdn]
|
storage.userDataLocation=SD
|
||||||
warningMessage=There are 3 hardware variants of this board. This build works on the original variant only ("v1").
|
|
||||||
|
|
||||||
[lvgl]
|
display.size=2.8"
|
||||||
colorDepth=16
|
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
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/ili9341-module
|
||||||
|
- Drivers/xpt2046-softspi-module
|
||||||
dts: cyd,2432s028r.dts
|
dts: cyd,2432s028r.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel
|
||||||
REQUIRES Tactility esp_lvgl_port ST7789 XPT2046SoftSPI PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
#include "devices/Display.h"
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
// Set the RGB LED Pins to output and turn them off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
|
|
||||||
|
|
||||||
// 0 on, 1 off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
|
|
||||||
|
|
||||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
#include "Xpt2046SoftSpi.h"
|
|
||||||
#include <St7789Display.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
constexpr auto* TAG = "CYD";
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
|
||||||
auto configuration = std::make_unique<Xpt2046SoftSpi::Configuration>(
|
|
||||||
TOUCH_MOSI_PIN,
|
|
||||||
TOUCH_MISO_PIN,
|
|
||||||
TOUCH_SCK_PIN,
|
|
||||||
TOUCH_CS_PIN,
|
|
||||||
LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
LCD_VERTICAL_RESOLUTION,
|
|
||||||
false, // swapXY
|
|
||||||
true, // mirrorX
|
|
||||||
false // mirrorY
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<Xpt2046SoftSpi>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
St7789Display::Configuration panel_configuration = {
|
|
||||||
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
|
||||||
.gapX = 0,
|
|
||||||
.gapY = 0,
|
|
||||||
.swapXY = false,
|
|
||||||
.mirrorX = false,
|
|
||||||
.mirrorY = false,
|
|
||||||
.invertColor = false,
|
|
||||||
.bufferSize = LCD_BUFFER_SIZE,
|
|
||||||
.touch = createTouch(),
|
|
||||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
|
||||||
.resetPin = GPIO_NUM_NC,
|
|
||||||
.lvglSwapBytes = false
|
|
||||||
};
|
|
||||||
|
|
||||||
auto spi_configuration = std::make_shared<St7789Display::SpiConfiguration>(St7789Display::SpiConfiguration {
|
|
||||||
.spiHostDevice = LCD_SPI_HOST,
|
|
||||||
.csPin = LCD_PIN_CS,
|
|
||||||
.dcPin = LCD_PIN_DC,
|
|
||||||
.pixelClockFrequency = 62'500'000,
|
|
||||||
.transactionQueueDepth = 10
|
|
||||||
});
|
|
||||||
|
|
||||||
return std::make_shared<St7789Display>(panel_configuration, spi_configuration);
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Display
|
|
||||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
|
||||||
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
|
|
||||||
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
|
|
||||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_21;
|
|
||||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
|
|
||||||
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
|
|
||||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
|
||||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
|
||||||
|
|
||||||
// Touch (Software SPI)
|
|
||||||
constexpr auto TOUCH_MISO_PIN = GPIO_NUM_39;
|
|
||||||
constexpr auto TOUCH_MOSI_PIN = GPIO_NUM_32;
|
|
||||||
constexpr auto TOUCH_SCK_PIN = GPIO_NUM_25;
|
|
||||||
constexpr auto TOUCH_CS_PIN = GPIO_NUM_33;
|
|
||||||
constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_36;
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,27 @@
|
|||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_uart.h>
|
#include <tactility/bindings/esp32_uart.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
#include <tactility/bindings/esp32_sdspi.h>
|
#include <tactility/bindings/esp32_sdspi.h>
|
||||||
#include <tactility/bindings/display_placeholder.h>
|
#include <tactility/bindings/esp32_pwm_ledc.h>
|
||||||
#include <tactility/bindings/touch_placeholder.h>
|
#include <tactility/bindings/pwm_backlight.h>
|
||||||
|
#include <tactility/bindings/rgb_led_pwm.h>
|
||||||
|
#include <bindings/st7789.h>
|
||||||
|
#include <bindings/xpt2046_softspi.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "CYD 2432S028R v3";
|
model = "CYD 2432S028R v3";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
compatible = "espressif,esp32-gpio";
|
compatible = "espressif,esp32-gpio";
|
||||||
gpio-count = <40>;
|
gpio-count = <40>;
|
||||||
@@ -26,21 +35,85 @@
|
|||||||
pin-scl = <&gpio0 22 GPIO_FLAG_NONE>;
|
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 {
|
spi0 {
|
||||||
compatible = "espressif,esp32-spi";
|
compatible = "espressif,esp32-spi";
|
||||||
host = <SPI2_HOST>;
|
host = <SPI2_HOST>;
|
||||||
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>, // Display
|
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
||||||
<&gpio0 33 GPIO_FLAG_NONE>; // Touch
|
|
||||||
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
||||||
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
|
pin-miso = <&gpio0 12 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
display@0 {
|
|
||||||
compatible = "display-placeholder";
|
|
||||||
};
|
|
||||||
|
|
||||||
touch@1 {
|
display@0 {
|
||||||
compatible = "touch-placeholder";
|
compatible = "sitronix,st7789";
|
||||||
|
horizontal-resolution = <240>;
|
||||||
|
vertical-resolution = <320>;
|
||||||
|
pixel-clock-hz = <62500000>;
|
||||||
|
pin-dc = <&gpio0 2 GPIO_FLAG_NONE>;
|
||||||
|
backlight = <&display_backlight>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,7 +124,7 @@
|
|||||||
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
|
||||||
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
|
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
sdcard@0 {
|
sdcard@0 {
|
||||||
compatible = "espressif,esp32-sdspi";
|
compatible = "espressif,esp32-sdspi";
|
||||||
frequency-khz = <20000>;
|
frequency-khz = <20000>;
|
||||||
|
|||||||
@@ -1,22 +1,23 @@
|
|||||||
[general]
|
general.vendor=CYD
|
||||||
vendor=CYD
|
general.name=2432S028R v3
|
||||||
name=2432S028R v3
|
|
||||||
|
|
||||||
[apps]
|
apps.launcherAppId=Launcher
|
||||||
launcherAppId=Launcher
|
|
||||||
|
|
||||||
[hardware]
|
hardware.target=ESP32
|
||||||
target=ESP32
|
hardware.flashSize=4MB
|
||||||
flashSize=4MB
|
hardware.spiRam=false
|
||||||
spiRam=false
|
|
||||||
|
|
||||||
[display]
|
dependencies.useDeprecatedHal=false
|
||||||
size=2.8"
|
|
||||||
shape=rectangle
|
|
||||||
dpi=143
|
|
||||||
|
|
||||||
[cdn]
|
storage.userDataLocation=SD
|
||||||
warningMessage=There are 3 hardware variants of this board. This build only supports board version 3.
|
|
||||||
|
|
||||||
[lvgl]
|
display.size=2.8"
|
||||||
colorDepth=16
|
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
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/st7789-module
|
||||||
|
- Drivers/xpt2046-softspi-module
|
||||||
dts: cyd,2432s028rv3.dts
|
dts: cyd,2432s028rv3.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel
|
||||||
REQUIRES Tactility esp_lvgl_port ILI934x GT911 PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
#include "devices/Display.h"
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <Tactility/kernel/SystemEvents.h>
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
|
||||||
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
if (!driver::pwmbacklight::init(LCD_PIN_BACKLIGHT)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the RGB LED Pins to output and turn them off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); // Blue
|
|
||||||
|
|
||||||
// 0 on, 1 off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); // Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); // Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); // Blue
|
|
||||||
|
|
||||||
// This display has a weird glitch with gamma during boot, which results in uneven dark gray colours.
|
|
||||||
// Setting gamma curve index to 0 doesn't work at boot for an unknown reason, so we set the curve index to 1:
|
|
||||||
tt::kernel::subscribeSystemEvent(tt::kernel::SystemEvent::BootSplash, [](auto) {
|
|
||||||
auto display = tt::hal::findFirstDevice<tt::hal::display::DisplayDevice>(tt::hal::Device::Type::Display);
|
|
||||||
assert(display != nullptr);
|
|
||||||
tt::lvgl::lock(portMAX_DELAY);
|
|
||||||
display->setGammaCurve(1U);
|
|
||||||
tt::lvgl::unlock();
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static tt::hal::DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const tt::hal::Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
|
|
||||||
#include <Gt911Touch.h>
|
|
||||||
#include <Ili934xDisplay.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
#include <tactility/check.h>
|
|
||||||
#include <tactility/device.h>
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
|
||||||
auto* i2c = device_find_by_name("i2c0");
|
|
||||||
check(i2c);
|
|
||||||
auto configuration = std::make_unique<Gt911Touch::Configuration>(
|
|
||||||
i2c,
|
|
||||||
LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
LCD_VERTICAL_RESOLUTION
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<Gt911Touch>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
Ili934xDisplay::Configuration panel_configuration = {
|
|
||||||
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
|
||||||
.gapX = 0,
|
|
||||||
.gapY = 0,
|
|
||||||
.swapXY = true,
|
|
||||||
.mirrorX = true,
|
|
||||||
.mirrorY = true,
|
|
||||||
.invertColor = true,
|
|
||||||
.swapBytes = true,
|
|
||||||
.bufferSize = LCD_BUFFER_SIZE,
|
|
||||||
.touch = createTouch(),
|
|
||||||
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
|
||||||
.resetPin = GPIO_NUM_NC,
|
|
||||||
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_RGB
|
|
||||||
};
|
|
||||||
|
|
||||||
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
|
|
||||||
.spiHostDevice = LCD_SPI_HOST,
|
|
||||||
.csPin = LCD_PIN_CS,
|
|
||||||
.dcPin = LCD_PIN_DC,
|
|
||||||
.pixelClockFrequency = 40'000'000,
|
|
||||||
.transactionQueueDepth = 10
|
|
||||||
});
|
|
||||||
|
|
||||||
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
// Display
|
|
||||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
|
||||||
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
|
|
||||||
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
|
|
||||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
|
|
||||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 240;
|
|
||||||
constexpr auto LCD_VERTICAL_RESOLUTION = 320;
|
|
||||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
|
||||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,16 +1,26 @@
|
|||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
#include <tactility/bindings/esp32_sdspi.h>
|
#include <tactility/bindings/esp32_sdspi.h>
|
||||||
#include <tactility/bindings/display_placeholder.h>
|
#include <tactility/bindings/esp32_pwm_ledc.h>
|
||||||
|
#include <tactility/bindings/pwm_backlight.h>
|
||||||
|
#include <tactility/bindings/rgb_led_pwm.h>
|
||||||
|
#include <bindings/ili9341.h>
|
||||||
|
#include <bindings/gt911.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "CYD 2432S032C";
|
model = "CYD 2432S032C";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
compatible = "espressif,esp32-gpio";
|
compatible = "espressif,esp32-gpio";
|
||||||
gpio-count = <40>;
|
gpio-count = <40>;
|
||||||
@@ -22,6 +32,66 @@
|
|||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
|
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
|
||||||
pin-scl = <&gpio0 32 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 {
|
spi0 {
|
||||||
@@ -30,9 +100,20 @@
|
|||||||
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
||||||
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
display {
|
display@0 {
|
||||||
compatible = "display-placeholder";
|
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>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
[general]
|
general.vendor=CYD
|
||||||
vendor=CYD
|
general.name=2432S032C
|
||||||
name=2432S032C
|
|
||||||
|
|
||||||
[apps]
|
apps.launcherAppId=Launcher
|
||||||
launcherAppId=Launcher
|
|
||||||
|
|
||||||
[hardware]
|
hardware.target=ESP32
|
||||||
target=ESP32
|
hardware.flashSize=4MB
|
||||||
flashSize=4MB
|
hardware.spiRam=false
|
||||||
spiRam=false
|
|
||||||
|
|
||||||
[display]
|
dependencies.useDeprecatedHal=false
|
||||||
size=3.2"
|
|
||||||
shape=rectangle
|
|
||||||
dpi=125
|
|
||||||
|
|
||||||
[lvgl]
|
storage.userDataLocation=SD
|
||||||
colorDepth=16
|
|
||||||
|
display.size=3.2"
|
||||||
|
display.shape=rectangle
|
||||||
|
display.dpi=125
|
||||||
|
|
||||||
|
lvgl.colorDepth=16
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/ili9341-module
|
||||||
|
- Drivers/gt911-module
|
||||||
dts: cyd,2432s032c.dts
|
dts: cyd,2432s032c.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel
|
||||||
REQUIRES Tactility esp_lvgl_port ST7796 GT911 PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
#include "devices/Display.h"
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
//Set the RGB Led Pins to output and turn them off
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_4, GPIO_MODE_OUTPUT)); //Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_16, GPIO_MODE_OUTPUT)); //Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_direction(GPIO_NUM_17, GPIO_MODE_OUTPUT)); //Blue
|
|
||||||
|
|
||||||
//0 on, 1 off... yep it's backwards.
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_4, 1)); //Red
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_16, 1)); //Green
|
|
||||||
ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_17, 1)); //Blue
|
|
||||||
|
|
||||||
return driver::pwmbacklight::init(LCD_PIN_BACKLIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
createDisplay(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#include "Display.h"
|
|
||||||
|
|
||||||
#include <Gt911Touch.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
#include <St7796Display.h>
|
|
||||||
#include <tactility/check.h>
|
|
||||||
#include <tactility/device.h>
|
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
|
||||||
auto* i2c = device_find_by_name("i2c0");
|
|
||||||
check(i2c);
|
|
||||||
auto configuration = std::make_unique<Gt911Touch::Configuration>(
|
|
||||||
i2c,
|
|
||||||
LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
LCD_VERTICAL_RESOLUTION
|
|
||||||
);
|
|
||||||
|
|
||||||
return std::make_shared<Gt911Touch>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
|
||||||
auto touch = createTouch();
|
|
||||||
auto configuration = std::make_unique<St7796Display::Configuration>(
|
|
||||||
LCD_SPI_HOST,
|
|
||||||
LCD_PIN_CS,
|
|
||||||
LCD_PIN_DC,
|
|
||||||
LCD_HORIZONTAL_RESOLUTION,
|
|
||||||
LCD_VERTICAL_RESOLUTION,
|
|
||||||
touch,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
configuration->backlightDutyFunction = driver::pwmbacklight::setBacklightDuty;
|
|
||||||
|
|
||||||
auto display = std::make_shared<St7796Display>(std::move(configuration));
|
|
||||||
return std::reinterpret_pointer_cast<tt::hal::display::DisplayDevice>(display);
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <driver/spi_common.h>
|
|
||||||
|
|
||||||
// Display backlight (PWM)
|
|
||||||
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_27;
|
|
||||||
|
|
||||||
// Display
|
|
||||||
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
|
||||||
constexpr auto LCD_PIN_CS = GPIO_NUM_15;
|
|
||||||
constexpr auto LCD_PIN_DC = GPIO_NUM_2;
|
|
||||||
constexpr auto LCD_HORIZONTAL_RESOLUTION = 320;
|
|
||||||
constexpr auto LCD_VERTICAL_RESOLUTION = 480;
|
|
||||||
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
|
||||||
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,27 @@
|
|||||||
/dts-v1/;
|
/dts-v1/;
|
||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
#include <tactility/bindings/esp32_uart.h>
|
#include <tactility/bindings/esp32_uart.h>
|
||||||
#include <tactility/bindings/esp32_sdspi.h>
|
#include <tactility/bindings/esp32_sdspi.h>
|
||||||
#include <tactility/bindings/display_placeholder.h>
|
#include <tactility/bindings/esp32_pwm_ledc.h>
|
||||||
|
#include <tactility/bindings/pwm_backlight.h>
|
||||||
|
#include <tactility/bindings/rgb_led_pwm.h>
|
||||||
|
#include <bindings/st7796.h>
|
||||||
|
#include <bindings/gt911.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "CYD 3248S035C";
|
model = "CYD 3248S035C";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
compatible = "espressif,esp32-gpio";
|
compatible = "espressif,esp32-gpio";
|
||||||
gpio-count = <40>;
|
gpio-count = <40>;
|
||||||
@@ -23,6 +33,13 @@
|
|||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
|
pin-sda = <&gpio0 33 GPIO_FLAG_NONE>;
|
||||||
pin-scl = <&gpio0 32 GPIO_FLAG_NONE>;
|
pin-scl = <&gpio0 32 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
|
touch {
|
||||||
|
compatible = "goodix,gt911";
|
||||||
|
reg = <0x5D>;
|
||||||
|
x-max = <320>;
|
||||||
|
y-max = <480>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// CN1 header
|
// CN1 header
|
||||||
@@ -34,15 +51,74 @@
|
|||||||
pin-scl = <&gpio0 22 GPIO_FLAG_NONE>;
|
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 {
|
spi0 {
|
||||||
compatible = "espressif,esp32-spi";
|
compatible = "espressif,esp32-spi";
|
||||||
host = <SPI2_HOST>;
|
host = <SPI2_HOST>;
|
||||||
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
cs-gpios = <&gpio0 15 GPIO_FLAG_NONE>;
|
||||||
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
pin-mosi = <&gpio0 13 GPIO_FLAG_NONE>;
|
||||||
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
pin-sclk = <&gpio0 14 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
display {
|
display@0 {
|
||||||
compatible = "display-placeholder";
|
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>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
[general]
|
general.vendor=CYD
|
||||||
vendor=CYD
|
general.name=3248S035C
|
||||||
name=3248S035C
|
|
||||||
|
apps.launcherAppId=Launcher
|
||||||
[apps]
|
|
||||||
launcherAppId=Launcher
|
hardware.target=ESP32
|
||||||
|
hardware.flashSize=4MB
|
||||||
[hardware]
|
hardware.spiRam=false
|
||||||
target=ESP32
|
|
||||||
flashSize=4MB
|
dependencies.useDeprecatedHal=false
|
||||||
spiRam=false
|
|
||||||
|
storage.userDataLocation=SD
|
||||||
[display]
|
|
||||||
size=3.5"
|
display.size=3.5"
|
||||||
shape=rectangle
|
display.shape=rectangle
|
||||||
dpi=165
|
display.dpi=165
|
||||||
|
|
||||||
[lvgl]
|
lvgl.colorDepth=16
|
||||||
colorDepth=16
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
- Platforms/platform-esp32
|
- Platforms/platform-esp32
|
||||||
|
- Drivers/st7796-module
|
||||||
|
- Drivers/gt911-module
|
||||||
dts: cyd,3248s035c.dts
|
dts: cyd,3248s035c.dts
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
file(GLOB_RECURSE SOURCE_FILES source/*.c*)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
REQUIRES TactilityKernel driver
|
||||||
REQUIRES Tactility EspLcdCompat esp_lcd_st7701 esp_lcd_panel_io_additions GT911 PwmBacklight driver vfs fatfs
|
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
#include "devices/St7701Display.h"
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
|
|
||||||
using namespace tt::hal;
|
|
||||||
|
|
||||||
static bool initBoot() {
|
|
||||||
return driver::pwmbacklight::init(GPIO_NUM_38, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DeviceVector createDevices() {
|
|
||||||
return {
|
|
||||||
std::make_shared<St7701Display>(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
extern const Configuration hardwareConfiguration = {
|
|
||||||
.initBoot = initBoot,
|
|
||||||
.createDevices = createDevices
|
|
||||||
};
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
#include "St7701Display.h"
|
|
||||||
|
|
||||||
#include <Gt911Touch.h>
|
|
||||||
#include <PwmBacklight.h>
|
|
||||||
#include <Tactility/Logger.h>
|
|
||||||
#include <tactility/check.h>
|
|
||||||
#include <tactility/device.h>
|
|
||||||
|
|
||||||
#include <driver/gpio.h>
|
|
||||||
#include <esp_err.h>
|
|
||||||
#include <esp_lcd_panel_rgb.h>
|
|
||||||
#include <esp_lcd_panel_ops.h>
|
|
||||||
#include <esp_lcd_panel_io_additions.h>
|
|
||||||
#include <esp_lcd_st7701.h>
|
|
||||||
|
|
||||||
static const auto LOGGER = tt::Logger("St7701Display");
|
|
||||||
|
|
||||||
static const st7701_lcd_init_cmd_t st7701_lcd_init_cmds[] = {
|
|
||||||
// {cmd, { data }, data_size, delay_ms}
|
|
||||||
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0},
|
|
||||||
{0xC0, (uint8_t[]) {0x3B, 0x00}, 2, 0},
|
|
||||||
{0xC1, (uint8_t[]) {0x0D, 0x02}, 2, 0},
|
|
||||||
{0xC2, (uint8_t[]) {0x31, 0x05}, 2, 0},
|
|
||||||
{0xCD, (uint8_t[]) {0x00}, 1, 0}, //0x08
|
|
||||||
//Positive Voltage Gamma Control
|
|
||||||
{0xB0, (uint8_t[]) {0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18}, 16, 0},
|
|
||||||
//Negative Voltage Gamma Control
|
|
||||||
{0xB1, (uint8_t[]) {0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18}, 16, 0},
|
|
||||||
//Page1
|
|
||||||
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x11}, 5, 0},
|
|
||||||
{0xB0, (uint8_t[]) {0x60}, 1, 0}, //Vop=4.7375v
|
|
||||||
{0xB1, (uint8_t[]) {0x32}, 1, 0}, //VCOM=32
|
|
||||||
{0xB2, (uint8_t[]) {0x07}, 1, 0}, //VGH=15v
|
|
||||||
{0xB3, (uint8_t[]) {0x80}, 1, 0},
|
|
||||||
{0xB5, (uint8_t[]) {0x49}, 1, 0}, //VGL=-10.17v
|
|
||||||
{0xB7, (uint8_t[]) {0x85}, 1, 0},
|
|
||||||
{0xB8, (uint8_t[]) {0x21}, 1, 0}, //AVDD=6.6 & AVCL=-4.6
|
|
||||||
{0xC1, (uint8_t[]) {0x78}, 1, 0},
|
|
||||||
{0xC2, (uint8_t[]) {0x78}, 1, 0},
|
|
||||||
{0xE0, (uint8_t[]) {0x00, 0x1B, 0x02}, 3, 0},
|
|
||||||
{0xE1, (uint8_t[]) {0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44}, 11, 0},
|
|
||||||
{0xE2, (uint8_t[]) {0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00}, 12, 0},
|
|
||||||
{0xE3, (uint8_t[]) {0x00, 0x00, 0x11, 0x11}, 4, 0},
|
|
||||||
{0xE4, (uint8_t[]) {0x44, 0x44}, 2, 0},
|
|
||||||
{0xE5, (uint8_t[]) {0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0}, 16, 0},
|
|
||||||
{0xE6, (uint8_t[]) {0x00, 0x00, 0x11, 0x11}, 4, 0},
|
|
||||||
{0xE7, (uint8_t[]) {0x44, 0x44}, 2, 0},
|
|
||||||
{0xE8, (uint8_t[]) {0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0}, 16, 0},
|
|
||||||
{0xEB, (uint8_t[]) {0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40}, 7, 0},
|
|
||||||
{0xEC, (uint8_t[]) {0x3C, 0x00}, 2, 0},
|
|
||||||
{0xED, (uint8_t[]) {0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA}, 16, 0},
|
|
||||||
//VAP & VAN
|
|
||||||
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x13}, 5, 0},
|
|
||||||
{0xE5, (uint8_t[]) {0xE4}, 1, 0},
|
|
||||||
{0xFF, (uint8_t[]) {0x77, 0x01, 0x00, 0x00, 0x00}, 5, 0},
|
|
||||||
{0x3A, (uint8_t[]) {0x60}, 1, 10}, //0x70 RGB888, 0x60 RGB666, 0x50 RGB565
|
|
||||||
{0x11, (uint8_t[]) {0x00}, 0, 120}, //Sleep Out
|
|
||||||
{0x29, (uint8_t[]) {0x00}, 0, 0}, //Display On
|
|
||||||
};
|
|
||||||
|
|
||||||
bool St7701Display::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
|
|
||||||
spi_line_config_t line_config = {
|
|
||||||
.cs_io_type = IO_TYPE_GPIO,
|
|
||||||
.cs_gpio_num = GPIO_NUM_39,
|
|
||||||
.scl_io_type = IO_TYPE_GPIO,
|
|
||||||
.scl_gpio_num = GPIO_NUM_48,
|
|
||||||
.sda_io_type = IO_TYPE_GPIO,
|
|
||||||
.sda_gpio_num = GPIO_NUM_47,
|
|
||||||
.io_expander = nullptr,
|
|
||||||
};
|
|
||||||
esp_lcd_panel_io_3wire_spi_config_t panel_io_config = ST7701_PANEL_IO_3WIRE_SPI_CONFIG(line_config, 0);
|
|
||||||
return esp_lcd_new_panel_io_3wire_spi(&panel_io_config, &outHandle) == ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool St7701Display::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) {
|
|
||||||
const esp_lcd_rgb_panel_config_t rgb_config = {
|
|
||||||
.clk_src = LCD_CLK_SRC_DEFAULT,
|
|
||||||
.timings = {
|
|
||||||
.pclk_hz = 14000000,
|
|
||||||
.h_res = 480,
|
|
||||||
.v_res = 480,
|
|
||||||
.hsync_pulse_width = 10,
|
|
||||||
.hsync_back_porch = 10,
|
|
||||||
.hsync_front_porch = 20,
|
|
||||||
.vsync_pulse_width = 10,
|
|
||||||
.vsync_back_porch = 10,
|
|
||||||
.vsync_front_porch = 10,
|
|
||||||
.flags = {
|
|
||||||
.hsync_idle_low = false,
|
|
||||||
.vsync_idle_low = false,
|
|
||||||
.de_idle_high = false,
|
|
||||||
.pclk_active_neg = false,
|
|
||||||
.pclk_idle_high = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.data_width = 16,
|
|
||||||
.bits_per_pixel = 16,
|
|
||||||
.num_fbs = 2,
|
|
||||||
.bounce_buffer_size_px = 480 * 10,
|
|
||||||
.sram_trans_align = 8,
|
|
||||||
.psram_trans_align = 64,
|
|
||||||
.hsync_gpio_num = GPIO_NUM_16,
|
|
||||||
.vsync_gpio_num = GPIO_NUM_17,
|
|
||||||
.de_gpio_num = GPIO_NUM_18,
|
|
||||||
.pclk_gpio_num = GPIO_NUM_21,
|
|
||||||
.disp_gpio_num = GPIO_NUM_NC,
|
|
||||||
.data_gpio_nums = {
|
|
||||||
GPIO_NUM_4, // B1
|
|
||||||
GPIO_NUM_5, // B2
|
|
||||||
GPIO_NUM_6, // B3
|
|
||||||
GPIO_NUM_7, // B4
|
|
||||||
GPIO_NUM_15, // B5
|
|
||||||
GPIO_NUM_8, // G1
|
|
||||||
GPIO_NUM_20, // G2
|
|
||||||
GPIO_NUM_3, // G3
|
|
||||||
GPIO_NUM_46, // G4
|
|
||||||
GPIO_NUM_9, // G5
|
|
||||||
GPIO_NUM_10, // G6
|
|
||||||
GPIO_NUM_11, // R1
|
|
||||||
GPIO_NUM_12, // R2
|
|
||||||
GPIO_NUM_13, // R3
|
|
||||||
GPIO_NUM_14, // R4
|
|
||||||
GPIO_NUM_0 // R5
|
|
||||||
},
|
|
||||||
.flags = {
|
|
||||||
.disp_active_low = false,
|
|
||||||
.refresh_on_demand = false,
|
|
||||||
.fb_in_psram = true,
|
|
||||||
.double_fb = true,
|
|
||||||
.no_fb = false,
|
|
||||||
.bb_invalidate_cache = true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
st7701_vendor_config_t vendor_config = {
|
|
||||||
.init_cmds = st7701_lcd_init_cmds,
|
|
||||||
.init_cmds_size = sizeof(st7701_lcd_init_cmds) / sizeof(st7701_lcd_init_cmd_t),
|
|
||||||
.rgb_config = &rgb_config,
|
|
||||||
.flags = {
|
|
||||||
.use_mipi_interface = 0,
|
|
||||||
.mirror_by_cmd = 1,
|
|
||||||
.auto_del_panel_io = 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const esp_lcd_panel_dev_config_t panel_config = {
|
|
||||||
.reset_gpio_num = GPIO_NUM_NC,
|
|
||||||
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
|
|
||||||
.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE,
|
|
||||||
.bits_per_pixel = 16,
|
|
||||||
.flags = {
|
|
||||||
.reset_active_high = false,
|
|
||||||
},
|
|
||||||
.vendor_config = &vendor_config,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (esp_lcd_new_panel_st7701(ioHandle, &panel_config, &panelHandle) != ESP_OK) {
|
|
||||||
LOGGER.error("Failed to create panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_reset(panelHandle) != ESP_OK) {
|
|
||||||
LOGGER.error("Failed to reset panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_init(panelHandle) != ESP_OK) {
|
|
||||||
LOGGER.error("Failed to init panel");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp_lcd_panel_invert_color(panelHandle, false) != ESP_OK) {
|
|
||||||
LOGGER.error("Failed to invert color");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_lcd_panel_set_gap(panelHandle, 0, 0);
|
|
||||||
|
|
||||||
if (esp_lcd_panel_disp_on_off(panelHandle, true) != ESP_OK) {
|
|
||||||
LOGGER.error("Failed to turn display on");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
lvgl_port_display_cfg_t St7701Display::getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
|
|
||||||
return {
|
|
||||||
.io_handle = ioHandle,
|
|
||||||
.panel_handle = panelHandle,
|
|
||||||
.control_handle = nullptr,
|
|
||||||
.buffer_size = (480 * 480),
|
|
||||||
.double_buffer = true,
|
|
||||||
.trans_size = 0,
|
|
||||||
.hres = 480,
|
|
||||||
.vres = 480,
|
|
||||||
.monochrome = false,
|
|
||||||
.rotation = {
|
|
||||||
.swap_xy = false,
|
|
||||||
.mirror_x = false,
|
|
||||||
.mirror_y = false,
|
|
||||||
},
|
|
||||||
.color_format = LV_COLOR_FORMAT_RGB565,
|
|
||||||
.flags = {
|
|
||||||
.buff_dma = false,
|
|
||||||
.buff_spiram = true,
|
|
||||||
.sw_rotate = false,
|
|
||||||
.swap_bytes = false,
|
|
||||||
.full_refresh = false,
|
|
||||||
.direct_mode = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
lvgl_port_display_rgb_cfg_t St7701Display::getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) {
|
|
||||||
return {
|
|
||||||
.flags = {
|
|
||||||
.bb_mode = true,
|
|
||||||
.avoid_tearing = false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::touch::TouchDevice> St7701Display::getTouchDevice() {
|
|
||||||
if (touchDevice == nullptr) {
|
|
||||||
auto* i2c = device_find_by_name("i2c0");
|
|
||||||
check(i2c);
|
|
||||||
auto configuration = std::make_unique<Gt911Touch::Configuration>(
|
|
||||||
i2c,
|
|
||||||
480,
|
|
||||||
480
|
|
||||||
);
|
|
||||||
|
|
||||||
touchDevice = std::make_shared<Gt911Touch>(std::move(configuration));
|
|
||||||
}
|
|
||||||
|
|
||||||
return touchDevice;
|
|
||||||
}
|
|
||||||
|
|
||||||
void St7701Display::setBacklightDuty(uint8_t backlightDuty) {
|
|
||||||
driver::pwmbacklight::setBacklightDuty(backlightDuty);
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <EspLcdDisplay.h>
|
|
||||||
#include <lvgl.h>
|
|
||||||
|
|
||||||
class St7701Display final : public EspLcdDisplay {
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::touch::TouchDevice> touchDevice;
|
|
||||||
|
|
||||||
bool createIoHandle(esp_lcd_panel_io_handle_t& outHandle) override;
|
|
||||||
|
|
||||||
bool createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t& panelHandle) override;
|
|
||||||
|
|
||||||
lvgl_port_display_cfg_t getLvglPortDisplayConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) override;
|
|
||||||
|
|
||||||
bool isRgbPanel() const override { return true; }
|
|
||||||
|
|
||||||
lvgl_port_display_rgb_cfg_t getLvglPortDisplayRgbConfig(esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t panelHandle) override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
St7701Display() : EspLcdDisplay() {}
|
|
||||||
|
|
||||||
std::string getName() const override { return "ST7701S"; }
|
|
||||||
|
|
||||||
std::string getDescription() const override { return "ST7701S RGB display"; }
|
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::touch::TouchDevice> getTouchDevice() override;
|
|
||||||
|
|
||||||
void setBacklightDuty(uint8_t backlightDuty) override;
|
|
||||||
|
|
||||||
bool supportsBacklightDuty() const override { return true; }
|
|
||||||
|
|
||||||
// TODO: Find out why it crashes
|
|
||||||
bool supportsDisplayDriver() const override { return false; }
|
|
||||||
};
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#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_4848s040c_module = {
|
|
||||||
.name = "cyd-4848s040c",
|
|
||||||
.start = start,
|
|
||||||
.stop = stop,
|
|
||||||
.symbols = nullptr,
|
|
||||||
.internal = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -2,17 +2,28 @@
|
|||||||
|
|
||||||
#include <tactility/bindings/root.h>
|
#include <tactility/bindings/root.h>
|
||||||
#include <tactility/bindings/esp32_ble.h>
|
#include <tactility/bindings/esp32_ble.h>
|
||||||
|
#include <tactility/bindings/esp32_wifi_pinned.h>
|
||||||
#include <tactility/bindings/esp32_gpio.h>
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
#include <tactility/bindings/esp32_i2c.h>
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
#include <tactility/bindings/esp32_spi.h>
|
|
||||||
#include <tactility/bindings/esp32_sdspi.h>
|
#include <tactility/bindings/esp32_sdspi.h>
|
||||||
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
|
#include <tactility/bindings/esp32_pwm_ledc.h>
|
||||||
|
#include <tactility/bindings/pwm_backlight.h>
|
||||||
|
#include <bindings/st7701.h>
|
||||||
|
#include <bindings/gt911.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
compatible = "root";
|
compatible = "root";
|
||||||
model = "CYD 4848S040C";
|
model = "CYD 4848S040C";
|
||||||
|
|
||||||
|
wifi0 {
|
||||||
|
compatible = "espressif,esp32-wifi-pinned";
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
ble0 {
|
ble0 {
|
||||||
compatible = "espressif,esp32-ble";
|
compatible = "espressif,esp32-ble";
|
||||||
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
gpio0 {
|
gpio0 {
|
||||||
@@ -26,6 +37,124 @@
|
|||||||
clock-frequency = <400000>;
|
clock-frequency = <400000>;
|
||||||
pin-sda = <&gpio0 19 GPIO_FLAG_NONE>;
|
pin-sda = <&gpio0 19 GPIO_FLAG_NONE>;
|
||||||
pin-scl = <&gpio0 45 GPIO_FLAG_NONE>;
|
pin-scl = <&gpio0 45 GPIO_FLAG_NONE>;
|
||||||
|
|
||||||
|
touch0 {
|
||||||
|
// No reset/interrupt pin wired up here, matching the original deprecated-HAL
|
||||||
|
// config (Gt911Touch::Configuration was constructed with no reset/interrupt pin
|
||||||
|
// arguments on this board).
|
||||||
|
compatible = "goodix,gt911";
|
||||||
|
reg = <0x5D>;
|
||||||
|
x-max = <480>;
|
||||||
|
y-max = <480>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
display_backlight_pwm {
|
||||||
|
compatible = "espressif,esp32-pwm-ledc";
|
||||||
|
pin = <&gpio0 38 GPIO_FLAG_NONE>;
|
||||||
|
period-ns = <1000000>;
|
||||||
|
ledc-timer = <0>;
|
||||||
|
ledc-channel = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
display_backlight {
|
||||||
|
compatible = "pwm-backlight";
|
||||||
|
pwm = <&display_backlight_pwm>;
|
||||||
|
};
|
||||||
|
|
||||||
|
display0 {
|
||||||
|
compatible = "sitronix,st7701";
|
||||||
|
horizontal-resolution = <480>;
|
||||||
|
vertical-resolution = <480>;
|
||||||
|
pixel-clock-hz = <14000000>;
|
||||||
|
hsync-pulse-width = <10>;
|
||||||
|
hsync-back-porch = <10>;
|
||||||
|
hsync-front-porch = <20>;
|
||||||
|
vsync-pulse-width = <10>;
|
||||||
|
vsync-back-porch = <10>;
|
||||||
|
vsync-front-porch = <10>;
|
||||||
|
num-fbs = <2>;
|
||||||
|
double-fb;
|
||||||
|
bounce-buffer-size-px = <4800>;
|
||||||
|
bb-invalidate-cache;
|
||||||
|
pin-hsync = <&gpio0 16 GPIO_FLAG_NONE>;
|
||||||
|
pin-vsync = <&gpio0 17 GPIO_FLAG_NONE>;
|
||||||
|
pin-de = <&gpio0 18 GPIO_FLAG_NONE>;
|
||||||
|
pin-pclk = <&gpio0 21 GPIO_FLAG_NONE>;
|
||||||
|
pin-data0 = <&gpio0 4 GPIO_FLAG_NONE>; // B1
|
||||||
|
pin-data1 = <&gpio0 5 GPIO_FLAG_NONE>; // B2
|
||||||
|
pin-data2 = <&gpio0 6 GPIO_FLAG_NONE>; // B3
|
||||||
|
pin-data3 = <&gpio0 7 GPIO_FLAG_NONE>; // B4
|
||||||
|
pin-data4 = <&gpio0 15 GPIO_FLAG_NONE>; // B5
|
||||||
|
pin-data5 = <&gpio0 8 GPIO_FLAG_NONE>; // G1
|
||||||
|
pin-data6 = <&gpio0 20 GPIO_FLAG_NONE>; // G2
|
||||||
|
pin-data7 = <&gpio0 3 GPIO_FLAG_NONE>; // G3
|
||||||
|
pin-data8 = <&gpio0 46 GPIO_FLAG_NONE>; // G4
|
||||||
|
pin-data9 = <&gpio0 9 GPIO_FLAG_NONE>; // G5
|
||||||
|
pin-data10 = <&gpio0 10 GPIO_FLAG_NONE>; // G6
|
||||||
|
pin-data11 = <&gpio0 11 GPIO_FLAG_NONE>; // R1
|
||||||
|
pin-data12 = <&gpio0 12 GPIO_FLAG_NONE>; // R2
|
||||||
|
pin-data13 = <&gpio0 13 GPIO_FLAG_NONE>; // R3
|
||||||
|
pin-data14 = <&gpio0 14 GPIO_FLAG_NONE>; // R4
|
||||||
|
pin-data15 = <&gpio0 0 GPIO_FLAG_NONE>; // R5
|
||||||
|
|
||||||
|
// 3-wire bit-banged command bus. GPIO47/48 are physically shared with this board's SD
|
||||||
|
// card SPI2 bus (MOSI/SCLK) - no alternate pins exist on this PCB. No SD card device is
|
||||||
|
// declared in this devicetree yet (CS/MISO pins are unverified), but if one is added on
|
||||||
|
// SPI2_HOST later, declare it *after* this node: starting that SPI bus unconditionally
|
||||||
|
// reprograms the GPIO matrix for its MOSI/SCLK pins (see esp32_spi.cpp's start()),
|
||||||
|
// which reclaims them from this display's bit-banged use without any extra code.
|
||||||
|
pin-cs = <&gpio0 39 GPIO_FLAG_NONE>;
|
||||||
|
pin-scl = <&gpio0 48 GPIO_FLAG_NONE>;
|
||||||
|
pin-sda = <&gpio0 47 GPIO_FLAG_NONE>;
|
||||||
|
mirror-by-cmd;
|
||||||
|
|
||||||
|
init-sequence = [
|
||||||
|
// Vendor bring-up sequence for this panel. Framing is
|
||||||
|
// [cmd, data-len, delay-ms, data-len bytes of data...] - see st7701-module's
|
||||||
|
// init-sequence binding property for the encoding.
|
||||||
|
0xFF 5 0 0x77 0x01 0x00 0x00 0x10
|
||||||
|
0xC0 2 0 0x3B 0x00
|
||||||
|
0xC1 2 0 0x0D 0x02
|
||||||
|
0xC2 2 0 0x31 0x05
|
||||||
|
0xCD 1 0 0x00
|
||||||
|
// Positive Voltage Gamma Control
|
||||||
|
0xB0 16 0 0x00 0x11 0x18 0x0E 0x11 0x06 0x07 0x08 0x07 0x22 0x04 0x12 0x0F 0xAA 0x31 0x18
|
||||||
|
// Negative Voltage Gamma Control
|
||||||
|
0xB1 16 0 0x00 0x11 0x19 0x0E 0x12 0x07 0x08 0x08 0x08 0x22 0x04 0x11 0x11 0xA9 0x32 0x18
|
||||||
|
// Page1
|
||||||
|
0xFF 5 0 0x77 0x01 0x00 0x00 0x11
|
||||||
|
0xB0 1 0 0x60 // Vop=4.7375v
|
||||||
|
0xB1 1 0 0x32 // VCOM=32
|
||||||
|
0xB2 1 0 0x07 // VGH=15v
|
||||||
|
0xB3 1 0 0x80
|
||||||
|
0xB5 1 0 0x49 // VGL=-10.17v
|
||||||
|
0xB7 1 0 0x85
|
||||||
|
0xB8 1 0 0x21 // AVDD=6.6 & AVCL=-4.6
|
||||||
|
0xC1 1 0 0x78
|
||||||
|
0xC2 1 0 0x78
|
||||||
|
0xE0 3 0 0x00 0x1B 0x02
|
||||||
|
0xE1 11 0 0x08 0xA0 0x00 0x00 0x07 0xA0 0x00 0x00 0x00 0x44 0x44
|
||||||
|
0xE2 12 0 0x11 0x11 0x44 0x44 0xED 0xA0 0x00 0x00 0xEC 0xA0 0x00 0x00
|
||||||
|
0xE3 4 0 0x00 0x00 0x11 0x11
|
||||||
|
0xE4 2 0 0x44 0x44
|
||||||
|
0xE5 16 0 0x0A 0xE9 0xD8 0xA0 0x0C 0xEB 0xD8 0xA0 0x0E 0xED 0xD8 0xA0 0x10 0xEF 0xD8 0xA0
|
||||||
|
0xE6 4 0 0x00 0x00 0x11 0x11
|
||||||
|
0xE7 2 0 0x44 0x44
|
||||||
|
0xE8 16 0 0x09 0xE8 0xD8 0xA0 0x0B 0xEA 0xD8 0xA0 0x0D 0xEC 0xD8 0xA0 0x0F 0xEE 0xD8 0xA0
|
||||||
|
0xEB 7 0 0x02 0x00 0xE4 0xE4 0x88 0x00 0x40
|
||||||
|
0xEC 2 0 0x3C 0x00
|
||||||
|
0xED 16 0 0xAB 0x89 0x76 0x54 0x02 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x20 0x45 0x67 0x98 0xBA
|
||||||
|
// VAP & VAN
|
||||||
|
0xFF 5 0 0x77 0x01 0x00 0x00 0x13
|
||||||
|
0xE5 1 0 0xE4
|
||||||
|
0xFF 5 0 0x77 0x01 0x00 0x00 0x00
|
||||||
|
0x3A 1 10 0x60 // 0x70 RGB888, 0x60 RGB666, 0x50 RGB565
|
||||||
|
0x11 0 120 // Sleep Out
|
||||||
|
0x29 0 0 // Display On
|
||||||
|
];
|
||||||
|
|
||||||
|
backlight = <&display_backlight>;
|
||||||
};
|
};
|
||||||
|
|
||||||
spi0 {
|
spi0 {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user