Compare commits

..

82 Commits

Author SHA1 Message Date
Adolfo Reyna 982bba70b2 Add simulator MCP screen drawing tools 2026-09-22 16:51:50 -04:00
Adolfo Reyna 9630707b41 Enable MCP tools in POSIX simulator 2026-09-22 16:44:06 -04:00
Adolfo Reyna fd82efe08f Add native macOS simulator app packaging 2026-09-22 16:21:05 -04:00
Ken Van Hoeylandt 72089f74f3 Refactor SDL/FreeRTOS implementation to support macOS simulator properly (#653)
- Run SDL from main() and place FreeRTOS in separate thread. This fixes macOS support.
- Updated GitHub Actions to publish macOS simulator build for testing, updated amd64 to x86_64 for consistent naming.
2026-09-21 19:52:01 -04:00
Adolfo Reyna 89e8baf517 feat(sim): web viewer /sim, touch injection, fast screenshot, SIM_DISPLAY_W/H 2026-09-14 21:43:41 -04:00
Adolfo Reyna 2060095028 feat(sim): web viewer at /sim + touch injection at /api/sim/touch
- GET /sim: live viewer page, 2s screenshot refresh, click-to-touch
- POST /api/sim/touch?x,y,down: injects into sdl-pointer backend,
  auto-releases after 1.5s; simulator-only (404 on ESP32)
- sdl_input: file-scope touch override state with extern C setters
2026-09-14 21:02:54 -04:00
Adolfo Reyna 620d56e19a feat(ui): simplify family UI - hide advanced settings/apps, sane defaults
Hide from Settings: Bluetooth, Development, MCP Screen, Power,
Region & Language, Time & Date (APP_MANIFEST_FLAG_HIDDEN).

Hide from Apps list: App Hub, Chat, I2C Scanner, Notes,
Screenshot, System Info, Web Server.

Defaults: MCP on, WebServer on, America/New_York timezone,
12-hour time format.
2026-09-12 19:45:13 -04:00
Adolfo Reyna a0583e3a30 fix(audio): AudioSettings save() always failed due to inverted path check
getSettingsFilePath() returns true on success, but save() bailed out
when it returned true, so volume/mute settings were never persisted
and always fell back to defaults (50% output) on boot.
2026-09-12 19:45:11 -04:00
Adolfo Reyna 054d1286b2 feat(display): Bible Verse screensaver + longer idle timeouts
- ScreensaverType::BibleVerse launches one.tactility.bibleverse on
  idle (falls back to black when not installed); tap stops the app
  and returns to launcher; 30-minute backlight auto-off stops it too
- Timeout options extended to 15/30 minutes; auto-off 5m -> 30m
- Screensaver dropdown lists Bible Verse
2026-09-12 09:03:37 -04:00
Adolfo Reyna 85da419a98 feat(display): night-dim backlight window for screensaver
- DisplaySettings: nightDimEnabled/startHour/endHour/duty
  (default 22:00-07:00 at duty 20), persisted in display.properties
- Display settings page: Night dim switch + Dim from/until hour
  dropdowns + Dim brightness slider
- DisplayIdle: screensaver runs at the dimmed level when the local
  hour is inside the window (wrap-around aware); falls back to the
  regular duty when time is unknown (year < 2025)
2026-09-12 08:17:52 -04:00
Adolfo Reyna 87c82f5314 feat(files): launch MP3 player from file explorer, 28p header cache
- SupportedFiles: isSupportedAudioFile (.mp3/.wav/.ogg/.flac)
- View::viewFile: audio files start one.tactility.mp3player with
  file=<path> argv (CurrentAppCompat parses key=value pairs)
- es3c28p: add CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT=16 for parity
  with es3c35p
2026-09-12 00:01:13 -04:00
Adolfo Reyna 4b7f82c38f feat(es3c28p,es3c35p): restore ES8311 42dB mic gain, font size, flash script
- Re-apply input-gain-percent (100 = no digital boost) + 42dB HW
  max mapping lost in the upstream merge (was 340953b1/7788415e)
- es3c35p: lvgl.fontSize=16 (text 12/16/22, launcher icons 42)
- Add flash-es3c.sh build+flash helper for 28p/35p
2026-09-11 23:59:03 -04:00
Adolfo Reyna 6d55f0b200 docs: add current firmware upgrade skill 2026-09-10 21:37:12 -04:00
Adolfo Reyna 61fc67cf4c feat: restore MCP settings and board customizations 2026-09-10 21:15:10 -04:00
Adolfo Reyna c8ee763f3d Merge remote-tracking branch 'upstream/main' into feature/es3c28p-es3c35p-modern 2026-09-10 20:57:10 -04:00
Ken Van Hoeylandt 8556103eb1 Implemented multi-binary app packaging (#648) 2026-09-09 20:05:04 +02:00
Adolfo Reyna 9e3dc3dc15 feat(launcher): restore custom SD background experience 2026-09-09 13:41:13 -04:00
Shadowtrance 2496dea5c2 M5Stack PaperS3 display driver improved (#647) 2026-09-08 21:57:41 +02:00
Adolfo Reyna a321bfeb4c fix(es3c35p): align runtime configuration 2026-09-07 23:15:26 -04:00
Adolfo Reyna f95cd7df4c Add ES3C35P board support 2026-09-07 23:04:44 -04:00
Ken Van Hoeylandt 1b16184a72 Multi-platform http server (#646)
- Add server support to `http-module`
- Ensure `DevelopmentService` works on all platforms (including posix)
- Ensure the built-in web server with dashboard works on all platforms (inluding posix). It still has some issues with certain featuers, but the basics work.
2026-09-06 14:16:23 +02:00
Ken Van Hoeylandt a0b2ee7ebc Run executables directly (#645)
- Apps can be launched directly from file paths (including Files app support)
- Added executable detection to identify unsupported or invalid binaries before launch.
- App startup is now streamlined through separate registered-app and direct-execution interfaces.
- Existing app launch points were migrated to the updated startup APIs.
2026-09-04 21:23:08 +02:00
Ken Van Hoeylandt 643cbc3806 Implement posix app loading (#643)
- Added POSIX desktop support for SDK builds, application packaging, and integration testing.
- Added POSIX filesystem partitions and improved application path handling.
- Added simulator support for loading and running applications dynamically.
- Improved simulator task stack handling and display startup reliability.
- Improved simulator display scaling, resizing, high-DPI support, and pointer accuracy.
- Fixed LVGL timers and input polling on POSIX. (fixes simulator with Linux on some Intel graphics platforms)
- Standardized data paths across platforms.
- Logging now works via separate task: this allows apps to write to log without it affecting their stdout (for apps that output text as relevant date for other apps, like the File Selection app)
- Fixes for app stdio
2026-08-31 22:09:04 +02:00
Shadowtrance d3656bcd3d Fixes and improvements (#642) 2026-08-30 23:10:52 +02:00
Ken Van Hoeylandt 7a81b525ed elf_loader update and fix for remote install (#641) 2026-08-30 12:58:48 +02:00
Ken Van Hoeylandt 6e5e35610b Implement app streams: stdio for apps (#640)
Implement file IO for applications to facilitate text input/output capturing.

Apps can now launch apps and:
- Read their stdio output
- Write to their stdio input
2026-08-30 12:07:40 +02:00
Ken Van Hoeylandt 64fb1a9f52 display backlight and bluetooth reference counting (#639) 2026-08-29 23:37:31 +02:00
Ken Van Hoeylandt 19b11eb9a8 Remove TactilityC and Firmware subprojects (#638)
- Removed TactilityC, moved its symbols to existing modules and several new ones (pthread-module, c-symbols-module, cpp-symbols-module, posix-symbols-module, freertos-module).
- Removed Firmware subproject and moved main() into Tactility subproject.
- Strengthened application archive, path, version, stack-size, and device validation.
- Moved symbol resolution for elf_loader to app-esp32-module.
- Improved `struct Module` declarations and made module and symbol definitions in modules more consistent.
- Removed old http download code from Tactility subproject.
- Rename app-module's source files for consistency.
- Add missing pthread symbols.
- Kernel module symbols are now resolvable on all platforms.
2026-08-29 21:06:43 +02:00
Crazypedia d3556fb536 feat(lilygo-tdeck-max): wire up the DRV2605 haptic driver (#635) 2026-08-29 17:53:45 +02:00
Crazypedia e466b183cc feat(lilygo-tdeck-max): wire up the MIA-M10Q GPS (#634) 2026-08-29 17:51:35 +02:00
Ken Van Hoeylandt bcbf18e363 Implement http-module (#637)
Create http-module and implement it in App Hub and App Hub Details apps.
2026-08-28 23:09:59 +02:00
Ken Van Hoeylandt d2442bedb4 LoraApi callbacks refactored to events (#632) 2026-08-28 18:56:12 +02:00
Crazypedia b7577f2328 feat(gdeq031t10): support an optional frontlight (#633) 2026-08-28 08:59:46 +02:00
Ken Van Hoeylandt 020aa471e2 File locking refactored (#631)
Remove FileMutex and wire locking into driver subsystems.
2026-08-28 01:06:53 +02:00
Ken Van Hoeylandt 92ca046681 app-module events & callstack config, crash diagnostics (#630)
- Apps can specify task stack depth and preferred memory placement in their manifests.
- App identifiers are validated against length and character requirements.
- Crash diagnostics now show the crash cause, reason, fault address, call stack, and program-counter details, with logs saved for review.
- App closing is more consistent across built-in screens. There's now a dedicated function, and the old _emit() function is made private.
- Crash diagnostics no longer display a QR code without a call stack.
- Improved memory allocation for unrestricted requests.
2026-08-27 21:50:12 +02:00
Crazypedia c656ee9ffd fix(gdeq031t10): skip the panel refresh when the frame is unchanged (#624) 2026-08-27 17:03:34 +02:00
Ken Van Hoeylandt 0ee2415f3b Bluetooth and Wi-Fi improvements (#622)
- Enable BT by default in DTS, and create separate radio on/of functionality (like recent Wi-Fi changes)
- Bluetooth event handling now uses queued subscriptions, improving event delivery and application responsiveness.
- Improved synchronization of Bluetooth advertising, connections, HID, MIDI, and SPP operations.
- Enhanced cleanup during Bluetooth shutdown and subscription removal.
- Clarified Bluetooth start and stop behavior.
- Improved wifi driver subscription stability to prevent endless loops
2026-08-26 00:30:03 +02:00
Ken Van Hoeylandt ab75d2022d Refactored events (#621)
Event handling:

- Added unified event handling for application, system, and Wi‑Fi events.
- Updated all apps to reflect event handling changes

Wi-Fi:

- Refactored event handling from listener interface to task & event group.
- Added direct Wi‑Fi radio controls and improved event subscriptions.
- Wi‑Fi screens now refresh asynchronously and handle unavailable devices more gracefully.
- Enabled Wi‑Fi by default on in dts files, but radio on/off is still done by code. The main reason was reliable event subscription and consistent devicetree states.
- Improved Wi‑Fi shutdown cleanup and radio-state handling.

Other:
- Renamed the Kernel Display app to Display.
2026-08-25 17:44:20 +02:00
Ken Van Hoeylandt db48dfe812 Fixes and improvements (#620)
- Standardized keyboard input using Unicode-based key codes across supported devices and the simulator. Keyboards don't emit `LV_KEY_*` anymore.
- Refactored lilygo encoder driver into a reusable GPIO rotary encoder driver (see `Drivers/gpio-encoder-module/`). Added more features to the config file.
- Improved LVGL keyboard device management, including duplicate prevention and reliable reconnects.
- LVGL file mutex now registers with lvgl start/stop
- Improved LVGL startup/shutdown stability and memory allocation reliability.
- Increased simulator LVGL memory capacity and improved USB device-class handling.
2026-08-23 17:21:16 +02:00
Ken Van Hoeylandt 4fea48f433 Remove explicit app closing function (#618) 2026-08-21 08:59:52 +02:00
Ken Van Hoeylandt 0ff1627385 Fixes and improvements (#617) 2026-08-20 17:22:01 +02:00
Ken Van Hoeylandt b03759a111 Fixes and improvements (#616) 2026-08-18 20:43:07 +02:00
Ken Van Hoeylandt f943c4dd69 Move tests to relevant subprojects (#615)
- Moved test projects to the parent project they belong to
- Improved test stability/corectness
- Improved recursive directory deletion by safely ignoring current- and parent-directory entries.
- Update docs
2026-08-13 23:01:12 +02:00
Ken Van Hoeylandt d6b1d15e56 Various improvements (#614)
- Auto-select widgets in Launcher and apps with toolbars on devices without touch.
- Improved USB HID input reliability, cleanup
- Updated PSRAM settings to improve boot stability on supported devices.
- Prevented duplicate Wi-Fi event subscriptions during screen rebuilds.
- Updated docs
- Fixes in WifiManage and WifiConnect
- Reduced main task stack size
- Moved USB HID stack size to PSRAM when available
- app_manager_find_manifest() now returns a copy instead of a pointer
2026-08-13 20:30:47 +02:00
Shadowtrance cc8be3faef USB device-mode support (#613) 2026-08-12 21:29:35 +02:00
Ken Van Hoeylandt 37c507544b Refactor app loading and window management (#609) 2026-08-11 23:40:59 +02:00
Shadowtrance dc3f6104b8 Papers3 improvements (#611)
- And Tab5 keyboard improvements
- Usb host keyboard improvements
- Symbols
- Requires the device.py change from CL-32 PR but that only affects visuals and not build breaking
2026-08-08 15:02:49 +02:00
NellowTCS 564d8af64c Implement Tulip Creative Computer 4r11 (#608) 2026-08-08 14:52:34 +02:00
NellowTCS c6373b79e9 Implement CL-32 Support (#610) 2026-08-07 19:30:22 +02:00
Ken Van Hoeylandt d2c69ee7e8 Move service API from TactilityKernel to service-module (#604)
Extracted the service API from TactilityKernel and put it in a new module at `Modules/service-module`
2026-08-01 20:51:43 +02:00
Shadowtrance 85fe1a319a Tab5 ST7121 variant + fixes (#605)
Added the newest variant to the tab5, St7121.
Fixed variant detection reliability
Fixed tab5 camera WHO_AM_I failing sometimes
Fixed tab5 keyboard live rotation on boot and after stopping/starting lvgl
2026-08-01 20:50:55 +02:00
Crazypedia d72d5a0ef2 fix(gdeq031t10): only commit the shadow after the panel confirms (#607)
shadow_framebuffer records what the panel is currently showing, but both
refresh paths updated it before the refresh was confirmed, so a failed
trigger or a BUSY timeout left it describing content that was never
displayed.

That misdescription compounds: the shadow is sent to the controller as
CMD_DATA_START_OLD, so the per-pixel transitions get computed from an
image the panel never held, and draw_bitmap() diffs against it, so a
region matching a wrong shadow is treated as clean and never repainted.

Both paths now commit only after wait_while_busy() confirms. refresh_full()
also sends new data straight from the render buffer, which drops a
full-framebuffer copy from the path.
2026-07-31 22:09:45 +02:00
Crazypedia 94deee8875 fix(gdeq031t10): reset the panel at the start of a full init (#603) 2026-07-30 23:07:25 +02:00
Crazypedia f13c18f398 LoRa device type + SX1262 kernel driver (first checkpoint) (#565)
Adds sub-GHz radio support to Tactility as a first-class kernel device type, plus a
driver for the Semtech SX1262. Continues the radio work discussed in #342, brought up to
the current kernel driver model (rather than the deprecated tt::hal layer the earlier
prototype targeted).
2026-07-30 19:32:23 +02:00
Ken Van Hoeylandt 606b918f9c Device license changes (#596)
See https://github.com/TactilityProject/Tactility/pull/596 for author consent.
2026-07-30 17:19:11 +02:00
Ken Van Hoeylandt 1cb661469d GPS refactor & license text updates (#601)
- Split up `gps-generic-module` into:
  - `gps-generic-module` that contains only interfaces/configs/bindings (Apache license)
  - `gps-meshtastic-module` that contains an implementation (GPL license)
- Update `LICENSE.md` for changes, but also added clarifications
- Added licenses to directories where they were missing
- Changed license of some test projects from GPL to Apache.
2026-07-30 16:28:41 +02:00
Ken Van Hoeylandt c729e8340f Trackball rewrite (#600)
- Implement generic trackball settings
- Refactor T-Deck trackball driver into generic driver at `Drivers/gpio-trackball-module`
- Automatically bind/unbind trackball devices with LVGL
- Automatically load settings for trackball devices on boot
2026-07-30 13:38:19 +02:00
Ken Van Hoeylandt de6fc3b346 Update dependencies in Devices/ and remove "useDeprecatedHal" (#599)
- Updated dependencies in `Devices/`: remove unused ones, update incorrect ones
- Removed `dependencies.useDeprecatedHal` from device properties (and related scripting/code)
2026-07-29 18:47:19 +02:00
Ken Van Hoeylandt acb2f1d4c7 Replace Tactility SystemEvents with new kernel implementation (#598)
TactilityKernel now has a system event API to replace the one from the Tactility subproject. It also implements several tests for it.
2026-07-29 17:31:20 +02:00
Ken Van Hoeylandt 6e55e71e67 Export atof symbol (#597) 2026-07-29 00:09:58 +02:00
Ken Van Hoeylandt bd108cc3c4 Improvements and fixes (#595)
- Fix BluetoothSettings app not updating when toggling on Bluetooth on
- Fix BluetoothSettings app crash when closing while scanning
- Fix BluetoothSettings app crash when turning BT off while scanning
- WebServer doesn't save config anymore as a side-effect of reading the config
- Add missing license headers
- Use TactilityKernel's time and delay functions instead of TactilityFreeRtos ones
2026-07-28 18:38:23 +02:00
Ken Van Hoeylandt e6e1dcd0ca Software keyboard refactored (#594)
Removed software keyboard in Tactility subproject (GuiService, Lvgl.cpp) and re-implemented it in TactilityKernel.
2026-07-28 00:04:09 +02:00
Ken Van Hoeylandt 58a529cc44 File locking deprecation replacements (#593) 2026-07-27 23:48:02 +02:00
Ken Van Hoeylandt d1f06cb774 Device cleanup (#592)
- Replaced device_find_\* usage by device_get_\* variants.
- Removed deprecated device_find_\* functions.
- Improved reliability of Bluetooth scanning, pairing, connection, and HID host lifecycle behavior, including peer auto-connect handling.
- Improved Bluetooth/USB status indicators and clarified “Eject failed” alerts with the affected mount path.
2026-07-27 17:29:12 +02:00
Ken Van Hoeylandt 3354924359 LvglSync removed (#591)
Replaced all usages with lvgl-module functions.
2026-07-26 23:56:07 +02:00
Ken Van Hoeylandt 03a6285328 Add kernel memory functions & other memory-related changes (#590)
New Features

- Added policy-based memory allocation APIs with capability flags and optional alignment: `memory_alloc_with_policy`, `memory_realloc_with_policy`, `memory_calloc_with_policy`, and `memory_free`.
- Switched heap memory reporting to `memory_print_stats`.

Bug Fixes

- Improved allocation robustness with capability fallback behavior.
- Added overflow-safe handling for aligned zero-initialized allocations.
- Tightened const-correctness for generated device-tree device arrays.

Tests

- Added unit tests for default policy, alignment, zero-initialization, realloc preservation, freeing, and memory stats reporting.
2026-07-26 22:59:18 +02:00
Ken Van Hoeylandt f21c0df6fe Improvements & fixes (#589) 2026-07-26 21:26:52 +02:00
Ken Van Hoeylandt b98a813f3c Migrate TactilityC and LVGL functionality (#588)
lvgl-module

- Move and rename source and include files
- Fix bug with missing lvgl unlock
- New widgets: spinner, toolbar, sliderbox

TactilityC

- Removed tt_lock, tt_lvgl_\*
2026-07-26 15:58:35 +02:00
Ken Van Hoeylandt cd2d9d6158 Fixes and improvements: LVGL, services and kernel symbols (#587) 2026-07-26 13:21:13 +02:00
Ken Van Hoeylandt d4ef83e316 Add LVGL symbols (#586) 2026-07-26 00:21:56 +02:00
Ken Van Hoeylandt db7468d0c8 Module improvements: lvgl, gps, crypt (#585) 2026-07-25 23:04:39 +02:00
Ken Van Hoeylandt ca5b071859 Fix module logic, updated tests, add tests (#584) 2026-07-25 18:05:19 +02:00
Ken Van Hoeylandt 2a2558b29a Remove old HAL components and refactored GPS-related code (#583)
- Added generic GPS/GNSS support with device detection, configuration, and persistent settings.
- Improved device and module lifecycle management.
- Added flexible filesystem locking support for displays and storage.
- Improved display-idle and keyboard backlight handling.
- Updated architecture, driver, module, testing, and licensing documentation.
- Removed old HAL device and related code.
2026-07-25 17:20:17 +02:00
Ken Van Hoeylandt 29e80cfd65 T-Deck Max & Pro support updates (#582)
- Created kernel driver for T-Deck Max & Pro display (needs work, doesn't refresh reliably on T-Deck Pro)
- Created T-Deck Pro device implementation (incubating)
2026-07-24 00:17:48 +02:00
Ken Van Hoeylandt 429125734a Add drivers to module and make start/stop optional (#580) 2026-07-23 23:28:09 +02:00
Shadowtrance 08eac48e64 Fix Tab5 Display Issues (#579)
And add PPA rotation to lvgl_display
2026-07-22 23:58:34 +02:00
Ken Van Hoeylandt 8b92aa8e5a GPIO descriptor fixes (#578) 2026-07-22 22:43:34 +02:00
Ken Van Hoeylandt a3fda9ad8f Device migrations and driver improvements (#576) 2026-07-22 21:11:12 +02:00
Ken Van Hoeylandt 2fbc44466a Device migrations, driver migrations and more (#575) 2026-07-20 23:43:17 +02:00
Shadowtrance 2d768ef3a1 ESP-NOW bridge for P4 (#573) 2026-07-19 09:23:20 +02:00
reyna-b bd30aa046a Add ES3C28P device (#569) 2026-07-19 09:17:19 +02:00
Ken Van Hoeylandt f9453d8956 Migrate devices, create drivers, other improvements & fixes (#574)
Migrated devices to kernel drivers:

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

New drivers:

- axp192-module
- axp2101-module

Fixes:

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

Improvements:

- `GuiService` now keeps trying to lock to prevent silent failures caused by drivers.
- `GuiService` now uses lvgl-module calls for locking/unlocking
- display driver now has capability `DISPLAY_CAPABILITY_SLOW_REFRESH`
2026-07-19 00:39:26 +02:00
1701 changed files with 84797 additions and 42906 deletions
+69
View File
@@ -0,0 +1,69 @@
# CLAUDE.md
Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.
**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
## 1. Think Before Coding
**Don't assume. Don't hide confusion. Surface tradeoffs.**
Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.
## 2. Simplicity First
**Minimum code that solves the problem. Nothing speculative.**
- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
## 3. Surgical Changes
**Touch only what you must. Clean up only your own mess.**
When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.
When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.
The test: Every changed line should trace directly to the user's request.
## 4. Goal-Driven Execution
**Define success criteria. Loop until verified.**
Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"
For multi-step tasks, state a brief plan:
```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
---
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
For current-firmware merges, board customization retention, ESP-IDF build/flash,
and external-app compatibility verification, also follow
`.claude/skills/tactility-firmware-development/SKILL.md`.
+18
View File
@@ -0,0 +1,18 @@
# Architecture: App Framework
Apps are event-driven, C API (`app-module`, `<app/*.h>`), not a C++ class. Each app has an `AppManifest` (`id`, `name`, `category`, `location`, `flags`) and a `main(argc, argv)` entry point (`AppMainFn`), modelled on a C program's `main()`. Every app instance gets its own dedicated task for its whole lifetime, and blocks in that task until it returns. Use `app_scheduler_current_app_id()` (`app/scheduler.h`) to identify the running instance - it's not passed as a parameter.
Lifecycle and inter-app communication go through `app_manager_*()` (`app/manager.h`) and `app_event_*()` (`app/event.h`):
- `app_manager_start()`/`app_manager_start_with_parameters()` launch a plain instance; `app_manager_start_for_result()` launches a modal child that reports back to a parent instance.
- An app subscribes with `app_event_subscribe()` (registers for its own instance's events, no id argument needed), blocks via `task_event_group_wait()`/`task_event_group_wait_any()`, and drains with `app_event_poll()`, reacting to `APP_EVENT_CLOSE` (terminate now) and `APP_EVENT_RESULT` (a child it started reported back).
- An app closes itself by calling `app_manager_finish()` right before returning from `main()`; another instance is closed via `app_manager_stop()`.
Apps are registered at startup via `app_manager_add()`. External apps can be loaded from SD card via `manifest.properties` files, or side-loaded as ELF binaries on ESP32 (see `app/loader.h`'s `AppLoaderApi`).
Apps can be loaded from:
- memory (`APP_LOCATION_MEMORY`)
- a path pointing to an install folder where an `.app` file was installed (`APP_LOCATION_PATH`)
- a path pointing to an `.elf` file (`APP_LOCATION_PATH`)
An app can build an optional UI via the LVGL window-manager module (see `lvgl.md`).
@@ -0,0 +1,10 @@
# Architecture: Device/Driver/Module System (kernel layer, C API)
The kernel uses a Linux-inspired device model:
- **Module** (`struct Module`): loadable unit that registers drivers, hardware and symbols. Lifecycle: `module_construct` → `module_add` → `module_start`. Each device board and platform is a module.
- **Driver** (`struct Driver`): binds to devices via `compatible` strings (like devicetree). Has `start_device`/`stop_device` callbacks and an `api` pointer for type-specific operations.
- **Device** (`struct Device`): represents hardware. Lifecycle: `device_construct` → `device_add` → `device_start`. Has a parent-child tree, driver binding, and locking.
- **DeviceType** (`struct DeviceType`): enables discovering devices by category (e.g. `DISPLAY_TYPE`, `TOUCH_TYPE`, `UART_CONTROLLER_TYPE`).
Devices are defined via **devicetree** `.dts` files in each `Devices/<id>/` folder. A custom devicetree compiler (`Buildscripts/DevicetreeCompiler/compile.py`) generates C code from these files. Each device folder also has a `devicetree.yaml` specifying dependencies and the `.dts` file.
+7
View File
@@ -0,0 +1,7 @@
# Architecture: Layer Stack (bottom to top)
- **TactilityKernel** — C API kernel: device/driver/module lifecycle, concurrency primitives (thread, mutex, timer, dispatcher), filesystem, logging. Header convention: `<tactility/*.h>` (lowercase snake_case).
- **TactilityFreeRtos** — Thin C++ wrappers around FreeRTOS primitives.
- **Tactility** — Main OS layer: app framework, service framework, LVGL integration, networking and services (Wi-Fi, BLE, NTP, ESP-NOW), settings, i18n.
- **TactilityC** — C bindings (`tt_*.h`) for Tactility, used by side-loaded ELF apps on ESP32. Deprecated, replaced by TactilityKernel.
- **Firmware** — Entry point (`app_main`).
+5
View File
@@ -0,0 +1,5 @@
# Architecture: Build System
The `tactility_add_module()` CMake macro (in `Buildscripts/module.cmake`) wraps ESP-IDF's `idf_component_register` on ESP32 and standard `add_library` on POSIX, allowing the same source to build for both targets.
`device.py` reads `Devices/<id>/device.properties` and generates the `sdkconfig` file with all necessary ESP-IDF config (target chip, flash size, SPIRAM, LVGL fonts, Bluetooth, USB, etc.).
+62
View File
@@ -0,0 +1,62 @@
# Building
## Git
The repository uses git submodules. Make sure to use `--recurse-submodules` on relevant git commands.
## Simulator (Linux/macOS, no ESP-IDF needed)
> [!IMPORTANT]
> The simulator does **NOT** build or run on native Windows (Win32/PowerShell/cmd). This is
> a hard platform limitation, not a missing tool or PATH issue — do not attempt `cmake -B
> buildsim` on Windows, it will not work. WSL is a separate, Linux environment and is fine.
```bash
cmake -B buildsim -G Ninja
ninja -C buildsim # build firmware + tests
./buildsim/Firmware/Tactility # run simulator
```
## ESP32 firmware
```bash
python device.py <device-id> # generate sdkconfig for device (e.g. lilygo-tdeck)
python device.py <device-id> --dev # dev mode: force 4MB partition table
idf.py build # build firmware
idf.py flash monitor # flash and monitor
```
Device IDs are the folder names under `Devices/` (e.g. `lilygo-tdeck`, `m5stack-cores3`, `cyd-2432s028r`).
### Windows: activating the ESP-IDF environment
On native Windows, `idf.py` is not on PATH by default — it must be activated per-shell first.
The install script places a PowerShell profile activator per IDF version at
`%IDF_TOOLS_PATH%\Microsoft.v<version>.PowerShell_profile.ps1` (path controlled by the
`IDF_TOOLS_PATH` environment variable, set to wherever ESP-IDF's tools were installed, e.g.
`C:\Espressif\tools`). Source it before running any `idf.py` command:
```powershell
. "$env:IDF_TOOLS_PATH\Microsoft.v5.5.2.PowerShell_profile.ps1" # match the installed IDF version
Set-Location "<repo-root>"
idf.py build 2>&1 | Select-Object -Last 250
```
This is Windows-specific setup (the main dev works on Linux, where `idf.py` is normally
already on PATH via `export.sh`/`. ./export.sh` or a shell profile).
## Devicetree
A device implementation has a `.dts` file.
The parser at `Buildscripts/DevicetreeCompiler/` converts DTS into C code.
It's called from the `Firmware/` build process.
## Tests
Tests use Doctest and run on simulator (POSIX) target only:
```bash
cmake -B buildsim -G Ninja
ninja -C buildsim build-tests
cd buildsim && ctest --test-dir Tests
```
+34
View File
@@ -0,0 +1,34 @@
# Coding Style
Two conventions coexist; which one to use depends on the project layer:
- **C code** (TactilityKernel, drivers): `lower_snake_case` for files, functions, variables. `UpperCamelCase` for types. Files in `source/`, `include/`, `private/` directories.
- **C++ code** (Tactility, apps, services): `UpperCamelCase` for files and types. `lowerCamelCase` for functions. Files in `Source/`, `Include/`, `Private/` directories.
For projects that emit C headers and have a C++ implementation file: the internal C++ function naming should be snake_case.
Formatting is enforced by `.clang-format` (LLVM-based, 4-space indent, no column limit).
Never throw exceptions — use return types for error handling. Use `enum class` over plain `enum` when writing C++ code.
Do not add redundant null checks for parameters with an explicit non-null precondition.
Code Comments:
- Should be as short as possible, leaving only important context.
- Should avoid explaining what the code does, unless the code complexity is high enough to warrant an explanation.
- Must avoid explaining how the code was before, or how it was changed.
- Should explain why code is implemented.
- Should be as brief as possible without losing critical information.
- Should avoid explaining what was not implemented.
- Should avoid referring to designs of other subsystems.
- Must avoid interjections: avoid hyphens or braces to interject. If interjections provide crucial info, use Doxygen entity/anchor references like:
/**
* A dedicated completion \signal for one app instance's task.
* Whichever \side finishes with it last is the one that deletes `semaphore` and frees this struct.
*
* \signal Not the task's shared default FreeRTOS notification, which app_event.cpp's AppEventSubscription also uses.
* An unrelated event delivered to the same task could otherwise unblock a waiter early.
* \side The exiting task or a concurrent app_scheduler_stop() that found the entry in time and is waiting on `semaphore`.
*/
```
@@ -0,0 +1,38 @@
# Architecture: Hardware Abstraction Layer
## Driver
A driver generally consists of:
- Registration of driver in parent module (optional, but desirable)
- YAML bindings in the `bindings/` folder
- An `#include` that is used in the `.dts` file. The include is in `[projectname]/bindings/[drivername].h`
- The driver implementation: a `.cpp` and `.h` file. The implementation is C++, but the header exposes pure C functions. C implementations are allowed, but C++ is preferred.
Drivers are part of a kernel module.
A driver whose device sits on a shared SPI controller (parent device type `SPI_CONTROLLER_TYPE`)
must bracket its own bus access with `spi_controller_lock()`/`spi_controller_unlock()`
(`spi_controller_lock_bus_of()`/`spi_controller_unlock_bus_of()` for the common case of a direct
child), at the logical-operation level rather than per primitive. This is not done for you by the
kernel's generic device-type wrappers (`display.cpp`, `pointer.cpp`, etc.) - only the driver knows
for certain which of its calls touch the bus.
Modules with drivers can be stored in:
- TactilityKernel
- A subproject in `Platforms` folder
- A subproject in `Devices` folder
- A subproject in `Drivers` folder
## Kernel Modules
Kernel module names are lower case and postfixed with `-module`.
Projects that are kernel modules:
1. Declare a `struct Module`
2. Contain a `devicetree.yaml` file that declares a list of dependencies (for parsing the devicetree) and specifies the bindings folder that contains the drivers' YAML definitions. For example:
```yaml
dependencies:
- TactilityKernel
bindings: bindings
```
+8
View File
@@ -0,0 +1,8 @@
# Key Conventions
- Shared cross-platform code uses `#ifdef ESP_PLATFORM` for ESP32-specific paths.
Code in `Platforms/PlatformEsp32/` is already ESP-only and does not need guards around ESP-IDF includes.
- The `Drivers/` directory contains hardware drivers (display controllers, touch controllers, PMICs, etc.) — each is its own CMake component.
- `Modules/` contains cross-cutting modules. e.g.`lvgl-module` (LVGL task management).
- `Data/system/` and `Data/data/` are flashed as FAT filesystem images on ESP32.
- Translations are in `Translations/` as CSV files, generated via `generate.py`.
+8
View File
@@ -0,0 +1,8 @@
# Architecture: LVGL
User interfaces should scale well for everything between very large (e.g. 1280x720) and small (e.g. 135x240) displays. Vertical and horizontal layouts are supported.
Two kernel modules cover LVGL:
- **`lvgl-module`** (`Modules/lvgl-module/`, `<lvgl/*.h>`) owns LVGL's lifecycle: init/deinit, the LVGL task loop, and `lvgl_lock()`/`lvgl_try_lock()`/`lvgl_unlock()` mutex-based locking that any task must hold before touching LVGL objects. It bridges Tactility's device model to LVGL indevs (`lvgl/devices/*.h`: `display`, `pointer`, `keyboard`, `trackball`), and provides shared fonts (`lvgl/fonts.h`: Montserrat text sizes, Material Symbols icon sets for statusbar/launcher/shared use) and a few shared widgets (`lvgl/widgets/*.h`: `toolbar`, `spinner`, `sliderbox`).
- **`lvgl-window-manager-module`** (`Modules/lvgl-window-manager-module/`, `<lvgl_window_manager/*.h>`) manages a single stacked window per app instance on top of `lvgl-module`. `window_manager_start()`/`window_manager_stop()` create/tear down the root widget (plus optional chrome from a configured `WindowManagerScreenInitFn`); `window_manager_create()`/`window_manager_remove()` push/pop an app's window and (re)populate it via a `WindowCreateWidgetsFn`. Only the topmost window ever has live widgets - burying and resurfacing a window deletes and rebuilds its widget tree rather than hiding/showing it. That rebuild-on-remove path can run `create_widgets` on a *different* app's thread (whichever app's `window_manager_remove()` call caused this window to resurface), so `create_widgets` must only rebuild already-committed state, never decide what happens next - state transitions belong in the app's own `main()` event loop, driven by real `APP_EVENT_RESULT`s.
+4
View File
@@ -0,0 +1,4 @@
# Architecture: Platform Abstraction
- `Platforms/platform-esp32/` — ESP-IDF specific implementations
- `Platforms/platform-posix/` — POSIX simulator implementations (SDL for display)
+3
View File
@@ -0,0 +1,3 @@
# Project Overview
Tactility is an operating system for the ESP32 microcontroller family. It runs on 40+ supported devices (CYD boards, LilyGO, M5Stack, Elecrow, etc.) and includes a desktop simulator. Built with C++23, ESP-IDF, LVGL, and FreeRTOS.
+3
View File
@@ -0,0 +1,3 @@
# Architecture: Service Framework
Services are a C API (`service-module`, `<service/*.h>`), not a C++ class. Each service has a `ServiceManifest` (`id`, `create_service`/`destroy_service` for its custom data, `on_start`/`on_stop` callbacks) registered via `service_manager_add()`, and is started/stopped via `service_manager_start()`/`service_manager_stop()`. Services are long-running background processes (GUI, Wi-Fi, loader, statusbar, GPS, etc.).
+1
View File
@@ -0,0 +1 @@
Tests for projects should be placed in the `Tests/` or `tests/` subfolder of that project.
@@ -0,0 +1,208 @@
---
name: tactility-firmware-development
description: Use when merging current Tactility firmware, preserving local ES3C28P/ES3C35P customizations, building/flashing ESP32 firmware, or validating external apps against it.
---
# Tactility firmware development
## Scope and success criteria
Use this skill for firmware upgrades, especially when upstream changes the app
loader, dashboard API, SDK export, or device model. Before editing, record the
active branch, `git status --short`, selected `Devices/<id>`, serial port, and
the expected device identity. Preserve user work and local board
customizations; do not reset or overwrite a dirty tree.
Success is not merely a successful flash: the board must boot, mount storage,
return `/api/sysinfo`, expose required internal apps, and accept an external
app rebuilt against this exact firmware.
## Upgrade and customization audit
1. Fetch and compare the intended upstream branch before merging. Treat
`upstream/main` as distinct from experimental release/IDF branches unless
the task explicitly asks for one of those branches.
2. Merge without discarding local work (for example, `git merge --autostash
upstream/main` after inspecting status). Resolve conflicts by preserving
required ES3C28P and ES3C35P device definitions, partition selection,
display/font customizations, and product features.
3. Compare the pre-upgrade customization commit against the resulting worktree.
Check new app registrations, CMake/source inclusion, settings pages,
web-server endpoints, and board-specific `sdkconfig` entries—not just files
that happen to conflict.
4. Commit the resulting firmware customization as a focused, reviewable
commit after `git diff --check`.
## Multi-binary external-app compatibility
Upstream app packaging changed to `bin/<platform>/<binary>.elf`. The old
`elf/<platform>.elf` archive layout produces a loader `Not executable` error.
- Manifest v0.2: `bin/esp32s3/app.elf`
- Manifest v0.3: `bin/esp32s3/<app.0.binary>.elf`
When this change arrives, update the companion app tool and rebuild every app
from a fresh SDK exported from this firmware. Do not attempt to repair a
packaged ELF on the SD card: its layout and ABI must both be regenerated.
## Build and flash
Use the installed IDF 5.5 environment; host virtual environments can corrupt
both Python dependencies and IDF tooling:
```zsh
unset VIRTUAL_ENV PYTHONPATH PYTHONHOME
export IDF_PYTHON_ENV_PATH=/Users/adolforeyna/.espressif/python_env/idf5.5_py3.9_env
source /Users/adolforeyna/esp/esp-idf/export.sh
# Select/check the intended board before this step.
python device.py <device-id>
idf.py build
idf.py -p /dev/cu.usbmodemXXXX flash
```
`Tactility/CMakeLists.txt` uses a non-configure-dependent source glob. After
adding a new `.c`/`.cpp` file, run `idf.py reconfigure build`; otherwise a
linker error for a newly referenced symbol may only mean CMake has not
discovered the source file yet.
## Boot and feature acceptance
Capture serial at 115200 after flash or reset. Confirm the board name, SD-card
mount, HTTP-server start, Wi-Fi address, and any feature-specific startup logs.
Then query the resolved device:
```zsh
curl -fsS http://<ip>/api/sysinfo
curl -fsS http://<ip>/api/apps
```
For MCP settings, verify the `McpSettings` internal app appears in `/api/apps`.
When enabled, verify MCP stream startup logs. For a feature restored from an
older customization, validate its registration path and persisted settings,
not only its source files.
## External-app acceptance gate
Use the companion app skill's exact-firmware wrapper:
```zsh
cd /path/to/tactility_apps
scripts/build_current_firmware_app.sh Apps/MyApp --firmware /path/to/tactility
```
Inspect the resulting tar member path, install through port-80 dashboard API,
launch it, and read serial. Required evidence is the loader's `Loading
.../bin/...`, an ELF entry address, `Task started`, and app-specific startup
logs. HTTP 200 or a package simply appearing in `/api/apps` is insufficient.
## Host simulator (buildsim) + web viewer
The POSIX simulator runs the real firmware (LVGL, services, web server) on
macOS/Linux with an SDL backend. On current firmware, `Main.cpp` runs SDL's
event loop on the process main thread while FreeRTOS runs on a separate thread.
This is required by AppKit and supports a native macOS window as well as the
web viewer. `SDL_VIDEODRIVER=dummy` remains useful for headless automation.
Code locations:
- `Devices/simulator/Source/module.cpp` — display resolution + `SIM_DISPLAY_W/H`
- `Devices/simulator/Source/drivers/sdl_display.{h,cpp}` — SDL backend
- `Devices/simulator/Source/drivers/sdl_input.{h,cpp}` — pointer/key state +
web touch-injection override
- `Tactility/Source/service/webserver/WebServerService.cpp` — `/sim` viewer,
`/sim/api/*` aliases, `POST /api/sim/touch`, `GET /api/screenshot?fast=`
- `Tactility/Private/Tactility/service/webserver/WebServerService.h` — handler decls
### Build and run
```zsh
# one-time host deps (outside any ESP-IDF env)
mkdir -p /tmp/simbin && ln -sf "$(which python3)" /tmp/simbin/python
pip3 install --break-system-packages lark pyyaml # devicetree compiler
cd /path/to/tactility
export PATH="/tmp/simbin:$PATH"
env -u ESP_IDF_VERSION -u IDF_PATH cmake -S . -B buildsim -DCMAKE_BUILD_TYPE=Release
env -u ESP_IDF_VERSION -u IDF_PATH cmake --build buildsim --target Tactility -j "$(sysctl -n hw.ncpu)"
# POSIX SDK for host apps (arm64)
env -u ESP_IDF_VERSION -u IDF_PATH cmake --build buildsim --target TactilityKernel lvgl minitar minmea \
app-module crypt-module gps-module http-module lvgl-module lvgl-window-manager-module service-module
env -u ESP_IDF_VERSION -u IDF_PATH python3 Buildscripts/release-sdk-posix.py /tmp/sim-sdk
# release (MUST run from the firmware root: release-simulator.sh uses relative
# version.txt / Data paths)
sh Buildscripts/release-simulator.sh buildsim /tmp/simrun
# Native macOS window + web API. Run this from the release directory because
# data/ and system/ are relative to the process working directory.
(cd /tmp/simrun && SIM_DISPLAY_W=480 SIM_DISPLAY_H=320 \
nohup ./Tactility > /tmp/sim_gui.log 2>&1 &)
# For CI/headless operation, set SDL_VIDEODRIVER=dummy instead.
curl -s --max-time 5 http://127.0.0.1/api/sysinfo | head -c 120
```
Display resolution: `SIM_DISPLAY_W/H` env (default **480x320 landscape**,
matching on-device screenshots). ES3C35P panel is 320x480 portrait in DTS but
presents 480x320 landscape; ES3C28P is 320x240. The chosen geometry is logged
as `Simulator Sim display WxH`. `SDL_VIDEODRIVER=dummy` is expected to log one
`SdlDisplay Failed to create SDL window: Couldn't find matching render
driver` line — LVGL still renders and screenshots work. A native macOS launch
must not emit that line.
### Web viewer, touch, screenshots
- `GET /sim` → 301 to `/sim/` (trailing slash required so the page's relative
`api/` URLs resolve under `/sim/`). Viewer polls `api/screenshot?fast=1`
every 500 ms, footer shows live `naturalWidth×naturalHeight`, click/tap
POSTs `api/sim/touch?x=&y=`.
- `POST /api/sim/touch?x=123&y=456[&down=0|1]` (also `/sim/api/sim/touch` via
alias). Coordinates are LVGL logical pixels. `down=1` (default) presses and
**auto-releases after 1500 ms** (`SIM_TOUCH_HOLD_MS` in `sdl_input.cpp`),
long enough for LVGL indev polls to register a click. Simulator-only: 404 on
ESP32 (`#ifndef ESP_PLATFORM`).
- `GET /api/screenshot?fast=1` (default): `lv_snapshot_take` (RGB888) → in-place
BGR→RGB swap → `lodepng_encode24` **to memory** → chunked HTTP. No filesystem
touch, ~8 ms/shot. `?fast=0` keeps the legacy `webscreenshotN.png` file path
(slot scan + accumulation — avoid for viewer loops).
- lodepng include in `.cpp`: `#define LODEPNG_NO_COMPILE_CPP` before
`#include "src/libs/lodepng/lodepng.h"`, otherwise its C++ `std::vector`
overloads collide with the C declarations (`conflicting types for 'encode'`).
- MCP includes and `settings::mcp` reads are `#ifdef ESP_PLATFORM`-gated; the
sim has no `McpSystem`.
### Tailscale viewer
```zsh
tailscale serve --bg --set-path=/simagent http://127.0.0.1:80/
# open: https://<node>/simagent/sim/
```
The serve target must be `/` (not `/sim`): the page resolves `api/` against
its own directory, so at `/simagent/sim/` fetches go to `/simagent/sim/api/…`,
which tailscale strips to `/sim/api/…` and the firmware's `/sim/api/*`
aliases (GET+POST, registered in `startServer()`) handle. Absolute `/api/…`
URLs would 404 at the edge (no `/api` mount there).
### Simulator pitfalls
- **Rebuild ≠ redeploy.** `cmake --build buildsim` updates `buildsim/` only.
Re-run `release-simulator.sh`, restart the process, then retest. A stale
`/tmp/simrun/Tactility` serves old handlers with new logs nowhere to be found.
- **One simulator owns port 80.** Do not launch a second instance while another
simulator is listening: it will initialize LVGL but fail `bind/listen`, so its
app API and viewer target the other process. Identify the listener with
`lsof -nP -iTCP:80 -sTCP:LISTEN`, stop only the intended simulator, then
release/restart it before installing or running POSIX apps.
- **Input is cross-thread on macOS.** SDL event pumping occurs on the real main
thread; LVGL and web touch injection run elsewhere. Keep all shared pointer,
key-queue, and touch-override state under `sdl_input.cpp`'s mutex.
- **C array `sizeof` decay.** A helper like
`f(HttpServerRequest*, char uri[256])` sees `sizeof(uri) == 8`, truncating
`get_uri` output to 7 chars (`/api/sy`, `/sim/ap` 404s). Pass the size
explicitly: `f(request, buf, sizeof(buf))`.
- **Log truncation.** `LOG_QUEUE_MESSAGE_MAX_LENGTH` is 256 (`TactilityKernel/
private/tactility/log_queue.h`), including color/timestamp prefix. Long URIs
and messages truncate — don't over-interpret a short path in the log.
- **Auth.** The viewer and API handlers enforce `validateRequestAuth` like any
other endpoint; failures surface as 401/404, not viewer bugs.
@@ -0,0 +1,41 @@
name: Build
runs:
using: "composite"
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
persist-credentials: false
- name: 'Detect architecture'
id: arch
shell: bash
run: echo "value=$(uname -m)" >> "$GITHUB_OUTPUT"
- name: 'Configure'
shell: bash
run: cmake -S ./ -B buildsim
- name: 'Build'
shell: bash
run: cmake --build buildsim --target TactilityKernel lvgl minitar minmea $(cat Buildscripts/release-sdk-modules.txt)
- name: 'Release'
shell: bash
run: python Buildscripts/release-sdk-posix.py release/TactilitySDK
- name: 'Test Integration Prep'
shell: bash
env:
TACTILITY_ARCH: ${{ steps.arch.outputs.value }}
run: |
TACTILITY_SDK_NAME="$(cat version.txt)-posix-$TACTILITY_ARCH"
mkdir -p test_sdk/$TACTILITY_SDK_NAME
cp -r release/TactilitySDK test_sdk/$TACTILITY_SDK_NAME
- name: 'Test Integration'
shell: bash
env:
TACTILITY_ARCH: ${{ steps.arch.outputs.value }}
run: cd Tests/SdkIntegration && TACTILITY_SDK_PATH=../../test_sdk python tactility.py build -a posix-$TACTILITY_ARCH --local-sdk
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
with:
name: TactilitySDK-posix-${{ steps.arch.outputs.value }}
path: release/TactilitySDK
retention-days: 30
+3 -3
View File
@@ -29,13 +29,13 @@ runs:
env: env:
# NOTE: Update with ESP-IDF! # NOTE: Update with ESP-IDF!
ESP_IDF_VERSION: '5.5.2' ESP_IDF_VERSION: '5.5.2'
run: python Buildscripts/release-sdk.py release/TactilitySDK run: python Buildscripts/release-sdk-esp32.py release/TactilitySDK
- name: 'Test Integration Prep' - name: 'Test Integration Prep'
shell: bash shell: bash
# The manifest.properties of our integration test uses version 0.0.0 to indicate that it is not using a normal SDK # The manifest.properties of our integration test uses version 0.0.0 to indicate that it is not using a normal SDK
# This way, it only works with our custom build. That means we have to create a copy of the SDK with the correct folder structure: # This way, it only works with our custom build. That means we have to create a copy of the SDK with the correct folder structure:
run: | run: |
TACTILITY_SDK_NAME="0.0.0-${{ inputs.arch }}" TACTILITY_SDK_NAME="$(cat version.txt)-${{ inputs.arch }}"
mkdir -p test_sdk/$TACTILITY_SDK_NAME mkdir -p test_sdk/$TACTILITY_SDK_NAME
cp -r release/TactilitySDK test_sdk/$TACTILITY_SDK_NAME cp -r release/TactilitySDK test_sdk/$TACTILITY_SDK_NAME
- name: 'Test Integration' - name: 'Test Integration'
@@ -43,7 +43,7 @@ runs:
with: with:
esp_idf_version: v5.5.2 esp_idf_version: v5.5.2
target: ${{ inputs.arch }} target: ${{ inputs.arch }}
command: export TACTILITY_SDK_PATH=../../test_sdk && cd Tests/SdkIntegration && python tactility.py build ${{ inputs.arch }} --local-sdk command: export TACTILITY_SDK_PATH=../../test_sdk && cd Tests/SdkIntegration && python tactility.py build -a ${{ inputs.arch }} --local-sdk
- name: 'Upload Artifact' - name: 'Upload Artifact'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
+6 -10
View File
@@ -4,11 +4,8 @@ inputs:
os_name: os_name:
description: A descriptive name for the operating system (e.g. linux, windows) description: A descriptive name for the operating system (e.g. linux, windows)
required: true required: true
platform_name: architecture:
description: A descriptive name for the target platform (e.g. amd64, aarch64, etc.) description: A descriptive name for the target architecture (e.g. x86_64, aarch64, etc.)
required: true
publish:
description: A boolean that enables publishing of artifacts
required: true required: true
runs: runs:
@@ -45,14 +42,13 @@ runs:
run: cmake -S ./ -B buildsim run: cmake -S ./ -B buildsim
- name: "Build Tests" - name: "Build Tests"
shell: bash shell: bash
run: cmake --build buildsim --target FirmwareSim run: cmake --build buildsim --target Tactility
- name: 'Release' - name: 'Release'
shell: bash shell: bash
run: Buildscripts/release-simulator.sh buildsim release/Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }} run: Buildscripts/release-simulator.sh buildsim release/Simulator-${{ inputs.os_name }}-${{ inputs.architecture }}
- name: 'Upload Artifact' - name: 'Upload Artifact'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
if: ${{ inputs.publish == 'true' }}
with: with:
name: Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }} name: Simulator-${{ inputs.os_name }}-${{ inputs.architecture }}
path: release/Simulator-${{ inputs.os_name }}-${{ inputs.platform_name }} path: release/Simulator-${{ inputs.os_name }}-${{ inputs.architecture }}
retention-days: 30 retention-days: 30
+2 -5
View File
@@ -17,8 +17,7 @@ jobs:
uses: ./.github/actions/build-simulator uses: ./.github/actions/build-simulator
with: with:
os_name: linux os_name: linux
platform_name: amd64 architecture: x86_64
publish: true
macOS: macOS:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
@@ -29,6 +28,4 @@ jobs:
uses: ./.github/actions/build-simulator uses: ./.github/actions/build-simulator
with: with:
os_name: macos os_name: macos
platform_name: aarch64 architecture: aarch64
# macOS simulator currently fails due to main thread requirement for rendering
publish: false
+11 -3
View File
@@ -11,7 +11,7 @@ on:
permissions: read-all permissions: read-all
jobs: jobs:
BuildSdk: BuildSdkEsp32:
strategy: strategy:
matrix: matrix:
board: [ board: [
@@ -30,9 +30,17 @@ jobs:
with: with:
board_id: ${{ matrix.board.id }} board_id: ${{ matrix.board.id }}
arch: ${{ matrix.board.arch }} arch: ${{ matrix.board.arch }}
BuildSdkPosix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: "Build SDK"
uses: ./.github/actions/build-sdk-posix
GenerateDeviceMatrix: GenerateDeviceMatrix:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ BuildSdk ] needs: [ BuildSdkEsp32 ]
outputs: outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }} matrix: ${{ steps.set-matrix.outputs.matrix }}
steps: steps:
@@ -57,7 +65,7 @@ jobs:
arch: ${{ matrix.board.arch }} arch: ${{ matrix.board.arch }}
BundleArtifacts: BundleArtifacts:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ BuildFirmware ] needs: [ BuildFirmware, BuildSdkPosix ]
if: | if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
+2 -8
View File
@@ -19,14 +19,8 @@ jobs:
run: cmake -S ./ -B build run: cmake -S ./ -B build
- name: "Build Tests" - name: "Build Tests"
run: cmake --build build --target build-tests run: cmake --build build --target build-tests
- name: "Run TactilityFreeRtos Tests" - name: "Run Tests"
run: build/Tests/TactilityFreeRtos/TactilityFreeRtosTests run: ctest --test-dir build/Tests
- name: "Run Tactility Tests"
run: build/Tests/Tactility/TactilityTests
- name: "Run TactilityKernel Tests"
run: build/Tests/TactilityKernel/TactilityKernelTests
- name: "Run CryptModuleTests Tests"
run: build/Tests/crypt-module/CryptModuleTests
DevicetreeTests: DevicetreeTests:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
+7 -4
View File
@@ -1,10 +1,11 @@
.idea/ .idea/
.DS_Store .DS_Store
build/ build*/
buildsim/ !.github/actions/build*/
build-*/ !Buildscripts/
cmake-*/ !Buildscripts/release-simulator-macos-app.sh
cmake*/
CMakeCache.txt CMakeCache.txt
*.cbp *.cbp
CMakeFiles CMakeFiles
@@ -27,3 +28,5 @@ sdkconfig.board.*.dev
.caveman.json .caveman.json
.ai/mcp .ai/mcp
__pycache__
+3
View File
@@ -16,3 +16,6 @@
[submodule "Libraries/cJSON/cJSON"] [submodule "Libraries/cJSON/cJSON"]
path = Libraries/cJSON/cJSON path = Libraries/cJSON/cJSON
url = https://github.com/DaveGamble/cJSON.git url = https://github.com/DaveGamble/cJSON.git
[submodule "Libraries/esp_epaper"]
path = Libraries/esp_epaper
url = https://github.com/NellowTCS/esp_epaper.git
@@ -26,7 +26,7 @@ def get_device_node_name_safe(device: Device):
def get_device_type_name(device: Device, bindings: list[Binding]): def get_device_type_name(device: Device, bindings: list[Binding]):
device_binding = find_device_binding(device, bindings) device_binding = find_device_binding(device, bindings)
if device_binding is None: if device_binding is None:
raise DevicetreeException(f"Binding not found for {device.node_name}") raise DevicetreeException(f"Binding not found for {device.node_name}. Make sure that the driver name in the driver's yaml and driver code declarations matches with the device dts file.")
if device_binding.compatible is None: if device_binding.compatible is None:
raise DevicetreeException(f"Couldn't find compatible binding for {device.node_name}") raise DevicetreeException(f"Couldn't find compatible binding for {device.node_name}")
compatible_safe = device_binding.compatible.split(",")[-1] compatible_safe = device_binding.compatible.split(",")[-1]
@@ -282,6 +282,7 @@ def write_device_structs(file, device: Device, parent_device: Device, bindings:
file.write(f"\t.address = {address_value},\n") file.write(f"\t.address = {address_value},\n")
file.write(f"\t.name = \"{device.node_name}\",\n") # Use original name file.write(f"\t.name = \"{device.node_name}\",\n") # Use original name
file.write(f"\t.config = &{config_variable_name},\n") file.write(f"\t.config = &{config_variable_name},\n")
file.write("\t.flags = DEVICE_FLAG_DTS,\n")
file.write(f"\t.parent = {parent_value},\n") file.write(f"\t.parent = {parent_value},\n")
file.write("\t.internal = NULL\n") file.write("\t.internal = NULL\n")
file.write("};\n\n") file.write("};\n\n")
@@ -349,7 +350,7 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin
for item in items: for item in items:
if type(item) is Device: if type(item) is Device:
write_device_structs(file, item, None, bindings, devices, verbose) write_device_structs(file, item, None, bindings, devices, verbose)
file.write("struct DtsDevice dts_devices[] = {\n") file.write("const struct DtsDevice dts_devices[] = {\n")
for item in items: for item in items:
if type(item) is Device: if type(item) is Device:
write_device_list_entry(file, item, bindings, verbose) write_device_list_entry(file, item, bindings, verbose)
@@ -378,7 +379,7 @@ def generate_devicetree_c(filename: str, items: list[object], bindings: list[Bin
file.write(f"extern struct Module {symbol};\n") file.write(f"extern struct Module {symbol};\n")
file.write("\n") file.write("\n")
# Create array of symbol variables # Create array of symbol variables
file.write("struct Module* dts_modules[] = {\n") file.write("struct Module* const dts_modules[] = {\n")
for symbol in module_symbol_names: for symbol in module_symbol_names:
file.write(f"\t&{symbol},\n") file.write(f"\t&{symbol},\n")
file.write("\tNULL\n") file.write("\tNULL\n")
@@ -396,10 +397,10 @@ def generate_devicetree_h(filename: str):
#endif #endif
// Array of device tree modules terminated with DTS_MODULE_TERMINATOR // Array of device tree modules terminated with DTS_MODULE_TERMINATOR
extern struct DtsDevice dts_devices[]; extern const struct DtsDevice dts_devices[];
// Array of module symbols terminated with NULL // Array of module symbols terminated with NULL
extern struct Module* dts_modules[]; extern struct Module* const dts_modules[];
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -13,6 +13,7 @@ static struct Device root = {
.address = 0, .address = 0,
.name = "/", .name = "/",
.config = &root_config, .config = &root_config,
.flags = DEVICE_FLAG_DTS,
.parent = NULL, .parent = NULL,
.internal = NULL .internal = NULL
}; };
@@ -27,6 +28,7 @@ static struct Device test_device = {
.address = 0, .address = 0,
.name = "test-device", .name = "test-device",
.config = &test_device_config, .config = &test_device_config,
.flags = DEVICE_FLAG_DTS,
.parent = &root, .parent = &root,
.internal = NULL .internal = NULL
}; };
@@ -43,11 +45,12 @@ static struct Device bool_test_device = {
.address = 0, .address = 0,
.name = "bool-test-device", .name = "bool-test-device",
.config = &bool_test_device_config, .config = &bool_test_device_config,
.flags = DEVICE_FLAG_DTS,
.parent = &root, .parent = &root,
.internal = NULL .internal = NULL
}; };
struct DtsDevice dts_devices[] = { const struct DtsDevice dts_devices[] = {
{ &root, "test,root", DTS_DEVICE_STATUS_OKAY }, { &root, "test,root", DTS_DEVICE_STATUS_OKAY },
{ &test_device, "test,generic-device", DTS_DEVICE_STATUS_OKAY }, { &test_device, "test,generic-device", DTS_DEVICE_STATUS_OKAY },
{ &bool_test_device, "test,bool-device", DTS_DEVICE_STATUS_OKAY }, { &bool_test_device, "test,bool-device", DTS_DEVICE_STATUS_OKAY },
@@ -56,7 +59,7 @@ struct DtsDevice dts_devices[] = {
extern struct Module data_module; extern struct Module data_module;
struct Module* dts_modules[] = { struct Module* const dts_modules[] = {
&data_module, &data_module,
NULL NULL
}; };
@@ -7,10 +7,10 @@ extern "C" {
#endif #endif
// Array of device tree modules terminated with DTS_MODULE_TERMINATOR // Array of device tree modules terminated with DTS_MODULE_TERMINATOR
extern struct DtsDevice dts_devices[]; extern const struct DtsDevice dts_devices[];
// Array of module symbols terminated with NULL // Array of module symbols terminated with NULL
extern struct Module* dts_modules[]; extern struct Module* const dts_modules[];
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -311,11 +311,39 @@ def test_compile_missing_config():
print("PASSED") print("PASSED")
return True return True
def test_es3c35p_uses_current_runtime_contract():
print("Running test_es3c35p_uses_current_runtime_contract...")
repository_root = os.path.abspath(os.path.join(SCRIPT_DIR, "..", "..", ".."))
device_dir = os.path.join(repository_root, "Devices", "es3c35p")
with open(os.path.join(device_dir, "device.properties")) as f:
properties = f.read()
with open(os.path.join(device_dir, "es3c35p.dts")) as f:
devicetree = f.read()
requirements = [
("apps.launcherAppId=tactility.launcher" in properties, "current launcher app id"),
("hardware.tinyUsb=" not in properties, "no obsolete hardware.tinyUsb property"),
('wifi0 {\n\t\tcompatible = "espressif,esp32-wifi-pinned";\n\t};' in devicetree,
"Wi-Fi enabled for web server and MCP"),
('ble0 {\n\t\tcompatible = "espressif,esp32-ble";\n\t};' in devicetree,
"BLE node matches hardware.bluetooth=true"),
]
missing = [description for condition, description in requirements if not condition]
if missing:
print("FAILED: " + ", ".join(missing))
return False
print("PASSED")
return True
if __name__ == "__main__": if __name__ == "__main__":
tests = [ tests = [
test_compile_success, test_compile_success,
test_compile_invalid_dts, test_compile_invalid_dts,
test_compile_missing_config, test_compile_missing_config,
test_es3c35p_uses_current_runtime_contract,
test_minmax_within_range_succeeds, test_minmax_within_range_succeeds,
test_minmax_below_minimum_fails, test_minmax_below_minimum_fails,
test_minmax_above_maximum_fails, test_minmax_above_maximum_fails,
+8 -6
View File
@@ -1,19 +1,21 @@
idf_component_register( idf_component_register(
INCLUDE_DIRS INCLUDE_DIRS
"Libraries/TactilityC/include"
"Libraries/TactilityKernel/include" "Libraries/TactilityKernel/include"
"Libraries/TactilityFreeRtos/include" "Libraries/TactilityFreeRtos/Include"
"Libraries/lvgl/include" "Libraries/lvgl/include"
"Libraries/minmea/include"
"Libraries/minitar/include"
"Modules/lvgl-module/include" "Modules/lvgl-module/include"
# DRIVER_INCLUDE_DIRS_PLACEHOLDER REQUIRES esp_timer app-module crypt-module gps-module lvgl-module lvgl-window-manager-module service-module
REQUIRES esp_timer
) )
# Regular and core features # Regular and core features
add_prebuilt_library(TactilityC Libraries/TactilityC/binary/libTactilityC.a)
add_prebuilt_library(TactilityKernel Libraries/TactilityKernel/binary/libTactilityKernel.a) add_prebuilt_library(TactilityKernel Libraries/TactilityKernel/binary/libTactilityKernel.a)
add_prebuilt_library(lvgl Libraries/lvgl/binary/liblvgl.a) add_prebuilt_library(lvgl Libraries/lvgl/binary/liblvgl.a)
add_prebuilt_library(minmea Libraries/minmea/binary/libminmea.a)
add_prebuilt_library(minitar Libraries/minitar/binary/libminitar.a)
target_link_libraries(${COMPONENT_LIB} INTERFACE TactilityC)
target_link_libraries(${COMPONENT_LIB} INTERFACE TactilityKernel) target_link_libraries(${COMPONENT_LIB} INTERFACE TactilityKernel)
target_link_libraries(${COMPONENT_LIB} INTERFACE lvgl) target_link_libraries(${COMPONENT_LIB} INTERFACE lvgl)
target_link_libraries(${COMPONENT_LIB} INTERFACE minmea)
target_link_libraries(${COMPONENT_LIB} INTERFACE minitar)
@@ -1,31 +0,0 @@
function(tactility_project)
endfunction()
function(_tactility_project)
endfunction()
macro(tactility_project project_name)
set(TACTILITY_SKIP_SPIFFS 1)
include("${TACTILITY_SDK_PATH}/Libraries/elf_loader/elf_loader.cmake")
project_elf($project_name)
file(READ ${TACTILITY_SDK_PATH}/idf-version.txt TACTILITY_SDK_IDF_VERSION)
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" TACTILITY_SDK_IDF_MAJOR_MINOR "${TACTILITY_SDK_IDF_VERSION}")
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" CURRENT_IDF_MAJOR_MINOR "$ENV{ESP_IDF_VERSION}")
if (NOT "${CURRENT_IDF_MAJOR_MINOR}" STREQUAL "${TACTILITY_SDK_IDF_MAJOR_MINOR}")
message(FATAL_ERROR "ESP-IDF version of Tactility SDK (${TACTILITY_SDK_IDF_VERSION}) does not match current ESP-IDF version ($ENV{ESP_IDF_VERSION})")
endif()
set(EXTRA_COMPONENT_DIRS
"Libraries/TactilityFreeRtos"
"Modules"
"Drivers"
)
set(COMPONENTS
TactilityFreeRtos
# DRIVER_COMPONENTS_PLACEHOLDER
)
endmacro()
@@ -0,0 +1,62 @@
function(tactility_project)
endfunction()
function(_tactility_project)
endfunction()
macro(tactility_project_pre project_name)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(EXTRA_COMPONENT_DIRS ${TACTILITY_SDK_PATH} ${TACTILITY_SDK_PATH}/Modules)
endmacro()
macro(tactility_project_post project_name)
set(TACTILITY_SKIP_SPIFFS 1)
# Tactility's PanicHandler.cpp needs s0 to stay a frame pointer to capture a callstack for
# a RISC-V app's crashes, which GCC does not guarantee without this flag. The firmware sets the
# same flag for its own code, but a crash usually happens in app code, built separately here.
# Gated to RISC-V since Xtensa never reads s0 this way. idf_build_set_property(), not
# add_compile_options(): the app's code compiles as an idf_component_register() component
# (Apps/*/main/CMakeLists.txt), which reads ESP-IDF's own COMPILE_OPTIONS build property rather
# than plain directory-scoped flags. project_elf() below uses the same property for its own
# flags for the same reason.
if(CONFIG_IDF_TARGET_ARCH_RISCV)
idf_build_set_property(COMPILE_OPTIONS "-fno-omit-frame-pointer" APPEND)
endif()
include("${TACTILITY_SDK_PATH}/Libraries/elf_loader/elf_loader.cmake")
project_elf($project_name)
file(READ ${TACTILITY_SDK_PATH}/idf-version.txt TACTILITY_SDK_IDF_VERSION)
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" TACTILITY_SDK_IDF_MAJOR_MINOR "${TACTILITY_SDK_IDF_VERSION}")
string(REGEX REPLACE "^([0-9]+\\.[0-9]+).*" "\\1" CURRENT_IDF_MAJOR_MINOR "$ENV{ESP_IDF_VERSION}")
if (NOT "${CURRENT_IDF_MAJOR_MINOR}" STREQUAL "${TACTILITY_SDK_IDF_MAJOR_MINOR}")
message(FATAL_ERROR "ESP-IDF version of Tactility SDK (${TACTILITY_SDK_IDF_VERSION}) does not match current ESP-IDF version ($ENV{ESP_IDF_VERSION})")
endif()
set(EXTRA_COMPONENT_DIRS
"${TACTILITY_SDK_PATH}/Libraries/TactilityFreeRtos"
"${TACTILITY_SDK_PATH}/Modules"
)
set(COMPONENTS
TactilityFreeRtos
app-module
crypt-module
gps-module
lvgl-module
lvgl-window-manager-module
service-module
)
endmacro()
macro(tactility_component_register)
cmake_parse_arguments(TT_COMPONENT "" "" "SRCS;INCLUDE_DIRS;REQUIRES;PRIV_REQUIRES" ${ARGN})
idf_component_register(
SRCS ${TT_COMPONENT_SRCS}
INCLUDE_DIRS ${TT_COMPONENT_INCLUDE_DIRS}
REQUIRES TactilitySDK ${TT_COMPONENT_REQUIRES}
PRIV_REQUIRES ${TT_COMPONENT_PRIV_REQUIRES}
)
endmacro()
@@ -0,0 +1,51 @@
function(tactility_project)
endfunction()
function(_tactility_project)
endfunction()
macro(tactility_project_pre project_name)
endmacro()
macro(tactility_project_post project_name)
# The app's own library target is defined in a subdirectory (e.g. "main"); without this it
# would land nested under that subdirectory instead of directly in the build dir.
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# Mirrors the ESP-IDF "TactilitySDK" component (Buildscripts/TactilitySDK/CMakeLists.txt):
# apps link against this single target instead of listing SDK include dirs themselves.
# Posix apps are dlopen()ed into a running Tactility process (see app-posix-module) and
# resolve symbols against Tactility's own copies at load time, so headers are all they need
# at compile time - no libraries to link.
add_library(TactilitySDK INTERFACE)
target_include_directories(TactilitySDK INTERFACE
${TACTILITY_SDK_PATH}/Modules/app-module/include
${TACTILITY_SDK_PATH}/Modules/crypt-module/include
${TACTILITY_SDK_PATH}/Modules/gps-module/include
${TACTILITY_SDK_PATH}/Modules/lvgl-module/include
${TACTILITY_SDK_PATH}/Modules/lvgl-window-manager-module/include
${TACTILITY_SDK_PATH}/Modules/service-module/include
${TACTILITY_SDK_PATH}/Libraries/TactilityKernel/include
${TACTILITY_SDK_PATH}/Libraries/lvgl/include
${TACTILITY_SDK_PATH}/Libraries/FreeRTOS-Kernel/include
${TACTILITY_SDK_PATH}/Libraries/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix
${TACTILITY_SDK_PATH}/Libraries/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils
)
target_compile_definitions(TactilitySDK INTERFACE LV_LVGL_H_INCLUDE_SIMPLE)
# ESP-IDF's project() auto-discovers the "main" component; plain CMake doesn't.
add_subdirectory(main)
endmacro()
macro(tactility_component_register)
cmake_parse_arguments(TT_COMPONENT "" "" "SRCS;INCLUDE_DIRS;REQUIRES;PRIV_REQUIRES" ${ARGN})
# Must be a SHARED object, not a -pie executable: glibc's dlopen() unconditionally refuses
# any ET_DYN carrying the DF_1_PIE flag ("cannot dynamically load position-independent
# executable"), regardless of whether it has a dynamic-linker segment - verified empirically.
add_library(${PROJECT_NAME} SHARED ${TT_COMPONENT_SRCS})
target_link_libraries(${PROJECT_NAME} PRIVATE TactilitySDK)
set_target_properties(${PROJECT_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
if (TT_COMPONENT_INCLUDE_DIRS)
target_include_directories(${PROJECT_NAME} PRIVATE ${TT_COMPONENT_INCLUDE_DIRS})
endif ()
endmacro()
-1
View File
@@ -5,7 +5,6 @@ import time
def build(device: str) -> bool: def build(device: str) -> bool:
print(f"Building {device}...") print(f"Building {device}...")
shutil.rmtree(os.path.join('Firmware', 'Generated'), ignore_errors=True)
result = subprocess.run(['python', 'device.py', device], capture_output=True, text=True) result = subprocess.run(['python', 'device.py', device], capture_output=True, text=True)
if result.returncode != 0: if result.returncode != 0:
print(f"Failed to select device {device}") print(f"Failed to select device {device}")
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Convert an image to an uncompressed LVGL RGB565 launcher background."""
import argparse
import shutil
import struct
import subprocess
from pathlib import Path
LV_IMAGE_HEADER_MAGIC = 0x19
LV_COLOR_FORMAT_RGB565 = 0x12
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(
description=(
"Create an uncompressed LVGL .bin image for "
"/sdcard/tactility/launcher/background.bin. Use a square image sized "
"to the display's longest edge to support both orientations without scaling "
"(for example, 320x320 for a 320x240 display)."
)
)
parser.add_argument("input", type=Path, help="Source image")
parser.add_argument("output", type=Path, help="Destination .bin file")
parser.add_argument("--width", type=int, required=True, help="Output width")
parser.add_argument("--height", type=int, required=True, help="Output height")
return parser.parse_args()
def main() -> None:
args = parse_args()
if args.width <= 0 or args.width > 65535 or args.height <= 0 or args.height > 65535:
raise SystemExit("width and height must be between 1 and 65535")
magick = shutil.which("magick")
if magick is None:
raise SystemExit("ImageMagick is required (the 'magick' command was not found)")
command = [
magick,
str(args.input),
"-resize",
f"{args.width}x{args.height}^",
"-gravity",
"center",
"-extent",
f"{args.width}x{args.height}",
"-depth",
"8",
"rgb:-",
]
rgb888 = subprocess.run(command, check=True, stdout=subprocess.PIPE).stdout
expected_size = args.width * args.height * 3
if len(rgb888) != expected_size:
raise SystemExit(f"unexpected ImageMagick output: {len(rgb888)} bytes, expected {expected_size}")
rgb565 = bytearray(args.width * args.height * 2)
for source_offset in range(0, len(rgb888), 3):
r, g, b = rgb888[source_offset : source_offset + 3]
pixel = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
destination_offset = (source_offset // 3) * 2
struct.pack_into("<H", rgb565, destination_offset, pixel)
stride = args.width * 2
header = struct.pack(
"<BBHHHHH",
LV_IMAGE_HEADER_MAGIC,
LV_COLOR_FORMAT_RGB565,
0,
args.width,
args.height,
stride,
0,
)
args.output.parent.mkdir(parents=True, exist_ok=True)
args.output.write_bytes(header + rgb565)
print(
f"Wrote {args.output} ({args.width}x{args.height}, "
f"{len(header) + len(rgb565)} bytes, uncompressed RGB565)"
)
if __name__ == "__main__":
main()
+25 -2
View File
@@ -2,6 +2,8 @@ if (COMMAND tactility_add_module)
return() return()
endif() endif()
cmake_minimum_required(VERSION 3.24)
macro(tactility_get_module_name NAME OUT_NAME) macro(tactility_get_module_name NAME OUT_NAME)
if (DEFINED ENV{ESP_IDF_VERSION}) if (DEFINED ENV{ESP_IDF_VERSION})
set(${OUT_NAME} ${COMPONENT_LIB}) set(${OUT_NAME} ${COMPONENT_LIB})
@@ -11,21 +13,35 @@ macro(tactility_get_module_name NAME OUT_NAME)
endmacro() endmacro()
macro(tactility_add_module NAME) macro(tactility_add_module NAME)
set(options) # WHOLE_ARCHIVE: force every object file in this module into the final link unconditionally,
# instead of only the ones some other already-scanned archive currently has a pending
# undefined reference to. Needed when this module provides symbols a component it depends on
# (e.g. lvgl__lvgl's custom-allocator hooks) calls back into - a reverse reference a normal
# single-pass static-archive link can't resolve, since that component is scanned after this
# one's archive has already been passed once.
set(options WHOLE_ARCHIVE)
set(oneValueArgs) set(oneValueArgs)
set(multiValueArgs SRCS INCLUDE_DIRS PRIV_INCLUDE_DIRS REQUIRES PRIV_REQUIRES) set(multiValueArgs SRCS INCLUDE_DIRS PRIV_INCLUDE_DIRS REQUIRES PRIV_REQUIRES)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (DEFINED ENV{ESP_IDF_VERSION}) if (DEFINED ENV{ESP_IDF_VERSION})
# idf_component_register's WHOLE_ARCHIVE is a presence-based flag (no value) - only pass
# the token at all when requested, rather than passing ARG_WHOLE_ARCHIVE's TRUE/FALSE as
# a value, which idf_component_register doesn't expect.
set(whole_archive_arg)
if (ARG_WHOLE_ARCHIVE)
set(whole_archive_arg WHOLE_ARCHIVE)
endif()
idf_component_register( idf_component_register(
SRCS ${ARG_SRCS} SRCS ${ARG_SRCS}
INCLUDE_DIRS ${ARG_INCLUDE_DIRS} INCLUDE_DIRS ${ARG_INCLUDE_DIRS}
PRIV_INCLUDE_DIRS ${ARG_PRIV_INCLUDE_DIRS} PRIV_INCLUDE_DIRS ${ARG_PRIV_INCLUDE_DIRS}
REQUIRES ${ARG_REQUIRES} REQUIRES ${ARG_REQUIRES}
PRIV_REQUIRES ${ARG_PRIV_REQUIRES} PRIV_REQUIRES ${ARG_PRIV_REQUIRES}
${whole_archive_arg}
) )
else() else()
add_library(${NAME} OBJECT) add_library(${NAME} STATIC)
target_sources(${NAME} PRIVATE ${ARG_SRCS}) target_sources(${NAME} PRIVATE ${ARG_SRCS})
target_include_directories(${NAME} target_include_directories(${NAME}
PRIVATE ${ARG_PRIV_INCLUDE_DIRS} PRIVATE ${ARG_PRIV_INCLUDE_DIRS}
@@ -33,5 +49,12 @@ macro(tactility_add_module NAME)
) )
target_link_libraries(${NAME} PUBLIC ${ARG_REQUIRES}) target_link_libraries(${NAME} PUBLIC ${ARG_REQUIRES})
target_link_libraries(${NAME} PRIVATE ${ARG_PRIV_REQUIRES}) target_link_libraries(${NAME} PRIVATE ${ARG_PRIV_REQUIRES})
if (ARG_WHOLE_ARCHIVE)
# A static archive only pulls in object files that already have a pending undefined
# reference at the point the archive is scanned, so a plain link drops ${NAME}'s
# reverse dependencies (see WHOLE_ARCHIVE comment above). Make whoever links ${NAME}
# whole-archive it instead of just archive-pruning it.
set_property(TARGET ${NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<LINK_LIBRARY:WHOLE_ARCHIVE,${NAME}>)
endif()
endif() endif()
endmacro() endmacro()
+28 -16
View File
@@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import platform
import shutil import shutil
import subprocess import subprocess
import sys import sys
@@ -17,35 +18,24 @@ def get_idf_target():
return None return None
return None return None
def main(): def get_version():
# 1. Get idf_target
idf_target = get_idf_target()
if not idf_target:
print("Could not determine IDF target from sdkconfig")
sys.exit(1)
# 2. Get version
try: try:
with open("version.txt", "r") as f: with open("version.txt", "r") as f:
version = f.read().strip() return f.read().strip()
except FileNotFoundError: except FileNotFoundError:
print("version.txt not found") print("version.txt not found")
sys.exit(1) sys.exit(1)
# 3. Construct sdk_path def run_release_script(script_name, sdk_path):
# release/TactilitySDK/${version}-${idf_target}/TactilitySDK # Cleanup sdk_path
sdk_path = os.path.join("release", "TactilitySDK", f"{version}-{idf_target}", "TactilitySDK")
# 4. Cleanup sdk_path
if os.path.exists(sdk_path): if os.path.exists(sdk_path):
print(f"Cleaning up {sdk_path}") print(f"Cleaning up {sdk_path}")
shutil.rmtree(sdk_path) shutil.rmtree(sdk_path)
os.makedirs(sdk_path, exist_ok=True) os.makedirs(sdk_path, exist_ok=True)
# 5. Call release-sdk.py
# Note: Using sys.executable to ensure we use the same python interpreter # Note: Using sys.executable to ensure we use the same python interpreter
script_path = os.path.join("Buildscripts", "release-sdk.py") script_path = os.path.join("Buildscripts", script_name)
print(f"Running {script_path} {sdk_path}") print(f"Running {script_path} {sdk_path}")
result = subprocess.run([sys.executable, script_path, sdk_path]) result = subprocess.run([sys.executable, script_path, sdk_path])
@@ -54,5 +44,27 @@ def main():
print(f"Error: {script_path} failed with return code {result.returncode}") print(f"Error: {script_path} failed with return code {result.returncode}")
sys.exit(result.returncode) sys.exit(result.returncode)
def main():
version = get_version()
# ESP_IDF_VERSION is only set once an ESP-IDF environment has been activated (export.sh /
# the Windows PowerShell profile - see building.md); same check release-sdk-esp32.py and
# release-sdk-posix.py themselves use to tell the two builds apart.
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
if esp_idf_version:
idf_target = get_idf_target()
if not idf_target:
print("Could not determine IDF target from sdkconfig")
sys.exit(1)
# release/TactilitySDK/${version}-${idf_target}/TactilitySDK
sdk_path = os.path.join("release", "TactilitySDK", f"{version}-{idf_target}", "TactilitySDK")
run_release_script("release-sdk-esp32.py", sdk_path)
else:
# release/TactilitySDK/${version}-posix-${arch}/TactilitySDK
arch = platform.machine()
sdk_path = os.path.join("release", "TactilitySDK", f"{version}-posix-{arch}", "TactilitySDK")
run_release_script("release-sdk-posix.py", sdk_path)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
+126
View File
@@ -0,0 +1,126 @@
#!/usr/bin/env python3
import os
import glob
import subprocess
import sys
import importlib.util
from textwrap import dedent
_shared_spec = importlib.util.spec_from_file_location("release_sdk_shared", os.path.join("Buildscripts", "release-sdk-shared.py"))
shared = importlib.util.module_from_spec(_shared_spec)
_shared_spec.loader.exec_module(shared)
def get_driver_mappings(driver_name):
return [
{'src': f'Drivers/{driver_name}/include/**', 'dst': f'Drivers/{driver_name}/include/'},
{'src': f'Drivers/{driver_name}/*.md', 'dst': f'Drivers/{driver_name}/'},
{'src': f'build/esp-idf/{driver_name}/lib{driver_name}.a', 'dst': f'Drivers/{driver_name}/binary/lib{driver_name}.a'},
]
def get_module_mappings(module_name):
return [
{'src': f'Modules/{module_name}/include/**', 'dst': f'Modules/{module_name}/include/'},
{'src': f'Modules/{module_name}/*.md', 'dst': f'Modules/{module_name}/'},
{'src': f'build/esp-idf/{module_name}/lib{module_name}.a', 'dst': f'Modules/{module_name}/binary/lib{module_name}.a'},
]
def create_module_cmakelists(module_name):
return dedent(f'''
cmake_minimum_required(VERSION 3.20)
idf_component_register(
INCLUDE_DIRS "include"
)
add_prebuilt_library({module_name} "binary/lib{module_name}.a")
''')
def driver_is_available(driver_name):
"""
Some drivers only build for certain chip targets (e.g. sc2356-module is ESP32-P4 only,
since it depends on esp_video/esp_cam_sensor/PPA which are themselves chip-restricted).
Build output presence is the single source of truth for "does this driver support the
current target" - no separate manifest to keep in sync with the real CMakeLists.txt
REQUIRES/Kconfig guards.
"""
binary_pattern = f'build/esp-idf/{driver_name}/lib{driver_name}.a'
return bool(glob.glob(binary_pattern))
def add_driver(target_path, driver_name):
mappings = get_driver_mappings(driver_name)
shared.map_copy(mappings, target_path)
cmakelists_content = create_module_cmakelists(driver_name)
shared.write_module_cmakelists(os.path.join(target_path, f"Drivers/{driver_name}/CMakeLists.txt"), cmakelists_content)
def add_module(target_path, module_name):
mappings = get_module_mappings(module_name)
shared.map_copy(mappings, target_path)
cmakelists_content = create_module_cmakelists(module_name)
shared.write_module_cmakelists(os.path.join(target_path, f"Modules/{module_name}/CMakeLists.txt"), cmakelists_content)
def main():
if len(sys.argv) < 2:
print("Usage: release-sdk-esp32.py [target_path]")
print("Example: release-sdk-esp32.py release/TactilitySDK")
sys.exit(1)
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
if not esp_idf_version:
print("Error: ESP_IDF_VERSION environment variable is not set")
sys.exit(1)
target_path = os.path.abspath(sys.argv[1])
os.makedirs(target_path, exist_ok=True)
# Mapping logic
mappings = [
{'src': 'version.txt', 'dst': ''},
# TactilityFreeRtos
{'src': 'TactilityFreeRtos/Include/**', 'dst': 'Libraries/TactilityFreeRtos/Include/'},
{'src': 'TactilityFreeRtos/CMakeLists.txt', 'dst': 'Libraries/TactilityFreeRtos/'},
{'src': 'TactilityFreeRtos/LICENSE*.*', 'dst': 'Libraries/TactilityFreeRtos/'},
# TactilityKernel
{'src': 'build/esp-idf/TactilityKernel/libTactilityKernel.a', 'dst': 'Libraries/TactilityKernel/binary/'},
{'src': 'TactilityKernel/include/**', 'dst': 'Libraries/TactilityKernel/include/'},
{'src': 'TactilityKernel/CMakeLists.txt', 'dst': 'Libraries/TactilityKernel/'},
{'src': 'TactilityKernel/*.md', 'dst': 'Libraries/TactilityKernel/'},
# lvgl (basics)
{'src': 'build/esp-idf/lvgl__lvgl/liblvgl__lvgl.a', 'dst': 'Libraries/lvgl/binary/liblvgl.a'},
{'src': 'Libraries/lvgl/lvgl.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/lv_version.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/LICENCE*.*', 'dst': 'Libraries/lvgl/'},
{'src': 'Libraries/lvgl/src/lv_conf_kconfig.h', 'dst': 'Libraries/lvgl/include/lv_conf.h'},
{'src': 'Libraries/lvgl/src/**/*.h', 'dst': 'Libraries/lvgl/include/src/'},
# elf_loader
{'src': 'managed_components/espressif__elf_loader/*.cmake', 'dst': 'Libraries/elf_loader/'},
{'src': 'managed_components/espressif__elf_loader/*.lf', 'dst': 'Libraries/elf_loader/'},
{'src': 'managed_components/espressif__elf_loader/license.txt', 'dst': 'Libraries/elf_loader/'},
# minitar
{'src': 'build/esp-idf/minitar/libminitar.a', 'dst': 'Libraries/minitar/binary/'},
{'src': 'Libraries/minitar/minitar/minitar.h', 'dst': 'Libraries/minitar/include/'},
{'src': 'Libraries/minitar/minitar/LICENSE*', 'dst': 'Libraries/minitar/'},
# minmea
{'src': 'build/esp-idf/minmea/libminmea.a', 'dst': 'Libraries/minmea/binary/'},
{'src': 'Libraries/minmea/Include/**', 'dst': 'Libraries/minmea/include/'},
{'src': 'Libraries/minmea/CMakeLists.txt', 'dst': 'Libraries/minmea/'},
{'src': 'Libraries/minmea/README.md', 'dst': 'Libraries/minmea/'},
{'src': 'Libraries/minmea/LICENSE*.*', 'dst': 'Libraries/minmea/'},
{'src': 'Libraries/minmea/COPYING', 'dst': 'Libraries/minmea/'},
]
shared.map_copy(mappings, target_path)
# Modules
module_names = shared.read_module_list(os.path.join('Buildscripts', 'release-sdk-modules.txt'))
for module_name in module_names:
add_module(target_path, module_name)
# Final scripts - copied verbatim
shared.generate_tactility_sdk_cmake(target_path, 'esp32')
shared.generate_tactility_sdk_top_cmakelists(target_path)
# Output ESP-IDF SDK version to file
with open(os.path.join(target_path, "idf-version.txt"), "a") as f:
f.write(esp_idf_version)
if __name__ == "__main__":
main()
+7
View File
@@ -0,0 +1,7 @@
app-module
crypt-module
gps-module
http-module
lvgl-module
lvgl-window-manager-module
service-module
+101
View File
@@ -0,0 +1,101 @@
#!/usr/bin/env python3
import os
import sys
import importlib.util
from textwrap import dedent
_shared_spec = importlib.util.spec_from_file_location("release_sdk_shared", os.path.join("Buildscripts", "release-sdk-shared.py"))
shared = importlib.util.module_from_spec(_shared_spec)
_shared_spec.loader.exec_module(shared)
def get_module_mappings(module_name):
return [
{'src': f'Modules/{module_name}/include/**', 'dst': f'Modules/{module_name}/include/'},
{'src': f'Modules/{module_name}/*.md', 'dst': f'Modules/{module_name}/'},
{'src': f'buildsim/Modules/{module_name}/lib{module_name}.a', 'dst': f'Modules/{module_name}/binary/lib{module_name}.a'},
]
def create_module_cmakelists(module_name):
return dedent(f'''
cmake_minimum_required(VERSION 3.20)
add_library({module_name} STATIC IMPORTED)
set_target_properties({module_name} PROPERTIES
IMPORTED_LOCATION "${{CMAKE_CURRENT_LIST_DIR}}/binary/lib{module_name}.a"
INTERFACE_INCLUDE_DIRECTORIES "${{CMAKE_CURRENT_LIST_DIR}}/include"
)
''')
def add_module(target_path, module_name):
mappings = get_module_mappings(module_name)
shared.map_copy(mappings, target_path)
cmakelists_content = create_module_cmakelists(module_name)
shared.write_module_cmakelists(os.path.join(target_path, f"Modules/{module_name}/CMakeLists.txt"), cmakelists_content)
def main():
if len(sys.argv) < 2:
print("Usage: release-sdk-posix.py [target_path]")
print("Example: release-sdk-posix.py release/TactilitySDK")
sys.exit(1)
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
if esp_idf_version:
print("Error: ESP_IDF_VERSION environment variable is set - this script packages the POSIX/simulator build, run it outside an ESP-IDF environment")
sys.exit(1)
target_path = os.path.abspath(sys.argv[1])
os.makedirs(target_path, exist_ok=True)
# Mapping logic
mappings = [
{'src': 'version.txt', 'dst': ''},
# TactilityFreeRtos
{'src': 'TactilityFreeRtos/Include/**', 'dst': 'Libraries/TactilityFreeRtos/Include/'},
{'src': 'TactilityFreeRtos/CMakeLists.txt', 'dst': 'Libraries/TactilityFreeRtos/'},
{'src': 'TactilityFreeRtos/LICENSE*.*', 'dst': 'Libraries/TactilityFreeRtos/'},
# TactilityKernel
{'src': 'buildsim/TactilityKernel/libTactilityKernel.a', 'dst': 'Libraries/TactilityKernel/binary/'},
{'src': 'TactilityKernel/include/**', 'dst': 'Libraries/TactilityKernel/include/'},
{'src': 'TactilityKernel/CMakeLists.txt', 'dst': 'Libraries/TactilityKernel/'},
{'src': 'TactilityKernel/*.md', 'dst': 'Libraries/TactilityKernel/'},
# FreeRTOS-Kernel - TactilityKernel's public headers (tactility/freertos/*.h) include the
# real FreeRTOS.h/task.h/etc directly, unlike ESP32 where ESP-IDF's own "freertos"
# component and Kconfig-generated FreeRTOSConfig.h are already part of every project.
{'src': 'Libraries/FreeRTOS-Kernel/include/**', 'dst': 'Libraries/FreeRTOS-Kernel/include/'},
{'src': 'Libraries/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/*.h', 'dst': 'Libraries/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/'},
{'src': 'Libraries/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils/*.h', 'dst': 'Libraries/FreeRTOS-Kernel/portable/ThirdParty/GCC/Posix/utils/'},
{'src': 'Libraries/FreeRTOS-Kernel/LICENSE*.*', 'dst': 'Libraries/FreeRTOS-Kernel/'},
{'src': 'Devices/simulator/Source/FreeRTOSConfig.h', 'dst': 'Libraries/FreeRTOS-Kernel/include/'},
# lvgl (basics)
{'src': 'buildsim/Libraries/lvgl/lib/liblvgl.a', 'dst': 'Libraries/lvgl/binary/liblvgl.a'},
{'src': 'Libraries/lvgl/lvgl.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/lv_version.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/LICENCE*.*', 'dst': 'Libraries/lvgl/'},
{'src': 'lv_conf.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/src/**/*.h', 'dst': 'Libraries/lvgl/include/src/'},
# minitar
{'src': 'buildsim/Libraries/minitar/libminitar.a', 'dst': 'Libraries/minitar/binary/'},
{'src': 'Libraries/minitar/minitar/minitar.h', 'dst': 'Libraries/minitar/include/'},
{'src': 'Libraries/minitar/minitar/LICENSE*', 'dst': 'Libraries/minitar/'},
# minmea
{'src': 'buildsim/Libraries/minmea/libminmea.a', 'dst': 'Libraries/minmea/binary/'},
{'src': 'Libraries/minmea/Include/**', 'dst': 'Libraries/minmea/include/'},
{'src': 'Libraries/minmea/CMakeLists.txt', 'dst': 'Libraries/minmea/'},
{'src': 'Libraries/minmea/README.md', 'dst': 'Libraries/minmea/'},
{'src': 'Libraries/minmea/LICENSE*.*', 'dst': 'Libraries/minmea/'},
{'src': 'Libraries/minmea/COPYING', 'dst': 'Libraries/minmea/'},
]
shared.map_copy(mappings, target_path)
# Modules
module_names = shared.read_module_list(os.path.join('Buildscripts', 'release-sdk-modules.txt'))
for module_name in module_names:
add_module(target_path, module_name)
# Final scripts - copied verbatim
shared.generate_tactility_sdk_cmake(target_path, 'posix')
shared.generate_tactility_sdk_top_cmakelists(target_path)
if __name__ == "__main__":
main()
+91
View File
@@ -0,0 +1,91 @@
#!/usr/bin/env python3
# Functions shared between release-sdk-esp32.py and release-sdk-posix.py. Not runnable on its
# own; loaded by those scripts via importlib (its hyphenated filename isn't a valid Python
# module name for a plain "import").
import os
import shutil
import glob
import sys
def map_copy(mappings, target_base):
"""
Helper function to map input files/directories to output files/directories.
mappings: list of dicts with 'src' (glob pattern) and 'dst' (relative to target_base or absolute)
'src' can be a single file or a directory (if it ends with /).
"""
for mapping in mappings:
src_pattern = mapping['src']
dst_rel = mapping['dst']
dst_path = os.path.join(target_base, dst_rel)
# To preserve directory structure, we need to know where the wildcard starts
# or have a way to determine the "base" of the search.
# We'll split the pattern into a fixed base and a pattern part.
# Simple heuristic: find the first occurrence of '*' or '?'
wildcard_idx = -1
for i, char in enumerate(src_pattern):
if char in '*?':
wildcard_idx = i
break
if wildcard_idx != -1:
# Found a wildcard. The base is the directory containing it.
pattern_base = os.path.dirname(src_pattern[:wildcard_idx])
else:
# No wildcard. If it's a directory, we might want to preserve its name?
# For now, let's treat no-wildcard as no relative structure needed.
pattern_base = None
src_files = glob.glob(src_pattern, recursive=True)
if not src_files:
continue
for src in src_files:
if os.path.isdir(src):
continue
if pattern_base and src.startswith(pattern_base):
# Calculate relative path from the base of the glob pattern
rel_src = os.path.relpath(src, pattern_base)
# If dst_rel ends with /, it's a target directory
if dst_rel.endswith('/') or os.path.isdir(dst_path):
final_dst = os.path.join(dst_path, rel_src)
else:
# If dst_rel is a file, we can't really preserve structure
# unless we join it. But usually it's a dir if structure is preserved.
final_dst = dst_path
else:
final_dst = dst_path if not (dst_rel.endswith('/') or os.path.isdir(dst_path)) else os.path.join(dst_path, os.path.basename(src))
os.makedirs(os.path.dirname(final_dst), exist_ok=True)
shutil.copy2(src, final_dst)
def write_module_cmakelists(path, content):
with open(path, 'w') as f:
f.write(content)
def read_module_list(path):
"""Reads a newline-separated module name list, skipping empty lines, and checks that each
named module actually exists under Modules/ - exits the process with an error if not."""
with open(path, 'r') as f:
module_names = [line.strip() for line in f if line.strip()]
for module_name in module_names:
if not os.path.isdir(os.path.join('Modules', module_name)):
print(f"Error: Modules/{module_name} does not exist (listed in {path})")
sys.exit(1)
return module_names
def generate_tactility_sdk_cmake(target_path, variant):
"""variant selects Buildscripts/TactilitySDK/TactilitySDK.{variant}.cmake (e.g. "esp32" or
"posix") - always copied into the SDK as the platform-neutral name TactilitySDK.cmake."""
src = os.path.join('Buildscripts', 'TactilitySDK', f'TactilitySDK.{variant}.cmake')
shutil.copy2(src, os.path.join(target_path, 'TactilitySDK.cmake'))
def generate_tactility_sdk_top_cmakelists(target_path):
src = os.path.join('Buildscripts', 'TactilitySDK', 'CMakeLists.txt')
shutil.copy2(src, os.path.join(target_path, 'CMakeLists.txt'))
-213
View File
@@ -1,213 +0,0 @@
#!/usr/bin/env python3
import os
import shutil
import glob
import subprocess
import sys
from textwrap import dedent
def map_copy(mappings, target_base):
"""
Helper function to map input files/directories to output files/directories.
mappings: list of dicts with 'src' (glob pattern) and 'dst' (relative to target_base or absolute)
'src' can be a single file or a directory (if it ends with /).
"""
for mapping in mappings:
src_pattern = mapping['src']
dst_rel = mapping['dst']
dst_path = os.path.join(target_base, dst_rel)
# To preserve directory structure, we need to know where the wildcard starts
# or have a way to determine the "base" of the search.
# We'll split the pattern into a fixed base and a pattern part.
# Simple heuristic: find the first occurrence of '*' or '?'
wildcard_idx = -1
for i, char in enumerate(src_pattern):
if char in '*?':
wildcard_idx = i
break
if wildcard_idx != -1:
# Found a wildcard. The base is the directory containing it.
pattern_base = os.path.dirname(src_pattern[:wildcard_idx])
else:
# No wildcard. If it's a directory, we might want to preserve its name?
# For now, let's treat no-wildcard as no relative structure needed.
pattern_base = None
src_files = glob.glob(src_pattern, recursive=True)
if not src_files:
continue
for src in src_files:
if os.path.isdir(src):
continue
if pattern_base and src.startswith(pattern_base):
# Calculate relative path from the base of the glob pattern
rel_src = os.path.relpath(src, pattern_base)
# If dst_rel ends with /, it's a target directory
if dst_rel.endswith('/') or os.path.isdir(dst_path):
final_dst = os.path.join(dst_path, rel_src)
else:
# If dst_rel is a file, we can't really preserve structure
# unless we join it. But usually it's a dir if structure is preserved.
final_dst = dst_path
else:
final_dst = dst_path if not (dst_rel.endswith('/') or os.path.isdir(dst_path)) else os.path.join(dst_path, os.path.basename(src))
os.makedirs(os.path.dirname(final_dst), exist_ok=True)
shutil.copy2(src, final_dst)
def get_driver_mappings(driver_name):
return [
{'src': f'Drivers/{driver_name}/include/**', 'dst': f'Drivers/{driver_name}/include/'},
{'src': f'Drivers/{driver_name}/*.md', 'dst': f'Drivers/{driver_name}/'},
{'src': f'build/esp-idf/{driver_name}/lib{driver_name}.a', 'dst': f'Drivers/{driver_name}/binary/lib{driver_name}.a'},
]
def get_module_mappings(module_name):
return [
{'src': f'Modules/{module_name}/include/**', 'dst': f'Modules/{module_name}/include/'},
{'src': f'Modules/{module_name}/*.md', 'dst': f'Modules/{module_name}/'},
{'src': f'build/esp-idf/{module_name}/lib{module_name}.a', 'dst': f'Modules/{module_name}/binary/lib{module_name}.a'},
]
def create_module_cmakelists(module_name):
return dedent(f'''
cmake_minimum_required(VERSION 3.20)
idf_component_register(
INCLUDE_DIRS "include"
)
add_prebuilt_library({module_name} "binary/lib{module_name}.a")
'''.format(module_name=module_name))
def write_module_cmakelists(path, content):
with open(path, 'w') as f:
f.write(content)
def driver_is_available(driver_name):
"""
Some drivers only build for certain chip targets (e.g. sc2356-module is ESP32-P4 only,
since it depends on esp_video/esp_cam_sensor/PPA which are themselves chip-restricted).
Build output presence is the single source of truth for "does this driver support the
current target" - no separate manifest to keep in sync with the real CMakeLists.txt
REQUIRES/Kconfig guards.
"""
binary_pattern = f'build/esp-idf/{driver_name}/lib{driver_name}.a'
return bool(glob.glob(binary_pattern))
def add_driver(target_path, driver_name):
mappings = get_driver_mappings(driver_name)
map_copy(mappings, target_path)
cmakelists_content = create_module_cmakelists(driver_name)
write_module_cmakelists(os.path.join(target_path, f"Drivers/{driver_name}/CMakeLists.txt"), cmakelists_content)
def add_module(target_path, module_name):
mappings = get_module_mappings(module_name)
map_copy(mappings, target_path)
cmakelists_content = create_module_cmakelists(module_name)
write_module_cmakelists(os.path.join(target_path, f"Modules/{module_name}/CMakeLists.txt"), cmakelists_content)
def discover_all_drivers():
"""
Discover all *-module directories under Drivers/ (not Modules/ - those are handled
separately via add_module). Sorted for deterministic output across OS/filesystem order.
"""
pattern = os.path.join('Drivers', '*-module')
return sorted(
os.path.basename(p) for p in glob.glob(pattern) if os.path.isdir(p)
)
def generate_tactility_sdk_cmake(target_path, available_drivers):
src = os.path.join('Buildscripts', 'TactilitySDK', 'TactilitySDK.cmake')
with open(src) as f:
content = f.read()
placeholder = " # DRIVER_COMPONENTS_PLACEHOLDER"
assert placeholder in content, \
f"Placeholder '{placeholder.strip()}' not found in {src} - template drifted, generator needs updating"
components = "\n".join(f" {d}" for d in available_drivers)
new_content = content.replace(placeholder, components)
assert placeholder not in new_content, \
f"Placeholder '{placeholder.strip()}' still present after replacement in {src}"
with open(os.path.join(target_path, 'TactilitySDK.cmake'), 'w') as f:
f.write(new_content)
def generate_tactility_sdk_top_cmakelists(target_path, available_drivers):
src = os.path.join('Buildscripts', 'TactilitySDK', 'CMakeLists.txt')
with open(src) as f:
content = f.read()
placeholder = " # DRIVER_INCLUDE_DIRS_PLACEHOLDER"
assert placeholder in content, \
f"Placeholder '{placeholder.strip()}' not found in {src} - template drifted, generator needs updating"
include_dirs = "\n".join(f' "Drivers/{d}/include"' for d in available_drivers)
new_content = content.replace(placeholder, include_dirs)
assert placeholder not in new_content, \
f"Placeholder '{placeholder.strip()}' still present after replacement in {src}"
with open(os.path.join(target_path, 'CMakeLists.txt'), 'w') as f:
f.write(new_content)
def main():
if len(sys.argv) < 2:
print("Usage: release-sdk.py [target_path]")
print("Example: release-sdk.py release/TactilitySDK")
sys.exit(1)
target_path = os.path.abspath(sys.argv[1])
os.makedirs(target_path, exist_ok=True)
# Mapping logic
mappings = [
{'src': 'version.txt', 'dst': ''},
# TactilityC
{'src': 'build/esp-idf/TactilityC/libTactilityC.a', 'dst': 'Libraries/TactilityC/binary/'},
{'src': 'TactilityC/Include/*', 'dst': 'Libraries/TactilityC/include/'},
{'src': 'TactilityC/CMakeLists.txt', 'dst': 'Libraries/TactilityC/'},
{'src': 'TactilityC/LICENSE*.*', 'dst': 'Libraries/TactilityC/'},
# TactilityFreeRtos
{'src': 'TactilityFreeRtos/Include/**', 'dst': 'Libraries/TactilityFreeRtos/include/'},
{'src': 'TactilityFreeRtos/CMakeLists.txt', 'dst': 'Libraries/TactilityFreeRtos/'},
{'src': 'TactilityFreeRtos/LICENSE*.*', 'dst': 'Libraries/TactilityFreeRtos/'},
# TactilityKernel
{'src': 'build/esp-idf/TactilityKernel/libTactilityKernel.a', 'dst': 'Libraries/TactilityKernel/binary/'},
{'src': 'TactilityKernel/include/**', 'dst': 'Libraries/TactilityKernel/include/'},
{'src': 'TactilityKernel/CMakeLists.txt', 'dst': 'Libraries/TactilityKernel/'},
{'src': 'TactilityKernel/*.md', 'dst': 'Libraries/TactilityKernel/'},
# lvgl (basics)
{'src': 'build/esp-idf/lvgl__lvgl/liblvgl__lvgl.a', 'dst': 'Libraries/lvgl/binary/liblvgl.a'},
{'src': 'Libraries/lvgl/lvgl.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/lv_version.h', 'dst': 'Libraries/lvgl/include/'},
{'src': 'Libraries/lvgl/LICENCE*.*', 'dst': 'Libraries/lvgl/'},
{'src': 'Libraries/lvgl/src/lv_conf_kconfig.h', 'dst': 'Libraries/lvgl/include/lv_conf.h'},
{'src': 'Libraries/lvgl/src/**/*.h', 'dst': 'Libraries/lvgl/include/src/'},
# elf_loader
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
{'src': 'Libraries/elf_loader/license.txt', 'dst': 'Libraries/elf_loader/'},
]
map_copy(mappings, target_path)
# Modules
add_module(target_path, "lvgl-module")
add_module(target_path, "crypt-module")
# Drivers - only ones actually built for this target (chip-restricted drivers like
# sc2356-module won't have a .a outside ESP32-P4)
available_drivers = [d for d in discover_all_drivers() if driver_is_available(d)]
for driver_name in available_drivers:
add_driver(target_path, driver_name)
# Final scripts - generated (not copied verbatim) so COMPONENTS/INCLUDE_DIRS only list
# drivers actually available for this target
generate_tactility_sdk_cmake(target_path, available_drivers)
generate_tactility_sdk_top_cmakelists(target_path, available_drivers)
# Output ESP-IDF SDK version to file
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
with open(os.path.join(target_path, "idf-version.txt"), "a") as f:
f.write(esp_idf_version)
if __name__ == "__main__":
main()
@@ -0,0 +1,61 @@
#!/bin/sh
# Usage: release-simulator-macos-app.sh [builddir] [Tactility.app]
# Example: release-simulator-macos-app.sh buildsim release/Tactility.app
set -eu
build_path=$1
bundle_path=$2
if [ -e "$bundle_path" ]; then
echo "Refusing to overwrite existing bundle: $bundle_path" >&2
exit 1
fi
contents_path="$bundle_path/Contents"
resources_path="$contents_path/Resources"
macos_path="$contents_path/MacOS"
mkdir -p "$resources_path" "$macos_path"
cp "$build_path/Tactility/Tactility" "$resources_path/Tactility-bin"
cp version.txt "$resources_path/"
cp -R Data/data "$resources_path/"
cp -R Data/system "$resources_path/"
cat > "$contents_path/Info.plist" <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>Tactility</string>
<key>CFBundleIdentifier</key>
<string>org.tactilityproject.simulator</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Tactility</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.0-dev</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
EOF
cat > "$macos_path/Tactility" <<'EOF'
#!/bin/sh
set -eu
resources_path="$(CDPATH= cd -- "$(dirname -- "$0")/../Resources" && pwd)"
cd "$resources_path"
exec "$resources_path/Tactility-bin" "$@"
EOF
chmod +x "$macos_path/Tactility" "$resources_path/Tactility-bin"
+5 -5
View File
@@ -9,9 +9,9 @@
build_path=$1 build_path=$1
target_path=$2 target_path=$2
mkdir -p $target_path mkdir -p "$target_path"
cp version.txt $target_path cp version.txt "$target_path"
cp $build_path/Firmware/FirmwareSim $target_path/ cp "$build_path/Tactility/Tactility" "$target_path/"
cp -r Data/data $target_path/ cp -r Data/data "$target_path/"
cp -r Data/system $target_path/ cp -r Data/system "$target_path/"
+10 -2
View File
@@ -1,6 +1,6 @@
# Increase stack size for Wi-Fi (fixes crash after scan) # Increase stack size for Wi-Fi (fixes crash after scan)
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=3072
# Ensure large enough stack for network operations # Ensure large enough stack for network operations (e.g. AppHub)
CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144 CONFIG_ESP_MAIN_TASK_STACK_SIZE=6144
# Fixes static assertion: FLASH and PSRAM Mode configuration are not supported # Fixes static assertion: FLASH and PSRAM Mode configuration are not supported
CONFIG_IDF_EXPERIMENTAL_FEATURES=y CONFIG_IDF_EXPERIMENTAL_FEATURES=y
@@ -11,6 +11,12 @@ CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
# EmbedTLS # EmbedTLS
# Use TLS 1.2 because 1.3 conflicts with MbedTLS dynamic buffer # Use TLS 1.2 because 1.3 conflicts with MbedTLS dynamic buffer
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
# Frees TLS IN/OUT buffers between reads/writes instead of holding them for the whole session.
# Internal-RAM-only devices need this: mbedtls_ssl_setup() otherwise fails with ALLOC_FAILED
# (-0x7F00).
# Keep MBEDTLS_SSL_IN_CONTENT_LEN at its 16384 default: servers may send TLS records up to that
# size, and a smaller buffer fails mid-transfer with MBEDTLS_ERR_SSL_INVALID_RECORD (-0x7200).
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
# LVGL # LVGL
CONFIG_LV_USE_USER_DATA=y CONFIG_LV_USE_USER_DATA=y
CONFIG_LV_USE_FS_STDIO=y CONFIG_LV_USE_FS_STDIO=y
@@ -19,7 +25,9 @@ CONFIG_LV_FS_STDIO_PATH=""
CONFIG_LV_FS_STDIO_CACHE_SIZE=4096 CONFIG_LV_FS_STDIO_CACHE_SIZE=4096
CONFIG_LV_USE_LODEPNG=y CONFIG_LV_USE_LODEPNG=y
CONFIG_LV_USE_BUILTIN_MALLOC=n CONFIG_LV_USE_BUILTIN_MALLOC=n
CONFIG_LV_USE_CLIB_MALLOC=y # Routes lv_malloc/realloc/free through Modules/lvgl-module/source/lv_mem_custom.c, which prefers
# PSRAM (falls back to internal RAM automatically) instead of a fixed-size pool or plain malloc.
CONFIG_LV_USE_CUSTOM_MALLOC=y
CONFIG_LV_USE_MSGBOX=n CONFIG_LV_USE_MSGBOX=n
CONFIG_LV_USE_SPINNER=n CONFIG_LV_USE_SPINNER=n
CONFIG_LV_USE_WIN=n CONFIG_LV_USE_WIN=n
-1
View File
@@ -1 +0,0 @@
Documentation/README.md
+52 -17
View File
@@ -33,18 +33,23 @@ if (DEFINED ENV{ESP_IDF_VERSION})
message("Using ESP-IDF ${Cyan}v$ENV{ESP_IDF_VERSION}${ColorReset}") message("Using ESP-IDF ${Cyan}v$ENV{ESP_IDF_VERSION}${ColorReset}")
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS Firmware) set(COMPONENTS Tactility)
set(EXTRA_COMPONENT_DIRS set(EXTRA_COMPONENT_DIRS
"Firmware" # Tactility must be discovered first: its CMakeLists.txt calls init_tactility_globals(),
# which other components' CMakeLists.txt (e.g. lvgl-module) rely on having already run to
# read back TACTILITY_DEVICE_ID/TACTILITY_DEVICE_PROJECT via get_property(). ESP-IDF's
# requirements-discovery pass processes EXTRA_COMPONENT_DIRS in an isolated sub-process, in
# the order listed here, so this must stay first now that Firmware no longer exists as a
# separate component.
"Tactility"
"Devices/${TACTILITY_DEVICE_PROJECT}" "Devices/${TACTILITY_DEVICE_PROJECT}"
"Drivers" "Drivers"
"Modules" "Modules"
"Platforms/platform-esp32" "Platforms/platform-esp32"
"TactilityKernel" "TactilityKernel"
"Tactility" "TactilityKernelCpp"
"TactilityC"
"TactilityFreeRtos" "TactilityFreeRtos"
"Libraries/elf_loader" "Libraries/esp_epaper"
"Libraries/lv_screenshot" "Libraries/lv_screenshot"
"Libraries/minitar" "Libraries/minitar"
"Libraries/minmea" "Libraries/minmea"
@@ -53,10 +58,17 @@ if (DEFINED ENV{ESP_IDF_VERSION})
set(EXCLUDE_COMPONENTS "Simulator") set(EXCLUDE_COMPONENTS "Simulator")
# Panic handler wrapping is only available on Xtensa architecture # panic_info_t is architecture-independent (esp_private/panic_internal.h) so this wrap applies
if (CONFIG_IDF_TARGET_ARCH_XTENSA) # to every target; PanicHandler.cpp branches internally per architecture.
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND) idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)
endif ()
# Wraps newlib's reentrant syscall stubs, not the plain read()/write()/close() newlib itself
# implements as thin wrappers around them. newlib's own stdio (fflush()'s buffer-flush path in particular)
# calls these _r stubs directly, bypassing the plain names entirely.
# See Modules/app-module/source/stdio_wrap.cpp's own comment for the exact call chain.
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=_read_r" APPEND)
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=_write_r" APPEND)
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=_close_r" APPEND)
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=lv_button_create" APPEND) idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=lv_button_create" APPEND)
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=lv_dropdown_create" APPEND) idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=lv_dropdown_create" APPEND)
@@ -69,26 +81,39 @@ if (DEFINED ENV{ESP_IDF_VERSION})
else () else ()
message("Building for sim target") message("Building for sim target")
# Devices/simulator/Source/Simulator.cpp always defines its own hardwareConfiguration; without # eps-idf generates these from Kconfig, but posix build isn't set up with Kconfig.
# this, Firmware/Source/Main.cpp's #else branch also defines an empty one (its ESP32-only
# fallback for devices migrated off the deprecated HAL), causing a duplicate-definition link error.
add_compile_definitions(CONFIG_TT_USE_DEPRECATED_HAL)
add_compile_definitions(CONFIG_TT_DEVICE_ID="simulator") add_compile_definitions(CONFIG_TT_DEVICE_ID="simulator")
add_compile_definitions(CONFIG_TT_DEVICE_NAME="Simulator") add_compile_definitions(CONFIG_TT_DEVICE_NAME="Simulator")
add_compile_definitions(CONFIG_TT_DEVICE_VENDOR="") add_compile_definitions(CONFIG_TT_DEVICE_VENDOR="")
add_compile_definitions(CONFIG_TT_DEVICE_NAME_SIMPLE="Simulator") add_compile_definitions(CONFIG_TT_DEVICE_NAME_SIMPLE="Simulator")
add_compile_definitions(CONFIG_TT_LAUNCHER_APP_ID="Launcher") add_compile_definitions(CONFIG_TT_LAUNCHER_APP_ID="tactility.launcher")
add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="") add_compile_definitions(CONFIG_TT_AUTO_START_APP_ID="")
add_compile_definitions(CONFIG_TT_USER_DATA_LOCATION_INTERNAL) add_compile_definitions(CONFIG_TT_USER_DATA_LOCATION_INTERNAL)
endif () endif ()
project(Tactility) project(Tactility)
if (DEFINED ENV{ESP_IDF_VERSION})
# PanicHandler.cpp's RISC-V callstack walker requires s0 to stay a frame pointer, which GCC
# does not guarantee without this flag. CONFIG_ESP_SYSTEM_USE_FRAME_POINTER does not add it
# (it only selects which ESP-IDF backtrace-printing function gets compiled), and can't be used
# instead: the bootloader shares this project's sdkconfig with no per-subproject override, and
# enabling it there overflows the bootloader's fixed partition budget. Setting the flag here via
# idf_build_set_property() only affects this project's own configure, not the bootloader's
# separate one, so it's naturally excluded. Gated to RISC-V since Xtensa never reads s0 this way.
# Must run after project(Tactility) above - project() initializes default build specifications
# that would otherwise overwrite this.
if(CONFIG_IDF_TARGET_ARCH_RISCV)
idf_build_set_property(COMPILE_OPTIONS "-fno-omit-frame-pointer" APPEND)
endif()
endif ()
# Defined as regular project for PC and component for ESP # Defined as regular project for PC and component for ESP
if (NOT DEFINED ENV{ESP_IDF_VERSION}) if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Tactility) add_subdirectory(Tactility)
add_subdirectory(TactilityFreeRtos) add_subdirectory(TactilityFreeRtos)
add_subdirectory(TactilityKernel) add_subdirectory(TactilityKernel)
add_subdirectory(TactilityKernelCpp)
add_subdirectory(Platforms/platform-posix) add_subdirectory(Platforms/platform-posix)
add_subdirectory(Devices/simulator) add_subdirectory(Devices/simulator)
add_subdirectory(Libraries/cJSON) add_subdirectory(Libraries/cJSON)
@@ -96,9 +121,22 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Libraries/QRCode) add_subdirectory(Libraries/QRCode)
add_subdirectory(Libraries/minitar) add_subdirectory(Libraries/minitar)
add_subdirectory(Libraries/minmea) add_subdirectory(Libraries/minmea)
add_subdirectory(Modules/hal-device-module)
add_subdirectory(Modules/lvgl-module) add_subdirectory(Modules/lvgl-module)
add_subdirectory(Modules/c-symbols-module)
add_subdirectory(Modules/cpp-symbols-module)
add_subdirectory(Modules/crypt-module) add_subdirectory(Modules/crypt-module)
add_subdirectory(Modules/freertos-module)
add_subdirectory(Modules/gps-module)
add_subdirectory(Modules/http-module)
add_subdirectory(Modules/mbedtls-module)
add_subdirectory(Modules/posix-symbols-module)
add_subdirectory(Modules/pthread-module)
add_subdirectory(Modules/service-module)
add_subdirectory(Modules/app-module)
add_subdirectory(Modules/app-posix-module)
add_subdirectory(Modules/lvgl-window-manager-module)
add_subdirectory(Drivers/gps-generic-module)
add_subdirectory(Drivers/gps-meshtastic-module)
# FreeRTOS # FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "") set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
@@ -122,9 +160,6 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(Libraries/lvgl) # Added as idf component for ESP and as library for other targets add_subdirectory(Libraries/lvgl) # Added as idf component for ESP and as library for other targets
target_link_libraries(lvgl PRIVATE SDL2-static) target_link_libraries(lvgl PRIVATE SDL2-static)
# Sim app
add_subdirectory(Firmware)
# Tests # Tests
add_subdirectory(Tests) add_subdirectory(Tests)
@@ -17,7 +17,7 @@ apOpenNetwork=0
apChannel=1 apChannel=1
# Web Server Settings # Web Server Settings
webServerEnabled=0 webServerEnabled=1
webServerPort=80 webServerPort=80
# HTTP Basic Authentication (optional) # HTTP Basic Authentication (optional)
Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

+1 -1
View File
@@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register( idf_component_register(
SRCS ${SOURCE_FILES} SRCS ${SOURCE_FILES}
INCLUDE_DIRS "source" INCLUDE_DIRS "source"
REQUIRES Tactility REQUIRES TactilityKernel
) )
@@ -18,12 +18,10 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
ble0 { ble0 {
compatible = "espressif,esp32-ble"; compatible = "espressif,esp32-ble";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,7 +1,7 @@
general.vendor=BigTreeTech general.vendor=BigTreeTech
general.name=Panda Touch,K Touch general.name=Panda Touch,K Touch
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32S3 hardware.target=ESP32S3
hardware.flashSize=16MB hardware.flashSize=16MB
@@ -12,8 +12,6 @@ hardware.esptoolFlashFreq=120M
hardware.bluetooth=true hardware.bluetooth=true
hardware.usbHostEnabled=true hardware.usbHostEnabled=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=Internal storage.userDataLocation=Internal
display.size=5" display.size=5"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module btt_panda_touch_module = {
return ERROR_NONE; .name = "btt-panda-touch"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module btt_panda_touch_module = {
.name = "btt-panda-touch",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
@@ -2,5 +2,6 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register( idf_component_register(
SRCS ${SOURCE_FILES} SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel driver INCLUDE_DIRS "source"
REQUIRES TactilityKernel
) )
+121
View File
@@ -0,0 +1,121 @@
/dts-v1/;
#include <tactility/bindings/root.h>
#include <tactility/bindings/esp32_gpio.h>
#include <tactility/bindings/esp32_grove.h>
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/esp32_wifi.h>
#include <bindings/tca8418.h>
#include <bindings/bm8563.h>
#include <bindings/esp_epaper.h>
/ {
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 keyboard and RTC (SDA: pin 1 <-> SCL: pin 2).
// External I2C devices on that port are reachable via i2c0.
i2c0 {
compatible = "espressif,esp32-i2c";
port = <I2C_NUM_0>;
clock-frequency = <100000>;
pin-sda = <&gpio0 1 GPIO_FLAG_PULL_UP>;
pin-scl = <&gpio0 2 GPIO_FLAG_PULL_UP>;
keyboard {
compatible = "ti,tca8418";
reg = <0x34>;
rows = <8>;
columns = <10>;
keymap-lc = [
37 49 50 51 52 53 54 55 56 0 // % 1 2 3 4 5 6 7 8
57 48 8 91 93 43 34 39 27 0 // 9 0 BKSP [ ] + " ' EXIT
9 113 119 101 114 116 121 117 105 0 // TAB q w e r t y u i
111 112 13 40 41 45 59 58 3 0 // o p ENTER ( ) - ; : STOP
0 97 115 100 102 103 104 106 107 0 // a s d f g h j k
108 17 35 123 125 42 44 46 2 0 // l UP # { } * , . MENU
122 120 99 118 98 32 32 110 109 0 // z x c v b n m
20 18 19 60 62 47 92 61 13 0 // LEFT DOWN RIGHT < > / \ = RUN
];
keymap-uc = [
37 49 50 51 52 53 54 55 56 0 // % 1 2 3 4 5 6 7 8
57 48 8 91 93 43 34 39 27 0 // 9 0 BKSP [ ] + " ' EXIT
9 81 87 69 82 84 89 85 73 0 // TAB Q W E R T Y U I
79 80 13 40 41 45 59 58 3 0 // O P ENTER ( ) - ; : STOP
0 65 83 68 70 71 72 74 75 0 // A S D F G H J K
76 17 35 123 125 42 44 46 2 0 // L UP # { } * , . MENU
90 88 67 86 66 32 32 78 77 0 // Z X C V B N M
20 18 19 60 62 47 92 61 13 0 // LEFT DOWN RIGHT < > / \ = RUN
];
keymap-sy = [
37 49 50 51 52 53 54 55 56 0 // % 1 2 3 4 5 6 7 8
57 48 8 91 93 43 34 39 27 0 // 9 0 BKSP [ ] + " ' EXIT
9 113 119 101 114 116 121 117 105 0 // TAB q w e r t y u i
111 112 13 40 41 45 59 58 3 0 // o p ENTER ( ) - ; : STOP
0 97 115 100 102 103 104 106 107 0 // a s d f g h j k
108 17 35 123 125 42 44 46 2 0 // l UP # { } * , . MENU
122 120 99 118 98 32 32 110 109 0 // z x c v b n m
20 18 19 60 62 47 92 61 13 0 // LEFT DOWN RIGHT < > / \ = RUN
];
shift-row = <4>;
shift-col = <0>;
sym-row = <5>;
sym-col = <8>;
};
rtc: bm8563 {
compatible = "belling,bm8563";
reg = <0x51>;
};
};
port_b: grove1 {
compatible = "espressif,esp32-grove";
defaultMode = <GROVE_MODE_I2C>;
pinSdaTx = <&gpio0 47 GPIO_FLAG_NONE>;
pinSclRx = <&gpio0 48 GPIO_FLAG_NONE>;
uartPort = <UART_NUM_1>;
i2cPort = <I2C_NUM_1>;
i2cClockFrequency = <100000>;
};
spi1 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 7 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>;
};
epd@1 {
compatible = "tuanpmt,esp-epaper";
pin-dc = <&gpio0 13 GPIO_FLAG_NONE>;
pin-reset = <&gpio0 12 GPIO_FLAG_NONE>;
pin-busy = <&gpio0 14 GPIO_FLAG_NONE>;
pin-cs = <&gpio0 6 GPIO_FLAG_NONE>;
clock-speed-hz = <4000000>;
panel-type = "gdey029t71h";
update-mode = <2>;
rotation = <1>;
};
};
};
+22
View File
@@ -0,0 +1,22 @@
general.vendor=CL-32
general.name=CL-32
apps.launcherAppId=tactility.launcher
hardware.target=ESP32S3
hardware.flashSize=8MB
hardware.spiRam=true
hardware.spiRamMode=QUAD
hardware.spiRamSpeed=80M
hardware.spiRamXipDisabled=true
hardware.esptoolFlashFreq=80M
hardware.bluetooth=true
storage.userDataLocation=SD
display.size=2.9"
display.shape=rectangle
display.dpi=139
lvgl.colorDepth=8
lvgl.theme=Mono
+6
View File
@@ -0,0 +1,6 @@
dependencies:
- Platforms/platform-esp32
- Drivers/tca8418-module
- Drivers/esp-epaper-module
- Drivers/bm8563-module
dts: cl32.dts
+9
View File
@@ -0,0 +1,9 @@
#include <tactility/module.h>
extern "C" {
struct Module cl32_module = {
.name = "cl32"
};
}
-1
View File
@@ -18,7 +18,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=2432S024C general.name=2432S024C
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=2.4" display.size=2.4"
-12
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() {
return ERROR_NONE;
}
static error_t stop() {
return ERROR_NONE;
}
Module cyd_2432s024c_module = { Module cyd_2432s024c_module = {
.name = "cyd-2432s024c", .name = "cyd-2432s024c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-1
View File
@@ -18,7 +18,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=2432S024R general.name=2432S024R
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=2.4" display.size=2.4"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_2432s024r_module = {
return ERROR_NONE; .name = "cyd-2432s024r"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_2432s024r_module = {
.name = "cyd-2432s024r",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-1
View File
@@ -19,7 +19,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=2432S028R general.name=2432S028R
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=2.8" display.size=2.8"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_2432s028r_module = {
return ERROR_NONE; .name = "cyd-2432s028r"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_2432s028r_module = {
.name = "cyd-2432s028r",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
@@ -19,7 +19,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=2432S028R v3 general.name=2432S028R v3
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=2.8" display.size=2.8"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_2432s028rv3_module = {
return ERROR_NONE; .name = "cyd-2432s028rv3"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_2432s028rv3_module = {
.name = "cyd-2432s028rv3",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-1
View File
@@ -18,7 +18,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=2432S032C general.name=2432S032C
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=3.2" display.size=3.2"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_2432s032c_module = {
return ERROR_NONE; .name = "cyd-2432s032c"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_2432s032c_module = {
.name = "cyd-2432s032c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-1
View File
@@ -19,7 +19,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=3248S035C general.name=3248S035C
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=3.5" display.size=3.5"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_3248s035c_module = {
return ERROR_NONE; .name = "cyd-3248s035c"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_3248s035c_module = {
.name = "cyd-3248s035c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+1 -1
View File
@@ -2,5 +2,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register( idf_component_register(
SRCS ${SOURCE_FILES} SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel driver REQUIRES TactilityKernel
) )
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-2
View File
@@ -18,12 +18,10 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
ble0 { ble0 {
compatible = "espressif,esp32-ble"; compatible = "espressif,esp32-ble";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,7 +1,7 @@
general.vendor=CYD general.vendor=CYD
general.name=4848S040C general.name=4848S040C
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32S3 hardware.target=ESP32S3
hardware.flashSize=16MB hardware.flashSize=16MB
@@ -10,8 +10,6 @@ hardware.spiRamMode=OCT
hardware.spiRamSpeed=80M hardware.spiRamSpeed=80M
hardware.bluetooth=true hardware.bluetooth=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=4" display.size=4"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_4848s040c_module = {
return ERROR_NONE; .name = "cyd-4848s040c"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_4848s040c_module = {
.name = "cyd-4848s040c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+1 -1
View File
@@ -2,5 +2,5 @@ file(GLOB_RECURSE SOURCE_FILES source/*.c*)
idf_component_register( idf_component_register(
SRCS ${SOURCE_FILES} SRCS ${SOURCE_FILES}
REQUIRES TactilityKernel driver REQUIRES TactilityKernel
) )
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-2
View File
@@ -19,12 +19,10 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
ble0 { ble0 {
compatible = "espressif,esp32-ble"; compatible = "espressif,esp32-ble";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -2,7 +2,7 @@ general.vendor=CYD
general.name=8048S043C general.name=8048S043C
general.incubating=false general.incubating=false
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32S3 hardware.target=ESP32S3
hardware.flashSize=16MB hardware.flashSize=16MB
@@ -12,8 +12,6 @@ hardware.spiRamSpeed=80M
hardware.esptoolFlashFreq=80M hardware.esptoolFlashFreq=80M
hardware.bluetooth=true hardware.bluetooth=true
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=4.3" display.size=4.3"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_8048s043c_module = {
return ERROR_NONE; .name = "cyd-8048s043c"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_8048s043c_module = {
.name = "cyd-8048s043c",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-1
View File
@@ -17,7 +17,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=E32R28T general.name=E32R28T
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=2.8" display.size=2.8"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_e32r28t_module = {
return ERROR_NONE; .name = "cyd-e32r28t"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_e32r28t_module = {
.name = "cyd-e32r28t",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }
+195
View File
@@ -0,0 +1,195 @@
Apache License
==============
_Version 2.0, January 2004_
_&lt;<http://www.apache.org/licenses/>&gt;_
### 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.
-1
View File
@@ -20,7 +20,6 @@
wifi0 { wifi0 {
compatible = "espressif,esp32-wifi-pinned"; compatible = "espressif,esp32-wifi-pinned";
status = "disabled";
}; };
gpio0 { gpio0 {
+1 -3
View File
@@ -1,14 +1,12 @@
general.vendor=CYD general.vendor=CYD
general.name=E32R32P general.name=E32R32P
apps.launcherAppId=Launcher apps.launcherAppId=tactility.launcher
hardware.target=ESP32 hardware.target=ESP32
hardware.flashSize=4MB hardware.flashSize=4MB
hardware.spiRam=false hardware.spiRam=false
dependencies.useDeprecatedHal=false
storage.userDataLocation=SD storage.userDataLocation=SD
display.size=2.8" display.size=2.8"
+2 -14
View File
@@ -2,20 +2,8 @@
extern "C" { extern "C" {
static error_t start() { Module cyd_e32r32p_module = {
return ERROR_NONE; .name = "cyd-e32r32p"
}
static error_t stop() {
return ERROR_NONE;
}
struct Module cyd_e32r32p_module = {
.name = "cyd-e32r32p",
.start = start,
.stop = stop,
.symbols = nullptr,
.internal = nullptr
}; };
} }

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