diff --git a/Buildscripts/Flashing/merge.sh b/Buildscripts/Flashing/merge.sh old mode 100644 new mode 100755 diff --git a/CMakeLists.txt b/CMakeLists.txt index 1406db335..2a6948362 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,10 +124,8 @@ else () 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="tactility.launcher") add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="") add_compile_definitions(CONFIG_TT_USER_DATA_LOCATION_INTERNAL) - add_compile_definitions(CONFIG_TT_LVGL_STATUSBAR_COLORS_INVERTED=false) endif () diff --git a/Devices/btt-panda-touch/device.properties b/Devices/btt-panda-touch/device.properties index 33b25f592..c84ed1728 100644 --- a/Devices/btt-panda-touch/device.properties +++ b/Devices/btt-panda-touch/device.properties @@ -1,8 +1,6 @@ general.vendor=BigTreeTech general.name=Panda Touch,K Touch -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/cl32/CMakeLists.txt b/Devices/cl32-v02-v03/CMakeLists.txt similarity index 100% rename from Devices/cl32/CMakeLists.txt rename to Devices/cl32-v02-v03/CMakeLists.txt diff --git a/Devices/cl32/LICENSE-Apache-2.0.md b/Devices/cl32-v02-v03/LICENSE-Apache-2.0.md similarity index 100% rename from Devices/cl32/LICENSE-Apache-2.0.md rename to Devices/cl32-v02-v03/LICENSE-Apache-2.0.md diff --git a/Devices/cl32/cl32.dts b/Devices/cl32-v02-v03/cl32-v02-v03.dts similarity index 90% rename from Devices/cl32/cl32.dts rename to Devices/cl32-v02-v03/cl32-v02-v03.dts index 1fe1a5da9..d6b25f328 100644 --- a/Devices/cl32/cl32.dts +++ b/Devices/cl32-v02-v03/cl32-v02-v03.dts @@ -26,9 +26,9 @@ }; // Top Stemma/Qwiic port 1 shares this bus with the RTC (SDA: pin 1 <-> SCL: pin 2). External - // I2C devices on that port are reachable via i2c0. The tca8418 keyboard (revision 2 hardware) - // and power-supply chip (revision 3 hardware) are mutually exclusive on this bus and are - // created dynamically based on hardware detection - see cl32_detect.cpp. + // I2C devices on that port are reachable via i2c0. The tca8418 keyboard has a different layout + // on revision 2 and 3 hardware and is created dynamically based on hardware detection, see + // cl32_detect.cpp. i2c0 { compatible = "espressif,esp32-i2c-master"; port = ; diff --git a/Devices/cl32/device.properties b/Devices/cl32-v02-v03/device.properties similarity index 62% rename from Devices/cl32/device.properties rename to Devices/cl32-v02-v03/device.properties index ddd42e13f..c61310dcb 100644 --- a/Devices/cl32/device.properties +++ b/Devices/cl32-v02-v03/device.properties @@ -1,10 +1,8 @@ general.vendor=CL-32 -general.name=CL-32 - -apps.launcherAppId=tactility.launcher +general.name=CL-32 v0.2 v0.3 hardware.target=ESP32S3 -hardware.flashSize=8MB +hardware.flashSize=16MB hardware.spiRam=true hardware.spiRamMode=QUAD hardware.spiRamSpeed=80M @@ -20,6 +18,5 @@ display.dpi=139 lvgl.colorDepth=8 lvgl.theme=Mono lvgl.uiDensity=compact -lvgl.statusbarColorsInverted=true -cdn.warningMessage=Only hardware revision 0.2 and 0.3 are supported for now! +cdn.infoMessage=This variant supports hardware revision v0.2 and v0.3. diff --git a/Devices/cl32/module.yaml b/Devices/cl32-v02-v03/module.yaml similarity index 85% rename from Devices/cl32/module.yaml rename to Devices/cl32-v02-v03/module.yaml index e2bc7d3bb..699105690 100644 --- a/Devices/cl32/module.yaml +++ b/Devices/cl32-v02-v03/module.yaml @@ -3,4 +3,4 @@ dependencies: - Drivers/tca8418-module - Drivers/esp-epaper-module - Drivers/bm8563-module -dts: cl32.dts +dts: cl32-v02-v03.dts diff --git a/Devices/cl32-v02-v03/source/cl32_detect.cpp b/Devices/cl32-v02-v03/source/cl32_detect.cpp new file mode 100644 index 000000000..78a2c8ab8 --- /dev/null +++ b/Devices/cl32-v02-v03/source/cl32_detect.cpp @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: Apache-2.0 +#include "cl32_detect.h" + +#include "cl32_v2_keyboard.h" +#include "cl32_v3_keyboard.h" +#include "cl32_v3.h" + +#include +#include +#include +#include + +#include + +constexpr auto* TAG = "cl32-detect"; + +// Revision 2 and 3 boards are both plain tca8418 keyboards with different physical key layouts. +// Revision 3 boards also have a fuel gauge. +static Cl32HardwareRevision cl32_revision = Cl32HardwareRevision::Unknown; + +// The probe-once latch for on_i2c0_started(). File-scope (not function-local) so +// cl32_teardown_devices() can reset it for a later start/probe cycle. +static bool did_probe = false; + +static Cl32HardwareRevision cl32_detect(Device* i2c0) { + if (i2c_controller_has_device_at_address(i2c0, CL32_V3_FUEL_GAUGE_I2C_ADDRESS, CL32_V3_TIMEOUT) == ERROR_NONE) { + LOG_I(TAG, "Detected V3 hardware by MAX17048G fuel gauge presence"); + return Cl32HardwareRevision::Revision3; + } + + LOG_I(TAG, "No fuel gauge detected, assuming revision 2 hardware"); + return Cl32HardwareRevision::Revision2; +} + +// Fires for every device's start/stop in the system. +static void on_i2c0_started(Device* device, DeviceEvent event, void* context) { + (void)context; + + if (did_probe || event != DEVICE_EVENT_STARTED || strcmp(device->name, "i2c0") != 0) { + return; + } + did_probe = true; + + cl32_revision = cl32_detect(device); + + switch (cl32_revision) { + case Cl32HardwareRevision::Revision2: + cl32_create_keyboard(device); + break; + case Cl32HardwareRevision::Revision3: + cl32_v3_create_keyboard(device); + break; + default: + LOG_W(TAG, "Unknown/unsupported hardware revision"); + break; + } +} + +Cl32HardwareRevision cl32_hardware_revision() { + return cl32_revision; +} + +void cl32_teardown_devices() { + // The keyboards bind the shared ti,tca8418 driver (owned by tca8418-module), so they don't block + // this module's driver destruction. They are torn down so a later start can recreate them. + cl32_destroy_keyboard(); + cl32_v3_destroy_keyboard(); + + did_probe = false; +} + +void cl32_power_detect_start() { + device_listener_add(on_i2c0_started, nullptr); +} + +void cl32_power_detect_stop() { + device_listener_remove(on_i2c0_started, nullptr); +} diff --git a/Devices/cl32/source/cl32_detect.h b/Devices/cl32-v02-v03/source/cl32_detect.h similarity index 95% rename from Devices/cl32/source/cl32_detect.h rename to Devices/cl32-v02-v03/source/cl32_detect.h index f54f56854..be890e184 100644 --- a/Devices/cl32/source/cl32_detect.h +++ b/Devices/cl32-v02-v03/source/cl32_detect.h @@ -4,7 +4,6 @@ enum class Cl32HardwareRevision { Unknown, Revision2, Revision3, - Revision4, }; Cl32HardwareRevision cl32_hardware_revision(); diff --git a/Devices/cl32/source/cl32_v2.h b/Devices/cl32-v02-v03/source/cl32_v2.h similarity index 100% rename from Devices/cl32/source/cl32_v2.h rename to Devices/cl32-v02-v03/source/cl32_v2.h diff --git a/Devices/cl32/source/cl32_v2_keyboard.cpp b/Devices/cl32-v02-v03/source/cl32_v2_keyboard.cpp similarity index 100% rename from Devices/cl32/source/cl32_v2_keyboard.cpp rename to Devices/cl32-v02-v03/source/cl32_v2_keyboard.cpp diff --git a/Devices/cl32/source/cl32_v2_keyboard.h b/Devices/cl32-v02-v03/source/cl32_v2_keyboard.h similarity index 100% rename from Devices/cl32/source/cl32_v2_keyboard.h rename to Devices/cl32-v02-v03/source/cl32_v2_keyboard.h diff --git a/Devices/cl32/source/cl32_v3.h b/Devices/cl32-v02-v03/source/cl32_v3.h similarity index 100% rename from Devices/cl32/source/cl32_v3.h rename to Devices/cl32-v02-v03/source/cl32_v3.h diff --git a/Devices/cl32/source/cl32_v3_keyboard.cpp b/Devices/cl32-v02-v03/source/cl32_v3_keyboard.cpp similarity index 100% rename from Devices/cl32/source/cl32_v3_keyboard.cpp rename to Devices/cl32-v02-v03/source/cl32_v3_keyboard.cpp diff --git a/Devices/cl32/source/cl32_v3_keyboard.h b/Devices/cl32-v02-v03/source/cl32_v3_keyboard.h similarity index 100% rename from Devices/cl32/source/cl32_v3_keyboard.h rename to Devices/cl32-v02-v03/source/cl32_v3_keyboard.h diff --git a/Devices/cl32/source/module.cpp b/Devices/cl32-v02-v03/source/module.cpp similarity index 72% rename from Devices/cl32/source/module.cpp rename to Devices/cl32-v02-v03/source/module.cpp index 89ace18a0..8ec26610c 100644 --- a/Devices/cl32/source/module.cpp +++ b/Devices/cl32-v02-v03/source/module.cpp @@ -1,8 +1,6 @@ #include #include "cl32_detect.h" -#include "cl32_v4_keyboard.h" -#include "cl32_v4_power.h" extern "C" { @@ -18,13 +16,10 @@ static error_t stop() { } static Driver* const cl32_drivers[] = { - &cl32_v4_power_driver, - &cl32_v4_power_supply_driver, - &cl32_v4_keyboard_driver, nullptr }; -Module cl32_module = { +Module cl32_v02_v03_module = { .name = "cl32", .start = start, .stop = stop, diff --git a/Devices/cl32-v04/CMakeLists.txt b/Devices/cl32-v04/CMakeLists.txt new file mode 100644 index 000000000..09a2fdee3 --- /dev/null +++ b/Devices/cl32-v04/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE SOURCE_FILES source/*.c*) + +idf_component_register( + SRCS ${SOURCE_FILES} + INCLUDE_DIRS "source" + REQUIRES TactilityKernel +) diff --git a/Devices/cl32-v04/LICENSE-Apache-2.0.md b/Devices/cl32-v04/LICENSE-Apache-2.0.md new file mode 100644 index 000000000..f5f4b8b5e --- /dev/null +++ b/Devices/cl32-v04/LICENSE-Apache-2.0.md @@ -0,0 +1,195 @@ +Apache License +============== + +_Version 2.0, January 2004_ +_<>_ + +### Terms and Conditions for use, reproduction, and distribution + +#### 1. Definitions + +“License” shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +“Licensor” shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +“Legal Entity” shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, “control” means **(i)** the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the +outstanding shares, or **(iii)** beneficial ownership of such entity. + +“You” (or “Your”) shall mean an individual or Legal Entity exercising +permissions granted by this License. + +“Source” form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +“Object” form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +“Work” shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +“Derivative Works” shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +“Contribution” shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +“submitted” means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as “Not a Contribution.” + +“Contributor” shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +#### 2. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +#### 3. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +#### 4. Redistribution + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +* **(a)** You must give any other recipients of the Work or Derivative Works a copy of +this License; and +* **(b)** You must cause any modified files to carry prominent notices stating that You +changed the files; and +* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +#### 5. Submission of Contributions + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +#### 6. Trademarks + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +#### 7. Disclaimer of Warranty + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +#### 8. Limitation of Liability + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +#### 9. Accepting Warranty or Additional Liability + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +_END OF TERMS AND CONDITIONS_ + +### APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets `[]` replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same “printed page” as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Devices/cl32-v04/bindings/cl32-v4-keyboard.yaml b/Devices/cl32-v04/bindings/cl32-v4-keyboard.yaml new file mode 100644 index 000000000..f1216fd15 --- /dev/null +++ b/Devices/cl32-v04/bindings/cl32-v4-keyboard.yaml @@ -0,0 +1,7 @@ +description: CL-32 v0.4 keyboard, provided by the core chip + +include: ["i2c-device.yaml"] + +compatible: "cl32-v4-keyboard" + +bus: i2c diff --git a/Devices/cl32-v04/bindings/cl32-v4-light.yaml b/Devices/cl32-v04/bindings/cl32-v4-light.yaml new file mode 100644 index 000000000..753c5f9b3 --- /dev/null +++ b/Devices/cl32-v04/bindings/cl32-v4-light.yaml @@ -0,0 +1,23 @@ +description: CL-32 v0.4 display light, provided by the core chip + +include: ["i2c-device.yaml"] + +compatible: "cl32-v4-light" + +bus: i2c + +properties: + brightness-register: + type: int + description: Register that holds the brightness level (0-255) + timeout-register: + type: int + description: Register that holds the timeout in seconds + brightness-default: + type: int + default: 255 + description: Default brightness level (0-255), applied by set_brightness_default() + timeout-seconds: + type: int + default: 10 + description: Seconds of inactivity after which the core chip turns the light off. 0 keeps the chip's own setting. diff --git a/Devices/cl32-v04/bindings/cl32-v4-power.yaml b/Devices/cl32-v04/bindings/cl32-v4-power.yaml new file mode 100644 index 000000000..14cb3473a --- /dev/null +++ b/Devices/cl32-v04/bindings/cl32-v4-power.yaml @@ -0,0 +1,7 @@ +description: CL-32 v0.4 battery voltage and power off, provided by the core chip + +include: ["i2c-device.yaml"] + +compatible: "cl32-v4-power" + +bus: i2c diff --git a/Devices/cl32-v04/cl32-v04.dts b/Devices/cl32-v04/cl32-v04.dts new file mode 100644 index 000000000..570a0c3e7 --- /dev/null +++ b/Devices/cl32-v04/cl32-v04.dts @@ -0,0 +1,107 @@ +/dts-v1/; + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/ { + compatible = "root"; + model = "CL-32"; + + gpio0 { + compatible = "espressif,esp32-gpio"; + gpio-count = <49>; + }; + + wifi0 { + compatible = "espressif,esp32-wifi"; + status = "disabled"; + }; + + // Top Stemma/Qwiic port 1 shares this bus with the RTC (SDA: pin 1 <-> SCL: pin 2). External + // I2C devices on that port are reachable via i2c0. + i2c0 { + compatible = "espressif,esp32-i2c-master"; + port = ; + clock-frequency = <100000>; + pin-sda = <&gpio0 1 GPIO_FLAG_PULL_UP>; + pin-scl = <&gpio0 2 GPIO_FLAG_PULL_UP>; + + rtc: bm8563 { + compatible = "belling,bm8563"; + reg = <0x51>; + }; + + // The core chip provides both the keyboard and the power functions + keyboard { + compatible = "cl32-v4-keyboard"; + reg = <0x08>; + }; + + power { + compatible = "cl32-v4-power"; + reg = <0x08>; + }; + + back_light { + compatible = "cl32-v4-light"; + reg = <0x08>; + brightness-register = <0x0F>; + timeout-register = <0x10>; + }; + + front_light { + compatible = "cl32-v4-light"; + status = "disabled"; // Will be in future hardware + reg = <0x08>; + brightness-register = <0x11>; + timeout-register = <0x12>; + }; + }; + + port_b: grove1 { + compatible = "espressif,esp32-grove"; + defaultMode = ; + pinSdaTx = <&gpio0 47 GPIO_FLAG_NONE>; + pinSclRx = <&gpio0 48 GPIO_FLAG_NONE>; + uartPort = ; + i2cPort = ; + i2cClockFrequency = <100000>; + }; + + spi1 { + compatible = "espressif,esp32-spi"; + host = ; + cs-gpios = <&gpio0 7 GPIO_FLAG_NONE>, + <&gpio0 6 GPIO_FLAG_NONE>; + pin-mosi = <&gpio0 10 GPIO_FLAG_NONE>; + pin-miso = <&gpio0 11 GPIO_FLAG_NONE>; + pin-sclk = <&gpio0 9 GPIO_FLAG_NONE>; + max-transfer-size = <4096>; + + sdcard@0 { + compatible = "espressif,esp32-sdspi"; + frequency-khz = <20000>; + }; + + display@1 { + compatible = "sitronix,st7305"; + pin-dc = <&gpio0 13 GPIO_FLAG_NONE>; + pin-reset = <&gpio0 12 GPIO_FLAG_NONE>; + pixel-clock-hz = <80000000>; + mirror-x; + mirror-y; + backlight = <&back_light>; + }; + }; +}; diff --git a/Devices/cl32-v04/device.properties b/Devices/cl32-v04/device.properties new file mode 100644 index 000000000..e0d4ac0e9 --- /dev/null +++ b/Devices/cl32-v04/device.properties @@ -0,0 +1,22 @@ +general.vendor=CL-32 +general.name=CL-32 v0.4 + +hardware.target=ESP32S3 +hardware.flashSize=8MB +hardware.spiRam=true +hardware.spiRamMode=OCT +hardware.spiRamSpeed=80M +hardware.spiRamXipDisabled=true +hardware.esptoolFlashFreq=80M +hardware.bluetooth=true + +storage.userDataLocation=SD + +display.size=2.9" +display.dpi=139 + +lvgl.colorDepth=8 +lvgl.theme=Mono +lvgl.uiDensity=compact + +cdn.infoMessage=This variant supports hardware revision v0.4 with the reflective LCD. diff --git a/Devices/cl32-v04/module.yaml b/Devices/cl32-v04/module.yaml new file mode 100644 index 000000000..fc1d8ecf3 --- /dev/null +++ b/Devices/cl32-v04/module.yaml @@ -0,0 +1,6 @@ +dependencies: + - Platforms/platform-esp32 + - Drivers/bm8563-module + - Drivers/st7305-module +bindings: bindings +dts: cl32-v04.dts diff --git a/Devices/cl32-v04/source/bindings/cl32_v4_keyboard.h b/Devices/cl32-v04/source/bindings/cl32_v4_keyboard.h new file mode 100644 index 000000000..3fe72c8d2 --- /dev/null +++ b/Devices/cl32-v04/source/bindings/cl32_v4_keyboard.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +DEFINE_DEVICETREE(cl32_v4_keyboard, struct Cl32V4KeyboardConfig) diff --git a/Devices/cl32-v04/source/bindings/cl32_v4_light.h b/Devices/cl32-v04/source/bindings/cl32_v4_light.h new file mode 100644 index 000000000..61957626e --- /dev/null +++ b/Devices/cl32-v04/source/bindings/cl32_v4_light.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +DEFINE_DEVICETREE(cl32_v4_light, struct Cl32V4LightConfig) diff --git a/Devices/cl32-v04/source/bindings/cl32_v4_power.h b/Devices/cl32-v04/source/bindings/cl32_v4_power.h new file mode 100644 index 000000000..604132032 --- /dev/null +++ b/Devices/cl32-v04/source/bindings/cl32_v4_power.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include + +DEFINE_DEVICETREE(cl32_v4_power, struct Cl32V4PowerConfig) diff --git a/Devices/cl32/source/cl32_v4.h b/Devices/cl32-v04/source/cl32_v4.h similarity index 56% rename from Devices/cl32/source/cl32_v4.h rename to Devices/cl32-v04/source/cl32_v4.h index d65739f33..2954c86b9 100644 --- a/Devices/cl32/source/cl32_v4.h +++ b/Devices/cl32-v04/source/cl32_v4.h @@ -4,6 +4,4 @@ #include -constexpr uint8_t CL32_V4_KEYBOARD_PROBE_REGISTER = 0x02; -constexpr uint8_t CL32_V4_CORE_I2C_ADDRESS = 0x08; constexpr TickType_t CL32_V4_CORE_TIMEOUT = pdMS_TO_TICKS(50); diff --git a/Devices/cl32/source/cl32_v4_keyboard.cpp b/Devices/cl32-v04/source/cl32_v4_keyboard.cpp similarity index 78% rename from Devices/cl32/source/cl32_v4_keyboard.cpp rename to Devices/cl32-v04/source/cl32_v4_keyboard.cpp index 6cae65b5d..229098eb2 100644 --- a/Devices/cl32/source/cl32_v4_keyboard.cpp +++ b/Devices/cl32-v04/source/cl32_v4_keyboard.cpp @@ -9,10 +9,12 @@ #include -extern Module cl32_module; +extern Module cl32_v04_module; constexpr auto* TAG = "cl32-v4-keyboard"; +#define GET_CONFIG(device) (static_cast((device)->config)) + // v4's core chip reports keyboard events on the same I2C address as the power-supply function // (see cl32_v4_power.h) - CL-32/CL-32's CL32_core class talks to both over one address. // Registers below come from that project's regMap.h (CL32_INTERRUPT/EVENT_COUNT/EVENT1). @@ -27,12 +29,13 @@ constexpr uint8_t MAX_EVENTS_PER_DRAIN = 16; // HID Keyboard/Keypad usage codes (USB HID Usage Tables page 0x07) this chip's matrix produces, // named after CL-32/CL-32's CL32_core::_matrix keymap (CL32_core.cpp). -constexpr uint8_t KEY_FN = 0x3A; // repurposed F1 position -constexpr uint8_t KEY_FILE = 0x43; // repurposed F10 position -constexpr uint8_t KEY_MENU = 0x44; // repurposed F11 position +constexpr uint8_t KEY_FN = 0x65; +constexpr uint8_t KEY_FILE = 0x76; +constexpr uint8_t KEY_MENU = 0x74; constexpr uint8_t KEY_ENTER = 0x28; constexpr uint8_t KEY_ESCAPE = 0x29; constexpr uint8_t KEY_BACKSPACE = 0x2A; +constexpr uint8_t KEY_TAB = 0x2B; constexpr uint8_t KEY_SPACE = 0x2C; constexpr uint8_t KEY_EQUALS = 0x2E; constexpr uint8_t KEY_PERIOD = 0x37; @@ -40,6 +43,8 @@ constexpr uint8_t KEY_ARROW_RIGHT = 0x4F; constexpr uint8_t KEY_ARROW_LEFT = 0x50; constexpr uint8_t KEY_ARROW_DOWN = 0x51; constexpr uint8_t KEY_ARROW_UP = 0x52; +constexpr uint8_t KEY_YES = 0x77; +constexpr uint8_t KEY_NO = 0x78; constexpr uint8_t KEYPAD_SLASH = 0x54; constexpr uint8_t KEYPAD_ASTERISK = 0x55; constexpr uint8_t KEYPAD_MINUS = 0x56; @@ -49,7 +54,7 @@ constexpr uint8_t KEYPAD_1 = 0x59; constexpr uint8_t KEYPAD_9 = 0x61; constexpr uint8_t KEYPAD_0 = 0x62; constexpr uint8_t KEYPAD_PERIOD = 0x63; -constexpr uint8_t KEY_SHIFT = 0xE1; +constexpr uint8_t KEY_SHIFT = 0x7F; enum class ToggleState { Unpressed, OnePress, Locked }; @@ -143,6 +148,7 @@ static bool translate_key(uint8_t code, bool shift, bool fn, uint32_t* out_key) switch (code) { case KEY_ENTER: *out_key = CODEPOINT_ENTER; return true; + case KEY_TAB: *out_key = CODEPOINT_TAB; return true; case KEY_ESCAPE: *out_key = CODEPOINT_ESCAPE; return true; case KEY_BACKSPACE: *out_key = CODEPOINT_BACKSPACE; return true; case KEY_SPACE: *out_key = ' '; return true; @@ -152,6 +158,8 @@ static bool translate_key(uint8_t code, bool shift, bool fn, uint32_t* out_key) case KEY_ARROW_LEFT: *out_key = CODEPOINT_ARROW_LEFT; return true; case KEY_ARROW_DOWN: *out_key = CODEPOINT_ARROW_DOWN; return true; case KEY_ARROW_UP: *out_key = CODEPOINT_ARROW_UP; return true; + case KEY_YES: *out_key = CODEPOINT_YES; return true; + case KEY_NO: *out_key = CODEPOINT_NO; return true; case KEYPAD_SLASH: *out_key = '/'; return true; case KEYPAD_ASTERISK: *out_key = '*'; return true; case KEYPAD_MINUS: *out_key = '-'; return true; @@ -171,12 +179,12 @@ static bool translate_key(uint8_t code, bool shift, bool fn, uint32_t* out_key) static void handle_key_down(Cl32V4KeyboardInternal* internal, uint8_t code) { if (code == KEY_SHIFT) { internal->shift_state = next_toggle_state(internal->shift_state); - LOG_I(TAG, "code=0x%02X shift -> %s", code, toggle_state_name(internal->shift_state)); + LOG_D(TAG, "code=0x%02X shift -> %s", code, toggle_state_name(internal->shift_state)); return; } if (code == KEY_FN) { internal->fn_state = next_toggle_state(internal->fn_state); - LOG_I(TAG, "code=0x%02X fn -> %s", code, toggle_state_name(internal->fn_state)); + LOG_D(TAG, "code=0x%02X fn -> %s", code, toggle_state_name(internal->fn_state)); return; } @@ -186,7 +194,7 @@ static void handle_key_down(Cl32V4KeyboardInternal* internal, uint8_t code) { // No app-level menu system at the driver layer - surface the raw HID code only, same as // tab5_keyboard.cpp's F1-F12 handling. if (code == KEY_MENU || code == KEY_FILE) { - LOG_I(TAG, "code=0x%02X (menu/file) shift=%s fn=%s hid_modifier=0x%02X", + LOG_D(TAG, "code=0x%02X (menu/file) shift=%s fn=%s hid_modifier=0x%02X", code, toggle_state_name(internal->shift_state), toggle_state_name(internal->fn_state), hid_modifier); push_pending(internal, 0, true, code, hid_modifier); push_pending(internal, 0, false, code, hid_modifier); @@ -198,7 +206,7 @@ static void handle_key_down(Cl32V4KeyboardInternal* internal, uint8_t code) { const bool has_key = translate_key(code, shift, fn, &key); const char printable = (has_key && key >= 0x20 && key < 0x7F) ? static_cast(key) : '.'; - LOG_I(TAG, "code=0x%02X key='%c' key_hex=0x%04X shift=%s fn=%s hid_modifier=0x%02X", + LOG_D(TAG, "code=0x%02X key='%c' key_hex=0x%04X shift=%s fn=%s hid_modifier=0x%02X", code, printable, static_cast(has_key ? key : 0), toggle_state_name(internal->shift_state), toggle_state_name(internal->fn_state), hid_modifier); @@ -216,9 +224,9 @@ static void handle_key_down(Cl32V4KeyboardInternal* internal, uint8_t code) { } } -static void drain_events(Device* i2c0, Cl32V4KeyboardInternal* internal) { +static void drain_events(Device* i2c0, uint8_t address, Cl32V4KeyboardInternal* internal) { uint8_t interrupt_status = 0; - if (i2c_controller_register8_get(i2c0, CL32_V4_CORE_I2C_ADDRESS, REG_INTERRUPT, &interrupt_status, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { + if (i2c_controller_register8_get(i2c0, address, REG_INTERRUPT, &interrupt_status, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { return; } if ((interrupt_status & INTERRUPT_BIT_KEYBOARD) == 0) { @@ -226,38 +234,38 @@ static void drain_events(Device* i2c0, Cl32V4KeyboardInternal* internal) { } uint8_t count = 0; - if (i2c_controller_register8_get(i2c0, CL32_V4_CORE_I2C_ADDRESS, REG_EVENT_COUNT, &count, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { + if (i2c_controller_register8_get(i2c0, address, REG_EVENT_COUNT, &count, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { return; } for (uint8_t drained = 0; drained < MAX_EVENTS_PER_DRAIN && count > 0; drained++) { uint8_t raw = 0; - if (i2c_controller_register8_get(i2c0, CL32_V4_CORE_I2C_ADDRESS, REG_EVENT1, &raw, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { + if (i2c_controller_register8_get(i2c0, address, REG_EVENT1, &raw, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { break; } - LOG_I(TAG, "raw event=0x%02X (%s)", raw, (raw & 0x80) != 0 ? "down" : "up"); + LOG_D(TAG, "raw event=0x%02X (%s)", raw, (raw & 0x80) != 0 ? "down" : "up"); if ((raw & 0x80) != 0) { handle_key_down(internal, static_cast(raw & 0x7F)); } - if (i2c_controller_register8_get(i2c0, CL32_V4_CORE_I2C_ADDRESS, REG_EVENT_COUNT, &count, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { + if (i2c_controller_register8_get(i2c0, address, REG_EVENT_COUNT, &count, CL32_V4_CORE_TIMEOUT) != ERROR_NONE) { break; } } // Only the keyboard bit is ours to clear - the power-supply function on this same chip owns // the other status bits in this register. - i2c_controller_register8_reset_bits(i2c0, CL32_V4_CORE_I2C_ADDRESS, REG_INTERRUPT, INTERRUPT_BIT_KEYBOARD, CL32_V4_CORE_TIMEOUT); + i2c_controller_register8_reset_bits(i2c0, address, REG_INTERRUPT, INTERRUPT_BIT_KEYBOARD, CL32_V4_CORE_TIMEOUT); } -static error_t v3_read_key(Device* device, KeyboardKeyData* data) { +static error_t v4_read_key(Device* device, KeyboardKeyData* data) { auto* internal = static_cast(device_get_driver_data(device)); Cl32V4KeyEvent event; if (internal->pending_count == 0) { - drain_events(device_get_parent(device), internal); + drain_events(device_get_parent(device), GET_CONFIG(device)->address, internal); } if (pop_pending(internal, &event)) { @@ -282,7 +290,7 @@ static error_t v3_read_key(Device* device, KeyboardKeyData* data) { } static constexpr KeyboardApi cl32_v4_keyboard_api = { - .read_key = v3_read_key, + .read_key = v4_read_key, .get_backlight = nullptr, .is_present = nullptr, }; @@ -313,52 +321,9 @@ Driver cl32_v4_keyboard_driver = { .compatible = (const char*[]) { "cl32-v4-keyboard", nullptr }, .start_device = start, .stop_device = stop, + .probe = nullptr, .api = &cl32_v4_keyboard_api, .device_type = &KEYBOARD_TYPE, - .owner = &cl32_module, - .internal = nullptr + .owner = &cl32_v04_module, + .internal = nullptr, }; - -static Device cl32_v4_keyboard_device {}; -static bool cl32_v4_keyboard_created = false; - -bool cl32_v4_create_keyboard(Device* i2c0) { - cl32_v4_keyboard_device = Device { .address = 0, .name = "cl32-v4-keyboard", .config = nullptr, .parent = nullptr, .flags = 0, .internal = nullptr }; - - error_t error = device_construct(&cl32_v4_keyboard_device); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to construct keyboard: %s", error_to_string(error)); - return false; - } - - device_set_parent(&cl32_v4_keyboard_device, i2c0); - device_set_driver(&cl32_v4_keyboard_device, &cl32_v4_keyboard_driver); - - error = device_add(&cl32_v4_keyboard_device); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to add keyboard: %s", error_to_string(error)); - device_destruct(&cl32_v4_keyboard_device); - return false; - } - - error = device_start(&cl32_v4_keyboard_device); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to start keyboard: %s", error_to_string(error)); - device_remove(&cl32_v4_keyboard_device); - device_destruct(&cl32_v4_keyboard_device); - return false; - } - - cl32_v4_keyboard_created = true; - return true; -} - -void cl32_v4_destroy_keyboard() { - if (!cl32_v4_keyboard_created) { - return; - } - device_stop(&cl32_v4_keyboard_device); - device_remove(&cl32_v4_keyboard_device); - device_destruct(&cl32_v4_keyboard_device); - cl32_v4_keyboard_created = false; -} diff --git a/Devices/cl32-v04/source/cl32_v4_keyboard.h b/Devices/cl32-v04/source/cl32_v4_keyboard.h new file mode 100644 index 000000000..de2340e3b --- /dev/null +++ b/Devices/cl32-v04/source/cl32_v4_keyboard.h @@ -0,0 +1,19 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +struct Cl32V4KeyboardConfig { + uint8_t address; +}; + +extern struct Driver cl32_v4_keyboard_driver; + +#ifdef __cplusplus +} +#endif diff --git a/Devices/cl32-v04/source/cl32_v4_light.cpp b/Devices/cl32-v04/source/cl32_v4_light.cpp new file mode 100644 index 000000000..e7fdeb050 --- /dev/null +++ b/Devices/cl32-v04/source/cl32_v4_light.cpp @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: Apache-2.0 +#include "cl32_v4_light.h" +#include "cl32_v4.h" + +#include +#include +#include +#include +#include + +extern Module cl32_v04_module; + +constexpr auto* TAG = "cl32-v4-light"; + +#define GET_CONFIG(device) (static_cast((device)->config)) + +static error_t set_brightness(Device* device, uint8_t brightness) { + return i2c_controller_register8_set(device_get_parent(device), GET_CONFIG(device)->address, GET_CONFIG(device)->brightness_register, brightness, CL32_V4_CORE_TIMEOUT); +} + +static error_t set_brightness_default(Device* device) { + return set_brightness(device, GET_CONFIG(device)->brightness_default); +} + +static error_t get_brightness(Device* device, uint8_t* out_brightness) { + return i2c_controller_register8_get(device_get_parent(device), GET_CONFIG(device)->address, GET_CONFIG(device)->brightness_register, out_brightness, CL32_V4_CORE_TIMEOUT); +} + +static constexpr BacklightApi CL32_V4_LIGHT_API = { + .set_brightness = set_brightness, + .set_brightness_default = set_brightness_default, + .get_brightness = get_brightness, + .get_min_brightness = nullptr, + .get_max_brightness = nullptr, +}; + +static error_t start(Device* device) { + auto* i2c0 = device_get_parent(device); + if (device_get_type(i2c0) != &I2C_CONTROLLER_TYPE) { + LOG_E(TAG, "Parent is not an I2C controller"); + return ERROR_RESOURCE; + } + + const auto* config = GET_CONFIG(device); + if (config->timeout_seconds > 0) { + auto timeout_value = config->timeout_seconds * 15; + if (timeout_value > 255) { + timeout_value = 255; + } + + error_t error = i2c_controller_register8_set(i2c0, config->address, config->timeout_register, static_cast(timeout_value), CL32_V4_CORE_TIMEOUT); + if (error != ERROR_NONE) { + LOG_E(TAG, "Failed to set timeout"); + return error; + } + } + + return ERROR_NONE; +} + +static error_t stop(Device*) { + return ERROR_NONE; +} + +Driver cl32_v4_light_driver = { + .name = "cl32-v4-light", + .compatible = (const char*[]) { "cl32-v4-light", nullptr }, + .start_device = start, + .stop_device = stop, + .probe = nullptr, + .api = &CL32_V4_LIGHT_API, + .device_type = &BACKLIGHT_TYPE, + .owner = &cl32_v04_module, + .internal = nullptr, +}; diff --git a/Devices/cl32-v04/source/cl32_v4_light.h b/Devices/cl32-v04/source/cl32_v4_light.h new file mode 100644 index 000000000..747899941 --- /dev/null +++ b/Devices/cl32-v04/source/cl32_v4_light.h @@ -0,0 +1,23 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +struct Cl32V4LightConfig { + uint8_t address; + uint8_t brightness_register; + uint8_t timeout_register; + uint8_t brightness_default; + uint8_t timeout_seconds; +}; + +extern struct Driver cl32_v4_light_driver; + +#ifdef __cplusplus +} +#endif diff --git a/Devices/cl32/source/cl32_v4_power.cpp b/Devices/cl32-v04/source/cl32_v4_power.cpp similarity index 85% rename from Devices/cl32/source/cl32_v4_power.cpp rename to Devices/cl32-v04/source/cl32_v4_power.cpp index 8e7439bf8..0f1d4a2ed 100644 --- a/Devices/cl32/source/cl32_v4_power.cpp +++ b/Devices/cl32-v04/source/cl32_v4_power.cpp @@ -11,10 +11,15 @@ #include -extern Module cl32_module; +extern Module cl32_v04_module; constexpr auto* TAG = "cl32-v4-power"; +#define GET_CONFIG(device) (static_cast((device)->config)) + +constexpr uint8_t REG_POWER_CONTROL = 0x01; +constexpr uint8_t POWER_CONTROL_CUT_POWER = 0x80; +constexpr uint8_t BAT_VOLTAGE = 0x13; constexpr uint8_t REG_VOLTAGE = 0x14; constexpr int MV_PER_LSB = 25; constexpr int MIN_MV = 3200; @@ -31,7 +36,7 @@ static bool ps_supports_property(Device*, PowerSupplyProperty property) { static error_t read_battery_mv(Device* chip_device, int* out_mv) { auto* i2c0 = device_get_parent(chip_device); uint8_t raw = 0; - error_t error = i2c_controller_register8_get(i2c0, CL32_V4_CORE_I2C_ADDRESS, REG_VOLTAGE, &raw, CL32_V4_CORE_TIMEOUT); + error_t error = i2c_controller_register8_get(i2c0, GET_CONFIG(chip_device)->address, BAT_VOLTAGE, &raw, CL32_V4_CORE_TIMEOUT); if (error != ERROR_NONE) { return error; } @@ -66,8 +71,13 @@ static error_t ps_set_allowed_to_charge(Device*, bool) { return ERROR_NOT_SUPPOR static bool ps_supports_quick_charge(Device*) { return false; } static bool ps_is_quick_charge_enabled(Device*) { return false; } static error_t ps_set_quick_charge_enabled(Device*, bool) { return ERROR_NOT_SUPPORTED; } -static bool ps_supports_power_off(Device*) { return false; } -static error_t ps_power_off(Device*) { return ERROR_NOT_SUPPORTED; } +static bool ps_supports_power_off(Device*) { return true; } + +static error_t ps_power_off(Device* device) { + auto* chip_device = device_get_parent(device); + auto* i2c0 = device_get_parent(chip_device); + return i2c_controller_register8_set_bits(i2c0, GET_CONFIG(chip_device)->address, REG_POWER_CONTROL, POWER_CONTROL_CUT_POWER, CL32_V4_CORE_TIMEOUT); +} static constexpr PowerSupplyApi CL32_V4_POWER_SUPPLY_API = { .supports_property = ps_supports_property, @@ -82,7 +92,7 @@ static constexpr PowerSupplyApi CL32_V4_POWER_SUPPLY_API = { .power_off = ps_power_off, }; -// Registered in cl32_module's driver list so driver_bind() has a valid ->internal, but never +// Registered in cl32_v04_module's driver list so driver_bind() has a valid ->internal, but never // matched against a devicetree node: wired up directly by pointer from cl32_v4_power_driver's start(). Driver cl32_v4_power_supply_driver = { .name = "cl32-v4-power-supply", @@ -91,7 +101,7 @@ Driver cl32_v4_power_supply_driver = { .stop_device = nullptr, .api = &CL32_V4_POWER_SUPPLY_API, .device_type = &POWER_SUPPLY_TYPE, - .owner = &cl32_module, + .owner = &cl32_v04_module, .internal = nullptr }; @@ -179,8 +189,9 @@ Driver cl32_v4_power_driver = { .compatible = (const char*[]) { "cl32-v4-power", nullptr }, .start_device = start, .stop_device = stop, + .probe = nullptr, .api = nullptr, .device_type = nullptr, - .owner = &cl32_module, - .internal = nullptr + .owner = &cl32_v04_module, + .internal = nullptr, }; diff --git a/Devices/cl32-v04/source/cl32_v4_power.h b/Devices/cl32-v04/source/cl32_v4_power.h new file mode 100644 index 000000000..3e2149f95 --- /dev/null +++ b/Devices/cl32-v04/source/cl32_v4_power.h @@ -0,0 +1,20 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +struct Cl32V4PowerConfig { + uint8_t address; +}; + +extern struct Driver cl32_v4_power_driver; +extern struct Driver cl32_v4_power_supply_driver; + +#ifdef __cplusplus +} +#endif diff --git a/Devices/cl32-v04/source/module.cpp b/Devices/cl32-v04/source/module.cpp new file mode 100644 index 000000000..cea5887ef --- /dev/null +++ b/Devices/cl32-v04/source/module.cpp @@ -0,0 +1,26 @@ +#include + +#include "cl32_v4_light.h" +#include "cl32_v4_keyboard.h" +#include "cl32_v4_power.h" + +extern "C" { + +static Driver* const cl32_drivers[] = { + &cl32_v4_power_driver, + &cl32_v4_power_supply_driver, + &cl32_v4_keyboard_driver, + &cl32_v4_light_driver, + nullptr +}; + +Module cl32_v04_module = { + .name = "cl32", + .start = nullptr, + .stop = nullptr, + .drivers = cl32_drivers, + .symbols = nullptr, + .internal = nullptr +}; + +} diff --git a/Devices/cl32/source/cl32_detect.cpp b/Devices/cl32/source/cl32_detect.cpp deleted file mode 100644 index ae9d46360..000000000 --- a/Devices/cl32/source/cl32_detect.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -#include "cl32_detect.h" - -#include "cl32_v2_keyboard.h" -#include "cl32_v3_keyboard.h" -#include "cl32_v2.h" -#include "cl32_v3.h" -#include "cl32_v4.h" -#include "cl32_v4_keyboard.h" -#include "cl32_v4_power.h" - -#include -#include -#include -#include - -#include - -constexpr auto* TAG = "cl32-detect"; - -// Revision 2 and 3 boards are both plain tca8418 keyboards (different physical key layouts) with -// no core chip. Revision 4 boards have the core chip (power + keyboard) at CL32_V4_CORE_I2C_ADDRESS. -static Cl32HardwareRevision cl32_revision = Cl32HardwareRevision::Unknown; - -static Device cl32_v4_power_device {}; -static bool cl32_v4_power_created = false; - -// The probe-once latch for on_i2c0_started(). File-scope (not function-local) so -// cl32_teardown_devices() can reset it for a later start/probe cycle. -static bool did_probe = false; - -static void create_v2_devices(Device* i2c0) { - cl32_create_keyboard(i2c0); -} - -static void create_v3_devices(Device* i2c0) { - cl32_v3_create_keyboard(i2c0); -} - -static bool create_v4_power_device(Device* i2c0) { - cl32_v4_power_device = Device { .address = 0, .name = "cl32-v4-power", .config = nullptr, .parent = nullptr, .flags = 0, .internal = nullptr }; - - error_t error = device_construct(&cl32_v4_power_device); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to construct cl32-v4-power: %s", error_to_string(error)); - return false; - } - - device_set_parent(&cl32_v4_power_device, i2c0); - device_set_driver(&cl32_v4_power_device, &cl32_v4_power_driver); - - error = device_add(&cl32_v4_power_device); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to add cl32-v4-power: %s", error_to_string(error)); - device_destruct(&cl32_v4_power_device); - return false; - } - - error = device_start(&cl32_v4_power_device); - if (error != ERROR_NONE) { - LOG_E(TAG, "Failed to start cl32-v4-power: %s", error_to_string(error)); - device_remove(&cl32_v4_power_device); - device_destruct(&cl32_v4_power_device); - return false; - } - - return true; -} - -static void create_v4_devices(Device* i2c0) { - cl32_v4_create_keyboard(i2c0); - cl32_v4_power_created = create_v4_power_device(i2c0); -} - -// Stops, removes and destructs cl32_v4_power_device if it was successfully created. -// cl32_v4_power_driver's own stop() tears down its power-supply child device. -static void destroy_v4_power_device() { - if (!cl32_v4_power_created) { - return; - } - device_stop(&cl32_v4_power_device); - device_remove(&cl32_v4_power_device); - device_destruct(&cl32_v4_power_device); - cl32_v4_power_created = false; -} - -static Cl32HardwareRevision cl32_detect(Device* i2c0) { - uint8_t probe_value = 0; - if (i2c_controller_register8_get(i2c0, CL32_V4_CORE_I2C_ADDRESS, CL32_V4_KEYBOARD_PROBE_REGISTER, &probe_value, CL32_V4_CORE_TIMEOUT) == ERROR_NONE) { - LOG_I(TAG, "Detected V4 hardware by V4 keyboard presence"); - return Cl32HardwareRevision::Revision4; - } - - if (i2c_controller_has_device_at_address(i2c0, CL32_V3_FUEL_GAUGE_I2C_ADDRESS, CL32_V3_TIMEOUT) == ERROR_NONE) { - LOG_I(TAG, "Detected V3 hardware by MAX17048G fuel gauge presence"); - return Cl32HardwareRevision::Revision3; - } - - LOG_I(TAG, "No core chip or fuel gauge detected, assuming revision 2 hardware"); - return Cl32HardwareRevision::Revision2; -} - -// Fires for every device's start/stop in the system. -static void on_i2c0_started(Device* device, DeviceEvent event, void* context) { - (void)context; - - if (did_probe || event != DEVICE_EVENT_STARTED || strcmp(device->name, "i2c0") != 0) { - return; - } - did_probe = true; - - cl32_revision = cl32_detect(device); - - switch (cl32_revision) { - case Cl32HardwareRevision::Revision2: - create_v2_devices(device); - break; - case Cl32HardwareRevision::Revision3: - create_v3_devices(device); - break; - case Cl32HardwareRevision::Revision4: - create_v4_devices(device); - break; - default: - LOG_W(TAG, "Unknown/unsupported hardware revision"); - break; - } -} - -Cl32HardwareRevision cl32_hardware_revision() { - return cl32_revision; -} - -void cl32_teardown_devices() { - // Revision 2/3 keyboards bind the shared ti,tca8418 driver (owned by tca8418-module), so they - // don't block cl32_module's own driver destruction - torn down anyway for symmetry and so a - // later start can recreate them cleanly. - cl32_destroy_keyboard(); - cl32_v3_destroy_keyboard(); - - // Revision 4 devices bind cl32-owned drivers (cl32_v4_keyboard_driver, cl32_v4_power_driver). - // Must be torn down before cl32_module's driver-removal loop runs, or driver_destruct() finds - // a started device still using the driver and fails. - cl32_v4_destroy_keyboard(); - destroy_v4_power_device(); - - did_probe = false; -} - -void cl32_power_detect_start() { - device_listener_add(on_i2c0_started, nullptr); -} - -void cl32_power_detect_stop() { - device_listener_remove(on_i2c0_started, nullptr); -} diff --git a/Devices/cl32/source/cl32_v4_keyboard.h b/Devices/cl32/source/cl32_v4_keyboard.h deleted file mode 100644 index 5656342ea..000000000 --- a/Devices/cl32/source/cl32_v4_keyboard.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include - -extern struct Driver cl32_v4_keyboard_driver; - -/** @return true if the device was successfully constructed, added and started. */ -bool cl32_v4_create_keyboard(struct Device* i2c0); - -void cl32_v4_destroy_keyboard(); diff --git a/Devices/cl32/source/cl32_v4_power.h b/Devices/cl32/source/cl32_v4_power.h deleted file mode 100644 index d5c00af36..000000000 --- a/Devices/cl32/source/cl32_v4_power.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include - -extern struct Driver cl32_v4_power_driver; -extern struct Driver cl32_v4_power_supply_driver; diff --git a/Devices/cyd-2432s022c/device.properties b/Devices/cyd-2432s022c/device.properties index d8d557195..eab2252b7 100644 --- a/Devices/cyd-2432s022c/device.properties +++ b/Devices/cyd-2432s022c/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=2432S022C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-2432s024c/device.properties b/Devices/cyd-2432s024c/device.properties index 79fbab144..e46cfeb35 100644 --- a/Devices/cyd-2432s024c/device.properties +++ b/Devices/cyd-2432s024c/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=2432S024C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-2432s024r/device.properties b/Devices/cyd-2432s024r/device.properties index 0ecc3c95a..a4354475c 100644 --- a/Devices/cyd-2432s024r/device.properties +++ b/Devices/cyd-2432s024r/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=2432S024R -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-2432s028r/device.properties b/Devices/cyd-2432s028r/device.properties index 0f1cd7291..e9ba9c11c 100644 --- a/Devices/cyd-2432s028r/device.properties +++ b/Devices/cyd-2432s028r/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=2432S028R -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-2432s028rv3/device.properties b/Devices/cyd-2432s028rv3/device.properties index 719d40944..ae63a8915 100644 --- a/Devices/cyd-2432s028rv3/device.properties +++ b/Devices/cyd-2432s028rv3/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=2432S028R v3 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-2432s032c/device.properties b/Devices/cyd-2432s032c/device.properties index 9b36b1169..0f1c43049 100644 --- a/Devices/cyd-2432s032c/device.properties +++ b/Devices/cyd-2432s032c/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=2432S032C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-3248s035c/device.properties b/Devices/cyd-3248s035c/device.properties index a51851cb6..88fe71771 100644 --- a/Devices/cyd-3248s035c/device.properties +++ b/Devices/cyd-3248s035c/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=3248S035C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-4848s040c/device.properties b/Devices/cyd-4848s040c/device.properties index 4010ff28e..9e4669b2d 100644 --- a/Devices/cyd-4848s040c/device.properties +++ b/Devices/cyd-4848s040c/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=4848S040C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/cyd-8048s043c/device.properties b/Devices/cyd-8048s043c/device.properties index e8fdd45ae..1ffd1cc91 100644 --- a/Devices/cyd-8048s043c/device.properties +++ b/Devices/cyd-8048s043c/device.properties @@ -2,8 +2,6 @@ general.vendor=CYD general.name=8048S043C general.incubating=false -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/cyd-e32r28t/device.properties b/Devices/cyd-e32r28t/device.properties index 9cf2c9585..53db09d96 100644 --- a/Devices/cyd-e32r28t/device.properties +++ b/Devices/cyd-e32r28t/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=E32R28T -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/cyd-e32r32p/device.properties b/Devices/cyd-e32r32p/device.properties index fb8e19615..88b6fc805 100644 --- a/Devices/cyd-e32r32p/device.properties +++ b/Devices/cyd-e32r32p/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=E32R32P -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/elecrow-crowpanel-advance-28/device.properties b/Devices/elecrow-crowpanel-advance-28/device.properties index 4e8cba9ac..8711bc1dd 100644 --- a/Devices/elecrow-crowpanel-advance-28/device.properties +++ b/Devices/elecrow-crowpanel-advance-28/device.properties @@ -1,8 +1,6 @@ general.vendor=Elecrow general.name=CrowPanel Advance 2.8" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/elecrow-crowpanel-advance-35/device.properties b/Devices/elecrow-crowpanel-advance-35/device.properties index 434b63456..e08b73b37 100644 --- a/Devices/elecrow-crowpanel-advance-35/device.properties +++ b/Devices/elecrow-crowpanel-advance-35/device.properties @@ -1,8 +1,6 @@ general.vendor=Elecrow general.name=CrowPanel Advance 3.5" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/elecrow-crowpanel-advance-50/device.properties b/Devices/elecrow-crowpanel-advance-50/device.properties index 019d03ea2..78cfc75a7 100644 --- a/Devices/elecrow-crowpanel-advance-50/device.properties +++ b/Devices/elecrow-crowpanel-advance-50/device.properties @@ -1,8 +1,6 @@ general.vendor=Elecrow general.name=CrowPanel Advance 5.0" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/elecrow-crowpanel-basic-28/device.properties b/Devices/elecrow-crowpanel-basic-28/device.properties index 2e331dbd0..73db8df69 100644 --- a/Devices/elecrow-crowpanel-basic-28/device.properties +++ b/Devices/elecrow-crowpanel-basic-28/device.properties @@ -1,8 +1,6 @@ general.vendor=Elecrow general.name=CrowPanel Basic 2.8" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/elecrow-crowpanel-basic-35/device.properties b/Devices/elecrow-crowpanel-basic-35/device.properties index 702b683f7..721ab97d7 100644 --- a/Devices/elecrow-crowpanel-basic-35/device.properties +++ b/Devices/elecrow-crowpanel-basic-35/device.properties @@ -1,8 +1,6 @@ general.vendor=Elecrow general.name=CrowPanel Basic 3.5" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/elecrow-crowpanel-basic-50/device.properties b/Devices/elecrow-crowpanel-basic-50/device.properties index 0c69017c9..060bef510 100644 --- a/Devices/elecrow-crowpanel-basic-50/device.properties +++ b/Devices/elecrow-crowpanel-basic-50/device.properties @@ -1,8 +1,6 @@ general.vendor=Elecrow general.name=CrowPanel Basic 5.0" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=4MB hardware.spiRam=true diff --git a/Devices/es3c28p/device.properties b/Devices/es3c28p/device.properties index 3e3f48275..83462a158 100644 --- a/Devices/es3c28p/device.properties +++ b/Devices/es3c28p/device.properties @@ -1,8 +1,6 @@ general.vendor=CYD general.name=ES3C28P -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/generic-esp32/device.properties b/Devices/generic-esp32/device.properties index d1d130b54..00a36531a 100644 --- a/Devices/generic-esp32/device.properties +++ b/Devices/generic-esp32/device.properties @@ -1,8 +1,6 @@ general.vendor=Generic general.name=ESP32 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=8MB hardware.spiRam=false diff --git a/Devices/generic-esp32c6/device.properties b/Devices/generic-esp32c6/device.properties index 07ce7ed4d..a94631150 100644 --- a/Devices/generic-esp32c6/device.properties +++ b/Devices/generic-esp32c6/device.properties @@ -1,8 +1,6 @@ general.vendor=Generic general.name=ESP32-C6 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32C6 hardware.flashSize=8MB hardware.spiRam=false diff --git a/Devices/generic-esp32p4/device.properties b/Devices/generic-esp32p4/device.properties index 815fac6e7..c0aead431 100644 --- a/Devices/generic-esp32p4/device.properties +++ b/Devices/generic-esp32p4/device.properties @@ -1,8 +1,6 @@ general.vendor=Generic general.name=ESP32-P4 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32P4 hardware.flashSize=8MB hardware.spiRam=false diff --git a/Devices/generic-esp32s3/device.properties b/Devices/generic-esp32s3/device.properties index cf04146bd..3cde4e5e8 100644 --- a/Devices/generic-esp32s3/device.properties +++ b/Devices/generic-esp32s3/device.properties @@ -1,8 +1,6 @@ general.vendor=Generic general.name=ESP32-S3 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=8MB hardware.spiRam=false diff --git a/Devices/guition-jc1060p470ciwy/device.properties b/Devices/guition-jc1060p470ciwy/device.properties index 82edaffd5..601c0ff06 100644 --- a/Devices/guition-jc1060p470ciwy/device.properties +++ b/Devices/guition-jc1060p470ciwy/device.properties @@ -1,8 +1,6 @@ general.vendor=Guition general.name=JC1060P470C-I-W-Y -apps.launcherAppId=tactility.launcher - hardware.target=ESP32P4 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/guition-jc2432w328c/device.properties b/Devices/guition-jc2432w328c/device.properties index 39fa27761..aba78d613 100644 --- a/Devices/guition-jc2432w328c/device.properties +++ b/Devices/guition-jc2432w328c/device.properties @@ -1,8 +1,6 @@ general.vendor=Guition general.name=JC2432W328C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=4MB hardware.spiRam=false diff --git a/Devices/guition-jc8048w550c/device.properties b/Devices/guition-jc8048w550c/device.properties index c7287f35e..f35ba22f7 100644 --- a/Devices/guition-jc8048w550c/device.properties +++ b/Devices/guition-jc8048w550c/device.properties @@ -1,8 +1,6 @@ general.vendor=Guition general.name=JC8048W550C -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/heltec-wifi-lora-32-v3/device.properties b/Devices/heltec-wifi-lora-32-v3/device.properties index bd0d98d5c..b04527448 100644 --- a/Devices/heltec-wifi-lora-32-v3/device.properties +++ b/Devices/heltec-wifi-lora-32-v3/device.properties @@ -1,8 +1,6 @@ general.vendor=Heltec general.name=WiFi LoRa 32 v3 general.incubating=true - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32S3 diff --git a/Devices/lilygo-t5-epd47-s3/device.properties b/Devices/lilygo-t5-epd47-s3/device.properties index a520f030c..ba0436a20 100644 --- a/Devices/lilygo-t5-epd47-s3/device.properties +++ b/Devices/lilygo-t5-epd47-s3/device.properties @@ -2,8 +2,6 @@ general.vendor=LilyGO general.name=T5 4.7 Inch E-Paper S3 general.incubating=true -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true @@ -20,4 +18,3 @@ display.dpi=235 lvgl.colorDepth=8 lvgl.fontSize=24 lvgl.theme=Mono -lvgl.statusbarColorsInverted=true diff --git a/Devices/lilygo-tdeck-max/device.properties b/Devices/lilygo-tdeck-max/device.properties index d0fb231f3..9dd64aa29 100644 --- a/Devices/lilygo-tdeck-max/device.properties +++ b/Devices/lilygo-tdeck-max/device.properties @@ -3,8 +3,6 @@ general.name=T-Deck Max # SD card support is not yet working, display driver is untested since refactoring; remove once it is functional. general.incubating=true -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.flashMode=DIO @@ -23,6 +21,5 @@ display.dpi=128 lvgl.colorDepth=8 lvgl.theme=Mono -lvgl.statusbarColorsInverted=true cdn.warningMessage=Display not reliably working. Use at your own risk. diff --git a/Devices/lilygo-tdeck-plus/device.properties b/Devices/lilygo-tdeck-plus/device.properties index 09d50663a..af98ca4ef 100644 --- a/Devices/lilygo-tdeck-plus/device.properties +++ b/Devices/lilygo-tdeck-plus/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-Deck Plus -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/lilygo-tdeck-pro/device.properties b/Devices/lilygo-tdeck-pro/device.properties index 8d43e9a87..ea3a2024c 100644 --- a/Devices/lilygo-tdeck-pro/device.properties +++ b/Devices/lilygo-tdeck-pro/device.properties @@ -3,8 +3,6 @@ general.name=T-Deck Pro # The display driver is not reliable yet general.incubating=true -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.flashMode=DIO @@ -22,6 +20,5 @@ display.dpi=128 lvgl.colorDepth=8 lvgl.theme=Mono -lvgl.statusbarColorsInverted=true cdn.warningMessage=Only for hardware revision 1.0! Display not reliably working. Use at your own risk. diff --git a/Devices/lilygo-tdeck/device.properties b/Devices/lilygo-tdeck/device.properties index ae048e02f..44053d410 100644 --- a/Devices/lilygo-tdeck/device.properties +++ b/Devices/lilygo-tdeck/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-Deck -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/lilygo-tdisplay-s3/device.properties b/Devices/lilygo-tdisplay-s3/device.properties index a4acfacb0..b2ee6a8cb 100644 --- a/Devices/lilygo-tdisplay-s3/device.properties +++ b/Devices/lilygo-tdisplay-s3/device.properties @@ -1,7 +1,5 @@ general.vendor=LilyGO general.name=T-Display S3 - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32S3 diff --git a/Devices/lilygo-tdisplay/device.properties b/Devices/lilygo-tdisplay/device.properties index 65f6e5d5b..079899106 100644 --- a/Devices/lilygo-tdisplay/device.properties +++ b/Devices/lilygo-tdisplay/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-Display general.incubating=true - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32 diff --git a/Devices/lilygo-tdongle-s3/device.properties b/Devices/lilygo-tdongle-s3/device.properties index 29026ceb7..3c693beee 100644 --- a/Devices/lilygo-tdongle-s3/device.properties +++ b/Devices/lilygo-tdongle-s3/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-Dongle S3 general.incubating=true - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32S3 diff --git a/Devices/lilygo-tembed-cc1101-plus/device.properties b/Devices/lilygo-tembed-cc1101-plus/device.properties index 3fc5b71e5..9c60d97f2 100644 --- a/Devices/lilygo-tembed-cc1101-plus/device.properties +++ b/Devices/lilygo-tembed-cc1101-plus/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-Embed CC1101 Plus -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/lilygo-thmi/device.properties b/Devices/lilygo-thmi/device.properties index f96e72b0d..214835544 100644 --- a/Devices/lilygo-thmi/device.properties +++ b/Devices/lilygo-thmi/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-HMI -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/lilygo-tlora-pager/device.properties b/Devices/lilygo-tlora-pager/device.properties index 67036824f..782008a68 100644 --- a/Devices/lilygo-tlora-pager/device.properties +++ b/Devices/lilygo-tlora-pager/device.properties @@ -1,8 +1,6 @@ general.vendor=LilyGO general.name=T-Lora Pager -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.flashMode=DIO diff --git a/Devices/m5stack-cardputer-adv/device.properties b/Devices/m5stack-cardputer-adv/device.properties index 88f711d13..23e7548b6 100644 --- a/Devices/m5stack-cardputer-adv/device.properties +++ b/Devices/m5stack-cardputer-adv/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=Cardputer Adv -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=8MB hardware.spiRam=false diff --git a/Devices/m5stack-cardputer/device.properties b/Devices/m5stack-cardputer/device.properties index 5acb634c3..ed78a3ac5 100644 --- a/Devices/m5stack-cardputer/device.properties +++ b/Devices/m5stack-cardputer/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=Cardputer,Cardputer v1.1 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=8MB hardware.spiRam=false diff --git a/Devices/m5stack-core2/device.properties b/Devices/m5stack-core2/device.properties index 75df93deb..94ce9607e 100644 --- a/Devices/m5stack-core2/device.properties +++ b/Devices/m5stack-core2/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=Core2 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/m5stack-cores3/device.properties b/Devices/m5stack-cores3/device.properties index dae43e479..987227f7e 100644 --- a/Devices/m5stack-cores3/device.properties +++ b/Devices/m5stack-cores3/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=CoreS3 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/m5stack-papers3/device.properties b/Devices/m5stack-papers3/device.properties index c9b589727..08a821fa3 100644 --- a/Devices/m5stack-papers3/device.properties +++ b/Devices/m5stack-papers3/device.properties @@ -2,8 +2,6 @@ general.vendor=M5Stack general.name=PaperS3 general.incubating=true -apps.launcherAppId=tactility.launcher - hardware.target=esp32s3 hardware.flashSize=16MB hardware.spiRam=true @@ -21,6 +19,5 @@ display.dpi=235 lvgl.colorDepth=8 lvgl.fontSize=24 lvgl.theme=Mono -lvgl.statusbarColorsInverted=true sdkconfig.CONFIG_EPD_DISPLAY_TYPE_ED047TC2=y diff --git a/Devices/m5stack-stackchan/device.properties b/Devices/m5stack-stackchan/device.properties index 7fba1d863..055f473cf 100644 --- a/Devices/m5stack-stackchan/device.properties +++ b/Devices/m5stack-stackchan/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=StackChan -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/m5stack-stickc-plus2/device.properties b/Devices/m5stack-stickc-plus2/device.properties index 4e8c6ac96..aa9583578 100644 --- a/Devices/m5stack-stickc-plus2/device.properties +++ b/Devices/m5stack-stickc-plus2/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=StickC Plus2 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32 hardware.flashSize=8MB hardware.spiRam=true diff --git a/Devices/m5stack-sticks3/device.properties b/Devices/m5stack-sticks3/device.properties index 1aef1abc7..d629fcb8c 100644 --- a/Devices/m5stack-sticks3/device.properties +++ b/Devices/m5stack-sticks3/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=StickS3 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=8MB hardware.spiRam=true diff --git a/Devices/m5stack-tab5/device.properties b/Devices/m5stack-tab5/device.properties index d8c6658d1..c96bb5061 100644 --- a/Devices/m5stack-tab5/device.properties +++ b/Devices/m5stack-tab5/device.properties @@ -1,8 +1,6 @@ general.vendor=M5Stack general.name=Tab5 -apps.launcherAppId=tactility.launcher - hardware.target=ESP32P4 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/seeed-wio-tracker-l2-pro/device.properties b/Devices/seeed-wio-tracker-l2-pro/device.properties index f71fc09e0..054d80fa8 100644 --- a/Devices/seeed-wio-tracker-l2-pro/device.properties +++ b/Devices/seeed-wio-tracker-l2-pro/device.properties @@ -1,8 +1,6 @@ general.vendor=Seeed Studio general.name=Wio Tracker L2 Pro -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/simulator/device.properties b/Devices/simulator/device.properties index 1d1e7935f..80de67e36 100644 --- a/Devices/simulator/device.properties +++ b/Devices/simulator/device.properties @@ -1,8 +1,6 @@ general.vendor=Simulator general.name=Tab5Simulator -apps.launcherAppId=tactility.launcher - hardware.target=POSIX storage.userDataLocation=Internal diff --git a/Devices/tulip-4r11/device.properties b/Devices/tulip-4r11/device.properties index 6e6565d9b..acd579872 100644 --- a/Devices/tulip-4r11/device.properties +++ b/Devices/tulip-4r11/device.properties @@ -1,8 +1,6 @@ general.vendor=Tulip general.name=Tulip Creative Computer (4r11) -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=32MB hardware.spiRam=true diff --git a/Devices/unphone/device.properties b/Devices/unphone/device.properties index 2bcae7cd3..e1a72b346 100644 --- a/Devices/unphone/device.properties +++ b/Devices/unphone/device.properties @@ -1,8 +1,6 @@ general.vendor=unPhone general.name=unPhone -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=8MB hardware.spiRam=true diff --git a/Devices/waveshare-esp32-s3-geek/device.properties b/Devices/waveshare-esp32-s3-geek/device.properties index ce932f6de..3fffaf9be 100644 --- a/Devices/waveshare-esp32-s3-geek/device.properties +++ b/Devices/waveshare-esp32-s3-geek/device.properties @@ -1,8 +1,6 @@ general.vendor=Waveshare general.name=ESP32 S3 GEEK general.incubating=true - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32S3 diff --git a/Devices/waveshare-s3-lcd-13/device.properties b/Devices/waveshare-s3-lcd-13/device.properties index 232afd04d..da76d32a2 100644 --- a/Devices/waveshare-s3-lcd-13/device.properties +++ b/Devices/waveshare-s3-lcd-13/device.properties @@ -1,8 +1,6 @@ general.vendor=WaveShare general.name=S3 LCD 1.3" general.incubating=true - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32S3 diff --git a/Devices/waveshare-s3-touch-lcd-128/device.properties b/Devices/waveshare-s3-touch-lcd-128/device.properties index 38312d5dc..12f762269 100644 --- a/Devices/waveshare-s3-touch-lcd-128/device.properties +++ b/Devices/waveshare-s3-touch-lcd-128/device.properties @@ -1,8 +1,6 @@ general.vendor=WaveShare general.name=S3 Touch LCD 1.28" general.incubating=true - -apps.launcherAppId=tactility.launcher apps.autoStartAppId=tactility.apwebserver hardware.target=ESP32S3 diff --git a/Devices/waveshare-s3-touch-lcd-147/device.properties b/Devices/waveshare-s3-touch-lcd-147/device.properties index 1e2c95cbd..bed48d83c 100644 --- a/Devices/waveshare-s3-touch-lcd-147/device.properties +++ b/Devices/waveshare-s3-touch-lcd-147/device.properties @@ -2,8 +2,6 @@ general.vendor=WaveShare general.name=S3 Touch LCD 1.47" general.incubating=true -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Devices/waveshare-s3-touch-lcd-43/device.properties b/Devices/waveshare-s3-touch-lcd-43/device.properties index bde03843a..5a54c63ba 100644 --- a/Devices/waveshare-s3-touch-lcd-43/device.properties +++ b/Devices/waveshare-s3-touch-lcd-43/device.properties @@ -1,8 +1,6 @@ general.vendor=WaveShare general.name=S3 Touch LCD 4.3" -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 # Some models have 16MB flash, but some have 8MB. We only support the latter to avoid making more builds. hardware.flashSize=8MB diff --git a/Devices/wireless-tag-wt32-sc01-plus/device.properties b/Devices/wireless-tag-wt32-sc01-plus/device.properties index 41b764c96..439aafad6 100644 --- a/Devices/wireless-tag-wt32-sc01-plus/device.properties +++ b/Devices/wireless-tag-wt32-sc01-plus/device.properties @@ -1,8 +1,6 @@ general.vendor=Wireless Tag general.name=WT32 SC01 Plus -apps.launcherAppId=tactility.launcher - hardware.target=ESP32S3 hardware.flashSize=16MB hardware.spiRam=true diff --git a/Drivers/axp192-module/source/axp192_backlight.cpp b/Drivers/axp192-module/source/axp192_backlight.cpp index 969a989ed..0532cd731 100644 --- a/Drivers/axp192-module/source/axp192_backlight.cpp +++ b/Drivers/axp192-module/source/axp192_backlight.cpp @@ -63,22 +63,14 @@ static error_t axp192_backlight_get_brightness(Device* device, uint8_t* out_brig return ERROR_NONE; } -static uint8_t axp192_backlight_get_min_brightness(Device*) { - return 0; -} - -static uint8_t axp192_backlight_get_max_brightness(Device*) { - return 255; -} - // endregion static constexpr BacklightApi AXP192_BACKLIGHT_API = { .set_brightness = axp192_backlight_set_brightness, .set_brightness_default = axp192_backlight_set_brightness_default, .get_brightness = axp192_backlight_get_brightness, - .get_min_brightness = axp192_backlight_get_min_brightness, - .get_max_brightness = axp192_backlight_get_max_brightness, + .get_min_brightness = nullptr, + .get_max_brightness = nullptr, }; // region Driver lifecycle @@ -123,6 +115,7 @@ Driver axp192_backlight_driver = { .compatible = (const char*[]) { "axp192-backlight", nullptr }, .start_device = start, .stop_device = stop, + .probe = nullptr, .api = &AXP192_BACKLIGHT_API, .device_type = &BACKLIGHT_TYPE, .owner = &axp192_module, diff --git a/Drivers/axp2101-module/source/axp2101_backlight.cpp b/Drivers/axp2101-module/source/axp2101_backlight.cpp index d3c5c756a..8a5d6d642 100644 --- a/Drivers/axp2101-module/source/axp2101_backlight.cpp +++ b/Drivers/axp2101-module/source/axp2101_backlight.cpp @@ -76,22 +76,14 @@ static error_t axp2101_backlight_get_brightness(Device* device, uint8_t* out_bri return ERROR_NONE; } -static uint8_t axp2101_backlight_get_min_brightness(Device*) { - return 0; -} - -static uint8_t axp2101_backlight_get_max_brightness(Device*) { - return 255; -} - // endregion static constexpr BacklightApi AXP2101_BACKLIGHT_API = { .set_brightness = axp2101_backlight_set_brightness, .set_brightness_default = axp2101_backlight_set_brightness_default, .get_brightness = axp2101_backlight_get_brightness, - .get_min_brightness = axp2101_backlight_get_min_brightness, - .get_max_brightness = axp2101_backlight_get_max_brightness, + .get_min_brightness = nullptr, + .get_max_brightness = nullptr, }; // region Driver lifecycle @@ -131,10 +123,11 @@ Driver axp2101_backlight_driver = { .compatible = (const char*[]) { "axp2101-backlight", nullptr }, .start_device = start, .stop_device = stop, + .probe = nullptr, .api = &AXP2101_BACKLIGHT_API, .device_type = &BACKLIGHT_TYPE, .owner = &axp2101_module, - .internal = nullptr + .internal = nullptr, }; } diff --git a/Drivers/lilygo-module/source/tdeck_keyboard_backlight.cpp b/Drivers/lilygo-module/source/tdeck_keyboard_backlight.cpp index fdc89785d..852227686 100644 --- a/Drivers/lilygo-module/source/tdeck_keyboard_backlight.cpp +++ b/Drivers/lilygo-module/source/tdeck_keyboard_backlight.cpp @@ -88,22 +88,14 @@ static error_t tdeck_keyboard_backlight_get_brightness(Device* device, uint8_t* return ERROR_NONE; } -static uint8_t tdeck_keyboard_backlight_get_min_brightness(Device*) { - return 0; -} - -static uint8_t tdeck_keyboard_backlight_get_max_brightness(Device*) { - return 255; -} - // endregion static const BacklightApi tdeck_keyboard_backlight_api = { .set_brightness = tdeck_keyboard_backlight_set_brightness, .set_brightness_default = tdeck_keyboard_backlight_set_brightness_default, .get_brightness = tdeck_keyboard_backlight_get_brightness, - .get_min_brightness = tdeck_keyboard_backlight_get_min_brightness, - .get_max_brightness = tdeck_keyboard_backlight_get_max_brightness, + .get_min_brightness = nullptr, + .get_max_brightness = nullptr, }; extern struct Module lilygo_module; @@ -113,6 +105,7 @@ Driver tdeck_keyboard_backlight_driver = { .compatible = (const char*[]) { "lilygo,tdeck-keyboard-backlight", nullptr }, .start_device = start, .stop_device = stop, + .probe = nullptr, .api = &tdeck_keyboard_backlight_api, .device_type = &BACKLIGHT_TYPE, .owner = &lilygo_module, diff --git a/Drivers/lp5814-module/source/lp5814.cpp b/Drivers/lp5814-module/source/lp5814.cpp index 1e13199be..7d2420525 100644 --- a/Drivers/lp5814-module/source/lp5814.cpp +++ b/Drivers/lp5814-module/source/lp5814.cpp @@ -93,22 +93,14 @@ static error_t lp5814_get_brightness(Device* device, uint8_t* out_brightness) { return ERROR_NONE; } -static uint8_t lp5814_get_min_brightness(Device*) { - return 0; -} - -static uint8_t lp5814_get_max_brightness(Device*) { - return 255; -} - // endregion static constexpr BacklightApi LP5814_BACKLIGHT_API = { .set_brightness = lp5814_set_brightness, .set_brightness_default = lp5814_set_brightness_default, .get_brightness = lp5814_get_brightness, - .get_min_brightness = lp5814_get_min_brightness, - .get_max_brightness = lp5814_get_max_brightness, + .get_min_brightness = nullptr, + .get_max_brightness = nullptr, }; // region Driver lifecycle @@ -159,7 +151,7 @@ Driver lp5814_driver = { .api = &LP5814_BACKLIGHT_API, .device_type = &BACKLIGHT_TYPE, .owner = &lp5814_module, - .internal = nullptr + .internal = nullptr, }; } diff --git a/Drivers/st7305-module/CMakeLists.txt b/Drivers/st7305-module/CMakeLists.txt new file mode 100644 index 000000000..03f9f9da3 --- /dev/null +++ b/Drivers/st7305-module/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.20) + +include("${CMAKE_CURRENT_LIST_DIR}/../../Buildscripts/module.cmake") + +file(GLOB_RECURSE SOURCE_FILES "source/*.c*") + +tactility_add_module(st7305-module + SRCS ${SOURCE_FILES} + INCLUDE_DIRS include/ + REQUIRES TactilityKernel platform-esp32 esp_lcd driver +) diff --git a/Drivers/st7305-module/LICENSE-Apache-2.0.md b/Drivers/st7305-module/LICENSE-Apache-2.0.md new file mode 100644 index 000000000..f5f4b8b5e --- /dev/null +++ b/Drivers/st7305-module/LICENSE-Apache-2.0.md @@ -0,0 +1,195 @@ +Apache License +============== + +_Version 2.0, January 2004_ +_<>_ + +### Terms and Conditions for use, reproduction, and distribution + +#### 1. Definitions + +“License” shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +“Licensor” shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +“Legal Entity” shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, “control” means **(i)** the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the +outstanding shares, or **(iii)** beneficial ownership of such entity. + +“You” (or “Your”) shall mean an individual or Legal Entity exercising +permissions granted by this License. + +“Source” form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +“Object” form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +“Work” shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +“Derivative Works” shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +“Contribution” shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +“submitted” means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as “Not a Contribution.” + +“Contributor” shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +#### 2. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +#### 3. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +#### 4. Redistribution + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +* **(a)** You must give any other recipients of the Work or Derivative Works a copy of +this License; and +* **(b)** You must cause any modified files to carry prominent notices stating that You +changed the files; and +* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +#### 5. Submission of Contributions + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +#### 6. Trademarks + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +#### 7. Disclaimer of Warranty + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +#### 8. Limitation of Liability + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +#### 9. Accepting Warranty or Additional Liability + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +_END OF TERMS AND CONDITIONS_ + +### APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets `[]` replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same “printed page” as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/Drivers/st7305-module/README.md b/Drivers/st7305-module/README.md new file mode 100644 index 000000000..e5602faf7 --- /dev/null +++ b/Drivers/st7305-module/README.md @@ -0,0 +1,12 @@ +# ST7305 display controller + +A driver for the Sitronix `ST7305` monochrome reflective LCD controller (`sitronix,st7305`), connected over SPI. + +- Original/reference code: https://github.com/Kevincoooool/esp_lcd_st7305, licensed under [Apache v2.0](https://github.com/Kevincoooool/esp_lcd_st7305/blob/master/license.txt) + +The init sequence and RAM layout are based on the reference's 2.9" (384x168) panel configuration. +The panel is driven in full-frame mode: each frame is converted from LVGL's 1bpp format into the controller's +interleaved 2-line RAM layout before it is sent. +Mirroring is applied in software during that conversion. + +License: [Apache v2.0](LICENSE-Apache-2.0.md) diff --git a/Drivers/st7305-module/bindings/sitronix,st7305.yaml b/Drivers/st7305-module/bindings/sitronix,st7305.yaml new file mode 100644 index 000000000..aa4f4e716 --- /dev/null +++ b/Drivers/st7305-module/bindings/sitronix,st7305.yaml @@ -0,0 +1,49 @@ +description: > + Sitronix ST7305 monochrome reflective LCD panel (SPI interface). + The horizontal axis maps to the panel's gate lines and the vertical axis to its source lines. + +compatible: "sitronix,st7305" + +bus: spi + +properties: + horizontal-resolution: + type: int + default: 384 + description: Horizontal resolution in pixels (gate lines, must be a multiple of 4, maximum 512) + vertical-resolution: + type: int + default: 168 + description: Vertical resolution in pixels (source lines) + column-offset: + type: int + default: 23 + description: First RAM column address used by the panel (0x17 for the 2.9" 384x168 panel) + mirror-x: + type: boolean + default: false + description: Mirror the X axis + mirror-y: + type: boolean + default: false + description: Mirror the Y axis + invert-color: + type: boolean + default: false + description: Invert the panel's color output + pixel-clock-hz: + type: int + default: 20000000 + description: SPI clock frequency in Hz + pin-dc: + type: phandles + required: true + description: Data/Command GPIO pin + pin-reset: + type: phandles + default: GPIO_PIN_SPEC_NONE + description: Reset GPIO pin + backlight: + type: phandle + default: "NULL" + description: Optional reference to this display's backlight device diff --git a/Drivers/st7305-module/include/bindings/st7305.h b/Drivers/st7305-module/include/bindings/st7305.h new file mode 100644 index 000000000..4acde6fd7 --- /dev/null +++ b/Drivers/st7305-module/include/bindings/st7305.h @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include +#include + +DEFINE_DEVICETREE(st7305, struct St7305Config) diff --git a/Drivers/st7305-module/include/drivers/st7305.h b/Drivers/st7305-module/include/drivers/st7305.h new file mode 100644 index 000000000..c368112d9 --- /dev/null +++ b/Drivers/st7305-module/include/drivers/st7305.h @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include +#include + +struct St7305Config { + uint16_t horizontal_resolution; + uint16_t vertical_resolution; + uint8_t column_offset; + bool mirror_x; + bool mirror_y; + bool invert_color; + uint32_t pixel_clock_hz; + struct GpioPinSpec pin_dc; + struct GpioPinSpec pin_reset; + // Optional reference to this display's backlight device, NULL if none. + struct Device* backlight; +}; + +#ifdef __cplusplus +} +#endif diff --git a/Drivers/st7305-module/include/st7305_module.h b/Drivers/st7305-module/include/st7305_module.h new file mode 100644 index 000000000..dffd85c1a --- /dev/null +++ b/Drivers/st7305-module/include/st7305_module.h @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct Module st7305_module; + +#ifdef __cplusplus +} +#endif diff --git a/Drivers/st7305-module/module.yaml b/Drivers/st7305-module/module.yaml new file mode 100644 index 000000000..a07d6f334 --- /dev/null +++ b/Drivers/st7305-module/module.yaml @@ -0,0 +1,3 @@ +dependencies: + - TactilityKernel +bindings: bindings diff --git a/Drivers/st7305-module/source/module.cpp b/Drivers/st7305-module/source/module.cpp new file mode 100644 index 000000000..610006f40 --- /dev/null +++ b/Drivers/st7305-module/source/module.cpp @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include + +extern "C" { + +extern Driver st7305_driver; + +static Driver* const st7305_drivers[] = { + &st7305_driver, + nullptr +}; + +Module st7305_module = { + .name = "st7305", + .start = nullptr, + .stop = nullptr, + .drivers = st7305_drivers, + .symbols = nullptr, + .internal = nullptr +}; + +} // extern "C" diff --git a/Drivers/st7305-module/source/st7305.cpp b/Drivers/st7305-module/source/st7305.cpp new file mode 100644 index 000000000..2d6b7769c --- /dev/null +++ b/Drivers/st7305-module/source/st7305.cpp @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: Apache-2.0 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#define TAG "ST7305" + +#define GET_CONFIG(device) (static_cast((device)->config)) + +constexpr uint8_t CMD_SLPOUT = 0x11; +constexpr uint8_t CMD_INVOFF = 0x20; +constexpr uint8_t CMD_INVON = 0x21; +constexpr uint8_t CMD_DISPOFF = 0x28; +constexpr uint8_t CMD_DISPON = 0x29; +constexpr uint8_t CMD_CASET = 0x2A; +constexpr uint8_t CMD_RASET = 0x2B; +constexpr uint8_t CMD_RAMWR = 0x2C; +constexpr uint8_t CMD_MADCTL = 0x36; +constexpr uint8_t CMD_LPM = 0x39; +constexpr uint8_t CMD_DFS = 0x3A; +constexpr uint8_t CMD_GATE_LINE = 0xB0; + +// Each RAM byte holds 4 source pixels of 2 adjacent gate lines and each column address spans 3 bytes. +constexpr uint32_t BYTES_PER_COLUMN = 3; + +struct St7305Internal { + Device* spi_controller; + esp_lcd_panel_io_handle_t io_handle; + // Given from ISR context when a queued SPI transfer completes, so draw_bitmap() can return + // only after the panel buffer is free to be overwritten. + SemaphoreHandle_t draw_done_semaphore; + uint8_t* panel_buffer; + uint32_t row_bytes; + uint32_t row_count; +}; + +struct InitCommand { + uint8_t cmd; + uint8_t data[10]; + uint8_t data_size; + uint16_t delay_ms; +}; + +// Vendor sequence for the 2.9" panel. Gate line count, column and row addresses depend on the +// resolution and are sent separately. +static const InitCommand INIT_COMMANDS[] = { + {0xD6, {0x13, 0x02}, 2, 0}, // NVM load control + {0xD1, {0x01}, 1, 0}, // Booster enable + {0xC0, {0x08, 0x06}, 2, 0}, // Gate voltage + {0xC1, {0x3C, 0x3E, 0x3C, 0x3C}, 4, 0}, // VSHP + {0xC2, {0x23, 0x21, 0x23, 0x23}, 4, 0}, // VSLP + {0xC4, {0x5A, 0x5C, 0x5A, 0x5A}, 4, 0}, // VSHN + {0xC5, {0x37, 0x35, 0x37, 0x37}, 4, 0}, // VSLN + {0xB2, {0x05}, 1, 0}, // Frame rate control + {0xB3, {0xE5, 0xF6, 0x17, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x71}, 10, 0}, // HPM gate EQ + {0xB4, {0x05, 0x46, 0x77, 0x77, 0x77, 0x77, 0x76, 0x45}, 8, 0}, // LPM gate EQ + {0x62, {0x32, 0x03, 0x1F}, 3, 0}, // Gate timing + {0xB7, {0x13}, 1, 0}, // Source EQ enable +}; + +static const InitCommand INIT_COMMANDS_SLEEP_OUT[] = { + {CMD_SLPOUT, {}, 0, 100}, + {0xC9, {0x00}, 1, 0}, // Source voltage select + {CMD_MADCTL, {0x00}, 1, 0}, + {CMD_DFS, {0x11}, 1, 0}, // Data format select + {0xB9, {0x20}, 1, 0}, // Gamma mode + {0xB8, {0x29}, 1, 0}, // Panel setting + {0xD0, {0xFF}, 1, 0}, // Auto power down +}; + +static IRAM_ATTR bool on_color_trans_done(esp_lcd_panel_io_handle_t, esp_lcd_panel_io_event_data_t*, void* user_ctx) { + auto* internal = static_cast(user_ctx); + BaseType_t high_task_woken = pdFALSE; + xSemaphoreGiveFromISR(internal->draw_done_semaphore, &high_task_woken); + return high_task_woken == pdTRUE; +} + +static int pin_or_unused(const struct GpioPinSpec& pin) { + return pin.gpio_controller == nullptr ? -1 : static_cast(pin.pin); +} + +static bool send_command(St7305Internal* internal, uint8_t cmd, const uint8_t* data, size_t data_size) { + return esp_lcd_panel_io_tx_param(internal->io_handle, cmd, data, data_size) == ESP_OK; +} + +static bool send_commands(St7305Internal* internal, const InitCommand* commands, size_t count) { + for (size_t i = 0; i < count; i++) { + if (!send_command(internal, commands[i].cmd, commands[i].data_size > 0 ? commands[i].data : nullptr, commands[i].data_size)) { + LOG_E(TAG, "Failed to send command 0x%02X", commands[i].cmd); + return false; + } + if (commands[i].delay_ms > 0) { + vTaskDelay(pdMS_TO_TICKS(commands[i].delay_ms)); + } + } + return true; +} + +static bool send_address_window(St7305Internal* internal, const St7305Config* config) { + const uint8_t caset[] = { + config->column_offset, + static_cast(config->column_offset + internal->row_bytes / BYTES_PER_COLUMN - 1) + }; + const uint8_t raset[] = {0x00, static_cast(internal->row_count - 1)}; + return send_command(internal, CMD_CASET, caset, sizeof(caset)) && + send_command(internal, CMD_RASET, raset, sizeof(raset)); +} + +static void perform_hardware_reset(const St7305Config* config) { + int pin = pin_or_unused(config->pin_reset); + if (pin < 0) { + return; + } + + gpio_config_t io_conf = { + .pin_bit_mask = 1ULL << pin, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&io_conf); + + // Reset is active-low + gpio_set_level(static_cast(pin), 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(static_cast(pin), 1); + vTaskDelay(pdMS_TO_TICKS(10)); +} + +static bool send_init_sequence(St7305Internal* internal, const St7305Config* config) { + const uint8_t gate_lines = static_cast(config->horizontal_resolution / 4); + return send_commands(internal, INIT_COMMANDS, std::size(INIT_COMMANDS)) && + send_command(internal, CMD_GATE_LINE, &gate_lines, 1) && + send_commands(internal, INIT_COMMANDS_SLEEP_OUT, std::size(INIT_COMMANDS_SLEEP_OUT)) && + send_address_window(internal, config) && + send_command(internal, CMD_LPM, nullptr, 0) && + send_command(internal, config->invert_color ? CMD_INVON : CMD_INVOFF, nullptr, 0); +} + +// region Driver lifecycle + +static void free_internal(St7305Internal* internal) { + if (internal->io_handle != nullptr) { + esp_lcd_panel_io_del(internal->io_handle); + } + if (internal->draw_done_semaphore != nullptr) { + vSemaphoreDelete(internal->draw_done_semaphore); + } + heap_caps_free(internal->panel_buffer); + free(internal); +} + +static error_t start(Device* device) { + auto* parent = device_get_parent(device); + check(device_get_type(parent) == &SPI_CONTROLLER_TYPE); + + const auto* spi_config = static_cast(parent->config); + const auto* config = GET_CONFIG(device); + + // Gate pairs are addressed by an 8-bit row address + if (config->horizontal_resolution == 0 || config->horizontal_resolution % 4 != 0 || config->horizontal_resolution > 512) { + LOG_E(TAG, "Invalid horizontal resolution %u (must be a multiple of 4, maximum 512)", config->horizontal_resolution); + return ERROR_NOT_SUPPORTED; + } + + struct GpioPinSpec cs_pin; + if (esp32_spi_get_cs_pin(device, &cs_pin) != ERROR_NONE) { + LOG_E(TAG, "Failed to resolve CS pin"); + return ERROR_RESOURCE; + } + + auto* internal = static_cast(calloc(1, sizeof(St7305Internal))); + if (internal == nullptr) { + return ERROR_OUT_OF_MEMORY; + } + + internal->spi_controller = parent; + internal->row_count = config->horizontal_resolution / 2; + const uint32_t source_bytes = (config->vertical_resolution + 3) / 4; + internal->row_bytes = (source_bytes + BYTES_PER_COLUMN - 1) / BYTES_PER_COLUMN * BYTES_PER_COLUMN; + + internal->panel_buffer = static_cast(heap_caps_malloc(internal->row_bytes * internal->row_count, MALLOC_CAP_DMA)); + internal->draw_done_semaphore = xSemaphoreCreateBinary(); + if (internal->panel_buffer == nullptr || internal->draw_done_semaphore == nullptr) { + free_internal(internal); + return ERROR_OUT_OF_MEMORY; + } + + esp_lcd_panel_io_spi_config_t io_config = { + .cs_gpio_num = static_cast(pin_or_unused(cs_pin)), + .dc_gpio_num = static_cast(pin_or_unused(config->pin_dc)), + .spi_mode = 0, + .pclk_hz = config->pixel_clock_hz, + .trans_queue_depth = 10, + .on_color_trans_done = on_color_trans_done, + .user_ctx = internal, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + .cs_ena_pretrans = 0, + .cs_ena_posttrans = 0, + .flags = { + .dc_high_on_cmd = 0, + .dc_low_on_data = 0, + .dc_low_on_param = 0, + .octal_mode = 0, + .quad_mode = 0, + .sio_mode = 0, + .psram_dma_direct = 0, + .lsb_first = 0, + .cs_high_active = 0, + }, + }; + + esp_err_t ret = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)spi_config->host, &io_config, &internal->io_handle); + if (ret != ESP_OK) { + LOG_E(TAG, "Failed to create panel IO: %s", esp_err_to_name(ret)); + free_internal(internal); + return ERROR_RESOURCE; + } + + spi_controller_lock(internal->spi_controller); + perform_hardware_reset(config); + bool ok = send_init_sequence(internal, config) && + send_command(internal, CMD_DISPON, nullptr, 0); + spi_controller_unlock(internal->spi_controller); + + if (!ok) { + LOG_E(TAG, "Failed to bring up panel"); + free_internal(internal); + return ERROR_RESOURCE; + } + + device_set_driver_data(device, internal); + return ERROR_NONE; +} + +static error_t stop(Device* device) { + auto* internal = static_cast(device_get_driver_data(device)); + + spi_controller_lock(internal->spi_controller); + esp_err_t ret = esp_lcd_panel_io_del(internal->io_handle); + spi_controller_unlock(internal->spi_controller); + if (ret != ESP_OK) { + LOG_E(TAG, "Failed to delete panel IO"); + return ERROR_RESOURCE; + } + internal->io_handle = nullptr; + + free_internal(internal); + device_set_driver_data(device, nullptr); + return ERROR_NONE; +} + +// endregion + +// region DisplayApi + +static error_t st7305_reset(Device* device) { + auto* internal = static_cast(device_get_driver_data(device)); + spi_controller_lock(internal->spi_controller); + perform_hardware_reset(GET_CONFIG(device)); + spi_controller_unlock(internal->spi_controller); + return ERROR_NONE; +} + +static error_t st7305_init(Device* device) { + auto* internal = static_cast(device_get_driver_data(device)); + spi_controller_lock(internal->spi_controller); + bool ok = send_init_sequence(internal, GET_CONFIG(device)); + spi_controller_unlock(internal->spi_controller); + return ok ? ERROR_NONE : ERROR_RESOURCE; +} + +// Converts the row-major MSB-first 1bpp frame (bit 1 = white) into the panel's RAM layout: +// RAM row r holds gate lines x = 2r and 2r + 1, and each byte packs 4 vertically adjacent pixels of +// both lines, interleaved MSB-first as (y, 2r), (y, 2r + 1), (y + 1, 2r), ... with bit 1 = black. +static void convert_frame(const St7305Internal* internal, const St7305Config* config, const uint8_t* src) { + const uint32_t width = config->horizontal_resolution; + const uint32_t height = config->vertical_resolution; + const uint32_t src_stride = (width + 7) / 8; + + memset(internal->panel_buffer, 0, internal->row_bytes * internal->row_count); + + for (uint32_t y = 0; y < height; y++) { + const uint32_t panel_y = config->mirror_y ? height - 1 - y : y; + const uint8_t* src_row = src + y * src_stride; + for (uint32_t x = 0; x < width; x++) { + if (src_row[x / 8] & (0x80 >> (x % 8))) { + continue; + } + const uint32_t panel_x = config->mirror_x ? width - 1 - x : x; + const uint32_t index = (panel_x / 2) * internal->row_bytes + panel_y / 4; + internal->panel_buffer[index] |= 0x80 >> ((panel_y % 4) * 2 + (panel_x % 2)); + } + } +} + +static error_t st7305_draw_bitmap(Device* device, int32_t x_start, int32_t y_start, int32_t x_end, int32_t y_end, const void* color_data) { + auto* internal = static_cast(device_get_driver_data(device)); + const auto* config = GET_CONFIG(device); + + if (x_start != 0 || y_start != 0 || x_end != config->horizontal_resolution || y_end != config->vertical_resolution) { + LOG_W(TAG, "draw_bitmap: only full-frame draws are supported (got %ld,%ld..%ld,%ld)", (long)x_start, (long)y_start, (long)x_end, (long)y_end); + return ERROR_NOT_SUPPORTED; + } + + spi_controller_lock(internal->spi_controller); + // Sending the address window first waits for in-flight chunks of a previous failed transfer that still read panel_buffer + bool ok = send_address_window(internal, config); + if (ok) { + convert_frame(internal, config, static_cast(color_data)); + // Drain any signal left over from earlier command transfers, which complete through the same callback + xSemaphoreTake(internal->draw_done_semaphore, 0); + ok = esp_lcd_panel_io_tx_color(internal->io_handle, CMD_RAMWR, internal->panel_buffer, internal->row_bytes * internal->row_count) == ESP_OK; + } + if (ok) { + xSemaphoreTake(internal->draw_done_semaphore, portMAX_DELAY); + } + spi_controller_unlock(internal->spi_controller); + return ok ? ERROR_NONE : ERROR_RESOURCE; +} + +static error_t st7305_invert_color(Device* device, bool invert_color_data) { + auto* internal = static_cast(device_get_driver_data(device)); + spi_controller_lock(internal->spi_controller); + bool ok = send_command(internal, invert_color_data ? CMD_INVON : CMD_INVOFF, nullptr, 0); + spi_controller_unlock(internal->spi_controller); + return ok ? ERROR_NONE : ERROR_RESOURCE; +} + +static error_t st7305_disp_on_off(Device* device, bool on_off) { + auto* internal = static_cast(device_get_driver_data(device)); + spi_controller_lock(internal->spi_controller); + bool ok = send_command(internal, on_off ? CMD_DISPON : CMD_DISPOFF, nullptr, 0); + spi_controller_unlock(internal->spi_controller); + return ok ? ERROR_NONE : ERROR_RESOURCE; +} + +static DisplayColorFormat st7305_get_color_format(Device*) { + return DISPLAY_COLOR_FORMAT_MONOCHROME; +} + +static uint16_t st7305_get_resolution_x(Device* device) { + return GET_CONFIG(device)->horizontal_resolution; +} + +static uint16_t st7305_get_resolution_y(Device* device) { + return GET_CONFIG(device)->vertical_resolution; +} + +// endregion + +static error_t st7305_get_backlight(Device* device, Device** backlight) { + auto* configured_backlight = GET_CONFIG(device)->backlight; + if (configured_backlight == nullptr) { + return ERROR_NOT_SUPPORTED; + } + *backlight = configured_backlight; + return ERROR_NONE; +} + +static const DisplayApi st7305_display_api = { + .capabilities = DISPLAY_CAPABILITY_INVERT_COLOR | DISPLAY_CAPABILITY_ON_OFF | DISPLAY_CAPABILITY_REQUIRES_FULL_FRAME | DISPLAY_CAPABILITY_PREFER_EXTERNAL_RAM, + .reset = st7305_reset, + .init = st7305_init, + .draw_bitmap = st7305_draw_bitmap, + .clear = nullptr, + .refresh = nullptr, + .mirror = nullptr, + .swap_xy = nullptr, + .get_swap_xy = nullptr, + .get_mirror_x = nullptr, + .get_mirror_y = nullptr, + .set_gap = nullptr, + .get_gap_x = nullptr, + .get_gap_y = nullptr, + .invert_color = st7305_invert_color, + .disp_on_off = st7305_disp_on_off, + .disp_sleep = nullptr, + .get_color_format = st7305_get_color_format, + .get_resolution_x = st7305_get_resolution_x, + .get_resolution_y = st7305_get_resolution_y, + .get_frame_buffer = nullptr, + .get_frame_buffer_count = nullptr, + .get_backlight = st7305_get_backlight, + .has_capability = nullptr, +}; + +Driver st7305_driver = { + .name = "st7305", + .compatible = (const char*[]) {"sitronix,st7305", nullptr}, + .start_device = start, + .stop_device = stop, + .api = &st7305_display_api, + .device_type = &DISPLAY_TYPE, + .owner = &st7305_module, + .internal = nullptr +}; diff --git a/Modules/lvgl-module/source/devices/keyboard.cpp b/Modules/lvgl-module/source/devices/keyboard.cpp index b23fc385e..6b576afd6 100644 --- a/Modules/lvgl-module/source/devices/keyboard.cpp +++ b/Modules/lvgl-module/source/devices/keyboard.cpp @@ -59,6 +59,8 @@ static uint32_t codepoint_to_lv_key(uint32_t key) { case CODEPOINT_ARROW_DOWN: return LV_KEY_NEXT; case CODEPOINT_HOME: return LV_KEY_HOME; case CODEPOINT_END: return LV_KEY_END; + case CODEPOINT_YES: return LV_KEY_ENTER; + case CODEPOINT_NO: return LV_KEY_ESC; default: return key; } } diff --git a/Modules/lvgl-module/source/themes/lv_theme_material.c b/Modules/lvgl-module/source/themes/lv_theme_material.c index 88b0a58fd..bb95d91f8 100644 --- a/Modules/lvgl-module/source/themes/lv_theme_material.c +++ b/Modules/lvgl-module/source/themes/lv_theme_material.c @@ -670,13 +670,13 @@ static bool config_equals(const lv_theme_material_config_t * a, const lv_theme_m static void style_init(my_theme_t * theme) { static const lv_style_prop_t trans_state_enter_props[] = { - LV_STYLE_BG_COLOR, LV_STYLE_BG_OPA, LV_STYLE_BORDER_COLOR, LV_STYLE_TEXT_COLOR, LV_STYLE_OUTLINE_WIDTH, LV_STYLE_OUTLINE_OPA, + LV_STYLE_BG_COLOR, LV_STYLE_BG_OPA, LV_STYLE_BORDER_COLOR, LV_STYLE_TEXT_COLOR, 0 }; lv_style_transition_dsc_init(&theme->trans_state_enter, trans_state_enter_props, lv_anim_path_ease_out, MOTION_DURATION_SHORT, 0, NULL); static const lv_style_prop_t trans_state_exit_props[] = { - LV_STYLE_BG_COLOR, LV_STYLE_BG_OPA, LV_STYLE_BORDER_COLOR, LV_STYLE_TEXT_COLOR, LV_STYLE_OUTLINE_WIDTH, LV_STYLE_OUTLINE_OPA, + LV_STYLE_BG_COLOR, LV_STYLE_BG_OPA, LV_STYLE_BORDER_COLOR, LV_STYLE_TEXT_COLOR, 0 }; lv_style_transition_dsc_init(&theme->trans_state_exit, trans_state_exit_props, lv_anim_path_ease_out, MOTION_DURATION_SHORT, 70, NULL); diff --git a/Modules/lvgl-module/themes/material.lss b/Modules/lvgl-module/themes/material.lss index e955685d5..cac27a03c 100644 --- a/Modules/lvgl-module/themes/material.lss +++ b/Modules/lvgl-module/themes/material.lss @@ -458,14 +458,14 @@ // ============================================================ @transition state-enter { - props: bgColor, bgOpa, borderColor, textColor, outlineWidth, outlineOpa; + props: bgColor, bgOpa, borderColor, textColor; path: ease-out; duration: @motion-duration-short; delay: 0; } @transition state-exit { - props: bgColor, bgOpa, borderColor, textColor, outlineWidth, outlineOpa; + props: bgColor, bgOpa, borderColor, textColor; path: ease-out; duration: @motion-duration-short; delay: 70; diff --git a/Tactility/Kconfig b/Tactility/Kconfig index 2c7866f10..d82244c4f 100644 --- a/Tactility/Kconfig +++ b/Tactility/Kconfig @@ -21,24 +21,12 @@ menu "Tactility App" help The name of the directory in Devices/ See https://docs.tactilityproject.org for formatting guidance. - config TT_LAUNCHER_APP_ID - string "Launcher App ID" - default "tactility.launcher" - help - The applications that gives access to other application. - This is the first thing that starts after the boot screen. - The user can override it with a boot.properties file config TT_FONT_DEFAULT_SIZE int "Default font size" default 14 range 10 32 help Default text font size in pixels. Other text and icon font sizes are derived from it. - config TT_LVGL_STATUSBAR_COLORS_INVERTED - bool "Statusbar colors inverted" - default n - help - Invert the statusbar's foreground/background colors config TT_AUTO_START_APP_ID string "Auto Start App ID" default "" diff --git a/Tactility/Private/Tactility/app/wifimanage/Bindings.h b/Tactility/Private/Tactility/app/wifimanage/Bindings.h index 2cc612d74..0bb17debc 100644 --- a/Tactility/Private/Tactility/app/wifimanage/Bindings.h +++ b/Tactility/Private/Tactility/app/wifimanage/Bindings.h @@ -9,6 +9,7 @@ typedef void (*OnConnectSsid)(const std::string& ssid); typedef void (*OnDisconnect)(); typedef void (*OnShowApSettings)(const std::string& ssid); typedef void (*OnConnectToHidden)(); +typedef void (*OnRefresh)(); struct Bindings{ OnWifiToggled onWifiToggled; @@ -16,6 +17,7 @@ struct Bindings{ OnDisconnect onDisconnect; OnShowApSettings onShowApSettings; OnConnectToHidden onConnectToHidden; + OnRefresh onRefresh; }; } // namespace diff --git a/Tactility/Private/Tactility/app/wifimanage/State.h b/Tactility/Private/Tactility/app/wifimanage/State.h index ca0b4b542..48f9b5fd8 100644 --- a/Tactility/Private/Tactility/app/wifimanage/State.h +++ b/Tactility/Private/Tactility/app/wifimanage/State.h @@ -17,6 +17,7 @@ class State final { RecursiveMutex mutex; bool scanning = false; bool scannedAfterRadioOn = false; + bool listRefreshRequested = true; WifiRadioState radioState = WIFI_RADIO_STATE_OFF; WifiStationState stationState = WIFI_STATION_STATE_DISCONNECTED; std::string connectionTarget; @@ -31,6 +32,11 @@ class State final { bool hasScannedAfterRadioOn() const { return scannedAfterRadioOn; } + /** The next finished scan updates the AP records and rebuilds the network list */ + void requestListRefresh(); + /** @return true if a list refresh was requested, clearing the request */ + bool takeListRefreshRequest(); + void setRadioState(WifiRadioState state); WifiRadioState getRadioState() const; diff --git a/Tactility/Private/Tactility/app/wifimanage/View.h b/Tactility/Private/Tactility/app/wifimanage/View.h index 80bcce5cf..2e1c0162e 100644 --- a/Tactility/Private/Tactility/app/wifimanage/View.h +++ b/Tactility/Private/Tactility/app/wifimanage/View.h @@ -17,25 +17,29 @@ class View final { lv_obj_t* enable_switch = nullptr; lv_obj_t* enable_on_boot_switch = nullptr; lv_obj_t* scanning_spinner = nullptr; + lv_obj_t* refresh_button = nullptr; lv_obj_t* networks_list = nullptr; lv_obj_t* connect_to_hidden = nullptr; void updateWifiToggle(); void updateEnableOnBootToggle(); void updateScanning(); + void updateRefreshButton(); void updateNetworkList(); void updateConnectToHidden(); void createSsidListItem(lv_obj_t* list, const WifiApRecord& record, bool isConnecting, size_t index); static void showDetails(lv_event_t* event); static void connect(lv_event_t* event); + static void onRefreshPressed(lv_event_t* event); public: View(Bindings* bindings, State* state) : bindings(bindings), state(state) {} void init(uint32_t appInstanceId, lv_obj_t* parent); - void update(); + /** @param[in] rebuildList recreates the network list, which resets the focused item */ + void update(bool rebuildList); /** Called when this window's widgets have been (or are about to be) deleted out from under * it - see WindowDestroyWidgetsFn. Only nulls out pointers; must stay lock-free. */ void reset(); diff --git a/Tactility/Source/app/boot/BootInit.cpp b/Tactility/Source/app/boot/BootInit.cpp index 96ffd0859..520ab487a 100644 --- a/Tactility/Source/app/boot/BootInit.cpp +++ b/Tactility/Source/app/boot/BootInit.cpp @@ -41,6 +41,7 @@ namespace tt::app::boot { constexpr auto* TAG = "Boot"; +constexpr auto* DEFAULT_LAUNCHER_ID = "tactility.launcher"; namespace { @@ -153,20 +154,20 @@ std::string getLauncherAppId() { settings::BootSettings boot_properties; // When boot.properties hasn't been overridden, return default if (!settings::loadBootSettings(boot_properties)) { - return CONFIG_TT_LAUNCHER_APP_ID; + return DEFAULT_LAUNCHER_ID; } // When boot properties didn't specify an override, return default if (boot_properties.launcherAppId.empty()) { LOG_E(TAG, "Failed to load launcher configuration, or launcher not configured"); - return CONFIG_TT_LAUNCHER_APP_ID; + return DEFAULT_LAUNCHER_ID; } // If the app in the boot.properties does not exist, return default AppManifest manifest; if (app_manager_find_manifest(boot_properties.launcherAppId.c_str(), &manifest) != ERROR_NONE) { LOG_E(TAG, "Launcher app %s not found", boot_properties.launcherAppId.c_str()); - return CONFIG_TT_LAUNCHER_APP_ID; + return DEFAULT_LAUNCHER_ID; } // The boot.properties launcher app id is valid diff --git a/Tactility/Source/app/files/SupportedFiles.cpp b/Tactility/Source/app/files/SupportedFiles.cpp index 9d914e249..24031b696 100644 --- a/Tactility/Source/app/files/SupportedFiles.cpp +++ b/Tactility/Source/app/files/SupportedFiles.cpp @@ -1,10 +1,34 @@ #include -#include + +#include +#include +#include namespace tt::app::files { constexpr auto* TAG = "Files"; +constexpr auto text_file_extensions = std::to_array({ + ".txt", ".md", ".rst", ".adoc", ".csv", ".tsv", ".log", ".diff", ".patch", + + ".sh", ".bash", + ".awk", ".sed", ".tcl", + ".c", ".h", + ".py", ".lua", ".js", + + ".yaml", ".yml", + ".json", ".json5", + ".toml", + ".ini", ".cfg", ".conf", ".config", + ".properties", + ".env", + ".gitignore", ".gitattributes", + + ".html", ".htm", + ".css", ".scss", ".sass", ".less", + ".xml", ".svg", +}); + bool isSupportedAppFile(const std::string& filename) { return filename.ends_with(".app"); } @@ -16,14 +40,9 @@ bool isSupportedImageFile(const std::string& filename) { bool isSupportedTextFile(const std::string& filename) { std::string filename_lower = string::lowercase(filename); - return filename_lower.ends_with(".txt") || - filename_lower.ends_with(".ini") || - filename_lower.ends_with(".json") || - filename_lower.ends_with(".yaml") || - filename_lower.ends_with(".yml") || - filename_lower.ends_with(".lua") || - filename_lower.ends_with(".js") || - filename_lower.ends_with(".properties"); + return std::ranges::any_of(text_file_extensions, [&filename_lower](std::basic_string_view extension) -> bool { + return filename_lower.ends_with(extension); + }); } } // namespace tt::app::filebrowser diff --git a/Tactility/Source/app/files/View.cpp b/Tactility/Source/app/files/View.cpp index 3ae28c6d7..e0c4879db 100644 --- a/Tactility/Source/app/files/View.cpp +++ b/Tactility/Source/app/files/View.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include #include diff --git a/Tactility/Source/app/notes/Notes.cpp b/Tactility/Source/app/notes/Notes.cpp index 7d40de977..2e2a16759 100644 --- a/Tactility/Source/app/notes/Notes.cpp +++ b/Tactility/Source/app/notes/Notes.cpp @@ -206,9 +206,6 @@ void createWidgets(lv_obj_t* parent, void* userData) { lv_obj_set_width(ctx->uiNoteText, LV_PCT(100)); lv_obj_set_height(ctx->uiNoteText, LV_PCT(86)); lv_textarea_set_password_mode(ctx->uiNoteText, false); - if (lv_display_get_color_format(lv_obj_get_display(parent)) != LV_COLOR_FORMAT_L8) { - lv_obj_set_style_bg_color(ctx->uiNoteText, lv_color_hex(0x262626), LV_PART_MAIN); - } lv_textarea_set_placeholder_text(ctx->uiNoteText, "Notes..."); lv_obj_add_event_cb(ctx->uiNoteText, onNoteTextPressed, LV_EVENT_PRESSED, ctx); @@ -217,13 +214,8 @@ void createWidgets(lv_obj_t* parent, void* userData) { lv_obj_set_flex_align(footer, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); // Shows the screen background lv_obj_set_style_bg_opa(footer, LV_OPA_TRANSP, LV_PART_MAIN); - if (lv_display_get_color_format(lv_obj_get_display(parent)) == LV_COLOR_FORMAT_L8) { - lv_obj_set_style_border_width(footer, 1, LV_PART_MAIN); - lv_obj_set_style_border_color(footer, lv_theme_get_color_secondary(footer), LV_PART_MAIN); - lv_obj_set_style_border_side(footer, LV_BORDER_SIDE_TOP, LV_PART_MAIN); - } else { - lv_obj_set_style_border_width(footer, 0, LV_PART_MAIN); - } + lv_obj_set_style_border_width(footer, 0, LV_PART_MAIN); + lv_obj_set_width(footer, LV_PCT(100)); lv_obj_set_height(footer, LV_PCT(14)); lv_obj_set_style_pad_all(footer, 0, LV_PART_MAIN); diff --git a/Tactility/Source/app/terminal/main.cpp b/Tactility/Source/app/terminal/main.cpp index 81dcebfd0..00509c75e 100644 --- a/Tactility/Source/app/terminal/main.cpp +++ b/Tactility/Source/app/terminal/main.cpp @@ -120,9 +120,15 @@ int main(int argc, char* argv[]) { return 0; } +#ifdef PLATFORM_ESP + constexpr auto memory_sufficient = memory_external_total() > 0; +#else + constexpr auto memory_sufficient = true; +#endif + // The canvas holds a full frame, which needs external RAM on larger displays. const bool useLvgl = module_is_started(&lvgl_module) && - memory_external_total() > 0 && + memory_sufficient && !hasArgument(argc, argv, "--no-lvgl"); if (useLvgl) { diff --git a/Tactility/Source/app/wifimanage/State.cpp b/Tactility/Source/app/wifimanage/State.cpp index a6a0986c3..104fde335 100644 --- a/Tactility/Source/app/wifimanage/State.cpp +++ b/Tactility/Source/app/wifimanage/State.cpp @@ -20,6 +20,20 @@ void State::setRadioState(WifiRadioState state) { mutex.unlock(); } +void State::requestListRefresh() { + mutex.lock(); + listRefreshRequested = true; + mutex.unlock(); +} + +bool State::takeListRefreshRequest() { + mutex.lock(); + bool result = listRefreshRequested; + listRefreshRequested = false; + mutex.unlock(); + return result; +} + WifiRadioState State::getRadioState() const { mutex.lock(); auto result = radioState; diff --git a/Tactility/Source/app/wifimanage/View.cpp b/Tactility/Source/app/wifimanage/View.cpp index bf5e348f4..98672b3dc 100644 --- a/Tactility/Source/app/wifimanage/View.cpp +++ b/Tactility/Source/app/wifimanage/View.cpp @@ -109,6 +109,12 @@ void View::showDetails(lv_event_t* event) { } } +void View::onRefreshPressed(lv_event_t* event) { + auto* self = static_cast(lv_event_get_user_data(event)); + self->state->requestListRefresh(); + self->bindings->onRefresh(); +} + /** Creates a title with a card below it, and returns the list in the card */ static lv_obj_t* createSection(lv_obj_t* parent, const char* title) { auto* label = lv_label_create(parent); @@ -257,6 +263,10 @@ void View::updateScanning() { } } +void View::updateRefreshButton() { + lv_obj_set_hidden(refresh_button, state->getRadioState() != WIFI_RADIO_STATE_ON); +} + void View::updateWifiToggle() { lv_obj_clear_state(enable_switch, LV_STATE_ANY); switch (state->getRadioState()) { @@ -308,6 +318,8 @@ void View::init(uint32_t newAppInstanceId, lv_obj_t* parent) { scanning_spinner = lvgl_toolbar_add_spinner_action(toolbar); + refresh_button = lvgl_toolbar_add_image_button_action(toolbar, LV_SYMBOL_REFRESH, onRefreshPressed, this); + enable_switch = lvgl_toolbar_add_switch_action(toolbar); lv_obj_add_event_cb(enable_switch, onEnableSwitchChanged, LV_EVENT_VALUE_CHANGED, bindings); @@ -320,14 +332,17 @@ void View::init(uint32_t newAppInstanceId, lv_obj_t* parent) { lv_obj_set_style_border_width(networks_list, 0, LV_STATE_DEFAULT); } -void View::update() { +void View::update(bool rebuildList) { if (root == nullptr) { // Buried (or not yet built) - see reset(). return; } updateWifiToggle(); updateScanning(); - updateNetworkList(); + updateRefreshButton(); + if (rebuildList) { + updateNetworkList(); + } updateConnectToHidden(); } @@ -336,6 +351,7 @@ void View::reset() { enable_switch = nullptr; enable_on_boot_switch = nullptr; scanning_spinner = nullptr; + refresh_button = nullptr; networks_list = nullptr; connect_to_hidden = nullptr; } diff --git a/Tactility/Source/app/wifimanage/WifiManage.cpp b/Tactility/Source/app/wifimanage/WifiManage.cpp index de009a531..ed84168bc 100644 --- a/Tactility/Source/app/wifimanage/WifiManage.cpp +++ b/Tactility/Source/app/wifimanage/WifiManage.cpp @@ -125,13 +125,29 @@ static void onConnectToHidden() { wificonnect::start(); } -void updateView(Context* ctx) { +/** Starting a scan doesn't block, so this runs directly on the LVGL task. */ +static void onRefresh() { + Device* wifi_device = nullptr; + if (device_get_first_by_type(&WIFI_TYPE, &wifi_device) != ERROR_NONE) { + LOG_W(TAG, "No WiFi device found"); + return; + } + if (!wifi_is_scanning(wifi_device)) { + error_t result = wifi_scan(wifi_device); + if (result != ERROR_NONE) { + LOG_E(TAG, "Failed to start scan (%s)", error_to_string(result)); + } + } + device_put(wifi_device); +} + +void updateView(Context* ctx, bool rebuildList) { // Same lock order as createWidgets() (called with the LVGL lock already held, per the // window-manager's WindowCreateWidgetsFn contract, then acquiring ctx->mutex) - acquiring // these in the opposite order here would deadlock against a concurrent createWidgets() call. lvgl_lock(); ctx->lock(); - ctx->view.update(); + ctx->view.update(rebuildList); ctx->unlock(); lvgl_unlock(); } @@ -162,16 +178,28 @@ void scanIfIdle(Context* ctx) { void onWifiEvent(Context* ctx, WifiEvent event) { updateStateFromDevice(ctx); LOG_I(TAG, "Update with radio state %d, station state %d", (int)ctx->state.getRadioState(), (int)ctx->state.getStationState()); + // Rebuilding the network list resets the keyboard focus, so it only happens for scans that were + // requested by this app, radio state changes and connection changes. + bool rebuild_list = false; switch (event.type) { case WIFI_EVENT_TYPE_SCAN_STARTED: ctx->state.setScanning(true); break; case WIFI_EVENT_TYPE_SCAN_FINISHED: ctx->state.setScanning(false); - ctx->state.updateApRecords(ctx->wifiDevice); + if (ctx->state.takeListRefreshRequest()) { + ctx->state.updateApRecords(ctx->wifiDevice); + rebuild_list = true; + } + break; + case WIFI_EVENT_TYPE_STATION_STATE_CHANGED: + case WIFI_EVENT_TYPE_STATION_CONNECTION_RESULT: + rebuild_list = true; break; case WIFI_EVENT_TYPE_RADIO_STATE_CHANGED: + rebuild_list = true; if (event.radio_state == WIFI_RADIO_STATE_ON) { + ctx->state.requestListRefresh(); scanIfIdle(ctx); } break; @@ -179,7 +207,7 @@ void onWifiEvent(Context* ctx, WifiEvent event) { break; } - updateView(ctx); + updateView(ctx, rebuild_list); } void createWidgets(lv_obj_t* parent, void* userData) { @@ -206,7 +234,8 @@ int32_t appMain(int argc, char* argv[]) { .onConnectSsid = onConnect, .onDisconnect = onDisconnect, .onShowApSettings = onShowApSettings, - .onConnectToHidden = onConnectToHidden + .onConnectToHidden = onConnectToHidden, + .onRefresh = onRefresh }; TaskEventGroup event_group {}; @@ -235,7 +264,6 @@ int32_t appMain(int argc, char* argv[]) { if (ctx.wifiDevice != nullptr) { updateStateFromDevice(&ctx); ctx.state.setScanning(wifi_is_scanning(ctx.wifiDevice)); - ctx.state.updateApRecords(ctx.wifiDevice); } WindowId window = window_manager_create_ext(appInstanceId, createWidgets, destroyWidgets, &ctx); @@ -262,7 +290,9 @@ int32_t appMain(int argc, char* argv[]) { ctx.wifiDevice = retry_device; updateStateFromDevice(&ctx); ctx.state.setScanning(wifi_is_scanning(ctx.wifiDevice)); - ctx.state.updateApRecords(ctx.wifiDevice); + if (ctx.state.getRadioState() == WIFI_RADIO_STATE_ON) { + scanIfIdle(&ctx); + } ctx.needsRefresh = true; } else { device_put(retry_device); @@ -290,7 +320,7 @@ int32_t appMain(int argc, char* argv[]) { } if (ctx.needsRefresh.exchange(false)) { - updateView(&ctx); + updateView(&ctx, true); } } diff --git a/Tactility/Source/lvgl/Statusbar.cpp b/Tactility/Source/lvgl/Statusbar.cpp index e474cae74..9462378be 100644 --- a/Tactility/Source/lvgl/Statusbar.cpp +++ b/Tactility/Source/lvgl/Statusbar.cpp @@ -30,12 +30,6 @@ namespace tt::lvgl { -#if defined(CONFIG_TT_LVGL_STATUSBAR_COLORS_INVERTED) && CONFIG_TT_LVGL_STATUSBAR_COLORS_INVERTED -constexpr bool STATUSBAR_COLORS_INVERTED = true; -#else -constexpr bool STATUSBAR_COLORS_INVERTED = false; -#endif - constexpr auto* TAG = "statusbar"; static void onUpdateTime(); diff --git a/TactilityKernel/include/tactility/drivers/backlight.h b/TactilityKernel/include/tactility/drivers/backlight.h index ff6e03baa..8fd254608 100644 --- a/TactilityKernel/include/tactility/drivers/backlight.h +++ b/TactilityKernel/include/tactility/drivers/backlight.h @@ -51,6 +51,7 @@ struct BacklightApi { /** * @brief Gets the minimum brightness level. Setting the brightness to this value turns the backlight off. + * This function is optional. If not present, 0 is assumed as minimum. * @param[in] device the backlight device * @return the minimum brightness level */ @@ -58,6 +59,7 @@ struct BacklightApi { /** * @brief Gets the maximum (full-strength) brightness level. + * This function is optional. If not present, 255 is assumed as maximum. * @param[in] device the backlight device * @return the maximum brightness level */ diff --git a/TactilityKernel/include/tactility/drivers/keyboard.h b/TactilityKernel/include/tactility/drivers/keyboard.h index 98578392d..5d3808fd4 100644 --- a/TactilityKernel/include/tactility/drivers/keyboard.h +++ b/TactilityKernel/include/tactility/drivers/keyboard.h @@ -30,6 +30,10 @@ typedef enum { CODEPOINT_ARROW_DOWN = 0x2193, CODEPOINT_HOME = 0x21F1, CODEPOINT_END = 0x21F2, + /** Confirms an action, for keyboards with a dedicated "yes" key */ + CODEPOINT_YES = 0x2713, + /** Cancels an action, for keyboards with a dedicated "no" key */ + CODEPOINT_NO = 0x2717, /** Moves the focus to the next widget, for devices that can only step through widgets (e.g. an encoder wheel) */ CODEPOINT_FOCUS_NEXT = 0x21E5, /** Moves the focus to the previous widget, for devices that can only step through widgets (e.g. an encoder wheel) */ diff --git a/TactilityKernel/source/drivers/backlight.cpp b/TactilityKernel/source/drivers/backlight.cpp index 4981890cb..392000794 100644 --- a/TactilityKernel/source/drivers/backlight.cpp +++ b/TactilityKernel/source/drivers/backlight.cpp @@ -23,16 +23,18 @@ error_t backlight_get_brightness(Device* device, uint8_t* out_brightness) { uint8_t backlight_get_min_brightness(Device* device) { const auto* driver = device_get_driver(device); - return BACKLIGHT_DRIVER_API(driver)->get_min_brightness(device); + auto* function = BACKLIGHT_DRIVER_API(driver)->get_min_brightness; + return function ? function(device) : 0; } uint8_t backlight_get_max_brightness(Device* device) { const auto* driver = device_get_driver(device); - return BACKLIGHT_DRIVER_API(driver)->get_max_brightness(device); + auto* function = BACKLIGHT_DRIVER_API(driver)->get_max_brightness; + return function ? function(device) : 255; } const DeviceType BACKLIGHT_TYPE { - .name = "backlight" + .name = "backlight", }; } diff --git a/TactilityKernel/source/drivers/gpio_backlight.cpp b/TactilityKernel/source/drivers/gpio_backlight.cpp index 0c91c8768..9884b7084 100644 --- a/TactilityKernel/source/drivers/gpio_backlight.cpp +++ b/TactilityKernel/source/drivers/gpio_backlight.cpp @@ -67,10 +67,6 @@ static error_t gpio_backlight_get_brightness(Device* device, uint8_t* out_bright return ERROR_NONE; } -static uint8_t gpio_backlight_get_min_brightness(Device*) { - return 0; -} - static uint8_t gpio_backlight_get_max_brightness(Device*) { return 1; } @@ -81,7 +77,7 @@ static constexpr BacklightApi GPIO_BACKLIGHT_API = { .set_brightness = gpio_backlight_set_brightness, .set_brightness_default = gpio_backlight_set_brightness_default, .get_brightness = gpio_backlight_get_brightness, - .get_min_brightness = gpio_backlight_get_min_brightness, + .get_min_brightness = nullptr, .get_max_brightness = gpio_backlight_get_max_brightness, }; @@ -132,10 +128,11 @@ Driver gpio_backlight_driver = { .compatible = (const char*[]) { "gpio-backlight", nullptr }, .start_device = start, .stop_device = stop, + .probe = nullptr, .api = &GPIO_BACKLIGHT_API, .device_type = &BACKLIGHT_TYPE, .owner = &kernel_module, - .internal = nullptr + .internal = nullptr, }; } diff --git a/device.py b/device.py index 5a5de77a2..866c10bc6 100755 --- a/device.py +++ b/device.py @@ -140,9 +140,6 @@ def write_tactility_variables(output_file, device_properties: dict, device_id: s output_file.write(f"CONFIG_TT_DEVICE_ID=\"{device_id}\"\n") if device_id == "lilygo-tdeck": output_file.write("CONFIG_TT_TDECK_WORKAROUND=y\n") - # Launcher app id - launcher_app_id = get_property_or_exit(device_properties, "apps.launcherAppId").replace("\"", "\\\"") - output_file.write(f"CONFIG_TT_LAUNCHER_APP_ID=\"{launcher_app_id}\"\n") # Auto start app id auto_start_app_id = get_property_or_none(device_properties, "apps.autoStartAppId") if auto_start_app_id is not None: @@ -288,9 +285,6 @@ def write_lvgl_variables(output_file, device_properties: dict): color_depth = get_property_or_exit(device_properties, "lvgl.colorDepth") output_file.write(f"CONFIG_LV_COLOR_DEPTH={color_depth}\n") output_file.write(f"CONFIG_LV_COLOR_DEPTH_{color_depth}=y\n") - has_statusbar_colors_inverted = get_boolean_property_or_false(device_properties, "lvgl.statusbarColorsInverted") - if has_statusbar_colors_inverted: - output_file.write("CONFIG_TT_LVGL_STATUSBAR_COLORS_INVERTED=y\n") # Tactility uses its own themes (Modules/lvgl-module), and lvgl.theme only selects the default light or dark mode theme = get_property_or_default(device_properties, "lvgl.theme", "DefaultDark") if theme not in ("DefaultDark", "DefaultLight", "Mono"):