@typecad/framework-zephyr 1.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +100 -0
  3. package/dist/async/timer-polyfill.d.ts +10 -0
  4. package/dist/async/timer-polyfill.js +95 -0
  5. package/dist/chips/controllers.d.ts +21 -0
  6. package/dist/chips/controllers.js +66 -0
  7. package/dist/chips/esp32.d.ts +2 -0
  8. package/dist/chips/esp32.js +59 -0
  9. package/dist/chips/esp32s3.d.ts +2 -0
  10. package/dist/chips/esp32s3.js +54 -0
  11. package/dist/chips/index.d.ts +15 -0
  12. package/dist/chips/index.js +45 -0
  13. package/dist/chips/resolve.d.ts +9 -0
  14. package/dist/chips/resolve.js +121 -0
  15. package/dist/chips/types.d.ts +154 -0
  16. package/dist/chips/types.js +14 -0
  17. package/dist/chips/xiao-ble.d.ts +2 -0
  18. package/dist/chips/xiao-ble.js +61 -0
  19. package/dist/debug-codegen.d.ts +33 -0
  20. package/dist/debug-codegen.js +162 -0
  21. package/dist/display/gfx.d.ts +17 -0
  22. package/dist/display/gfx.js +171 -0
  23. package/dist/display/index.d.ts +20 -0
  24. package/dist/display/index.js +53 -0
  25. package/dist/display/profiles.d.ts +25 -0
  26. package/dist/display/profiles.js +41 -0
  27. package/dist/display/touch-adapter.d.ts +9 -0
  28. package/dist/display/touch-adapter.js +95 -0
  29. package/dist/display/ui-adapter.d.ts +21 -0
  30. package/dist/display/ui-adapter.js +534 -0
  31. package/dist/doctor.d.ts +6 -0
  32. package/dist/doctor.js +48 -0
  33. package/dist/dt-config/kconfig.d.ts +27 -0
  34. package/dist/dt-config/kconfig.js +283 -0
  35. package/dist/dt-config/overlay.d.ts +35 -0
  36. package/dist/dt-config/overlay.js +246 -0
  37. package/dist/framework.manifest.d.ts +101 -0
  38. package/dist/framework.manifest.js +536 -0
  39. package/dist/index.d.ts +6 -0
  40. package/dist/index.js +17 -0
  41. package/dist/lowering/adc.d.ts +19 -0
  42. package/dist/lowering/adc.js +76 -0
  43. package/dist/lowering/ble.d.ts +20 -0
  44. package/dist/lowering/ble.js +419 -0
  45. package/dist/lowering/board.d.ts +9 -0
  46. package/dist/lowering/board.js +33 -0
  47. package/dist/lowering/gpio.d.ts +12 -0
  48. package/dist/lowering/gpio.js +123 -0
  49. package/dist/lowering/http.d.ts +23 -0
  50. package/dist/lowering/http.js +482 -0
  51. package/dist/lowering/i2c.d.ts +15 -0
  52. package/dist/lowering/i2c.js +114 -0
  53. package/dist/lowering/index.d.ts +29 -0
  54. package/dist/lowering/index.js +93 -0
  55. package/dist/lowering/interrupts.d.ts +21 -0
  56. package/dist/lowering/interrupts.js +91 -0
  57. package/dist/lowering/mqtt.d.ts +19 -0
  58. package/dist/lowering/mqtt.js +366 -0
  59. package/dist/lowering/power.d.ts +9 -0
  60. package/dist/lowering/power.js +64 -0
  61. package/dist/lowering/preferences.d.ts +23 -0
  62. package/dist/lowering/preferences.js +345 -0
  63. package/dist/lowering/pulse.d.ts +7 -0
  64. package/dist/lowering/pulse.js +82 -0
  65. package/dist/lowering/pwm.d.ts +15 -0
  66. package/dist/lowering/pwm.js +59 -0
  67. package/dist/lowering/random.d.ts +18 -0
  68. package/dist/lowering/random.js +129 -0
  69. package/dist/lowering/spi.d.ts +17 -0
  70. package/dist/lowering/spi.js +113 -0
  71. package/dist/lowering/timing.d.ts +9 -0
  72. package/dist/lowering/timing.js +63 -0
  73. package/dist/lowering/tone.d.ts +10 -0
  74. package/dist/lowering/tone.js +50 -0
  75. package/dist/lowering/uart.d.ts +15 -0
  76. package/dist/lowering/uart.js +102 -0
  77. package/dist/lowering/util.d.ts +4 -0
  78. package/dist/lowering/util.js +12 -0
  79. package/dist/lowering/wdt.d.ts +15 -0
  80. package/dist/lowering/wdt.js +80 -0
  81. package/dist/lowering/wifi.d.ts +21 -0
  82. package/dist/lowering/wifi.js +447 -0
  83. package/dist/lowering/worker-backing.d.ts +14 -0
  84. package/dist/lowering/worker-backing.js +79 -0
  85. package/dist/lowering/worker.d.ts +6 -0
  86. package/dist/lowering/worker.js +14 -0
  87. package/dist/strategy.d.ts +168 -0
  88. package/dist/strategy.js +1094 -0
  89. package/dist/toolchain/compat.d.ts +38 -0
  90. package/dist/toolchain/compat.js +133 -0
  91. package/dist/toolchain/debug-config.d.ts +82 -0
  92. package/dist/toolchain/debug-config.js +359 -0
  93. package/dist/toolchain/index.d.ts +73 -0
  94. package/dist/toolchain/index.js +444 -0
  95. package/dist/toolchain/scaffold.d.ts +15 -0
  96. package/dist/toolchain/scaffold.js +196 -0
  97. package/dist/toolchain/west-discover.d.ts +40 -0
  98. package/dist/toolchain/west-discover.js +203 -0
  99. package/dist/toolchain/west-spawn.d.ts +39 -0
  100. package/dist/toolchain/west-spawn.js +117 -0
  101. package/package.json +82 -0
  102. package/src/async/timer-polyfill.ts +107 -0
  103. package/src/chips/controllers.ts +74 -0
  104. package/src/chips/esp32.ts +62 -0
  105. package/src/chips/esp32s3.ts +57 -0
  106. package/src/chips/index.ts +54 -0
  107. package/src/chips/resolve.ts +146 -0
  108. package/src/chips/types.ts +163 -0
  109. package/src/chips/xiao-ble.ts +64 -0
  110. package/src/debug-codegen.ts +207 -0
  111. package/src/display/gfx.ts +190 -0
  112. package/src/display/index.ts +70 -0
  113. package/src/display/profiles.ts +63 -0
  114. package/src/display/touch-adapter.ts +100 -0
  115. package/src/display/ui-adapter.ts +558 -0
  116. package/src/doctor.ts +56 -0
  117. package/src/dt-config/kconfig.ts +308 -0
  118. package/src/dt-config/overlay.ts +293 -0
  119. package/src/framework.manifest.ts +558 -0
  120. package/src/index.ts +29 -0
  121. package/src/lowering/adc.ts +102 -0
  122. package/src/lowering/ble.ts +426 -0
  123. package/src/lowering/board.ts +38 -0
  124. package/src/lowering/gpio.ts +148 -0
  125. package/src/lowering/http.ts +488 -0
  126. package/src/lowering/i2c.ts +126 -0
  127. package/src/lowering/index.ts +86 -0
  128. package/src/lowering/interrupts.ts +114 -0
  129. package/src/lowering/mqtt.ts +371 -0
  130. package/src/lowering/power.ts +70 -0
  131. package/src/lowering/preferences.ts +354 -0
  132. package/src/lowering/pulse.ts +93 -0
  133. package/src/lowering/pwm.ts +74 -0
  134. package/src/lowering/random.ts +135 -0
  135. package/src/lowering/spi.ts +124 -0
  136. package/src/lowering/timing.ts +72 -0
  137. package/src/lowering/tone.ts +60 -0
  138. package/src/lowering/uart.ts +111 -0
  139. package/src/lowering/util.ts +12 -0
  140. package/src/lowering/wdt.ts +84 -0
  141. package/src/lowering/wifi.ts +452 -0
  142. package/src/lowering/worker-backing.ts +94 -0
  143. package/src/lowering/worker.ts +17 -0
  144. package/src/strategy.ts +1265 -0
  145. package/src/toolchain/compat.ts +145 -0
  146. package/src/toolchain/debug-config.ts +399 -0
  147. package/src/toolchain/index.ts +482 -0
  148. package/src/toolchain/scaffold.ts +196 -0
  149. package/src/toolchain/west-discover.ts +233 -0
  150. package/src/toolchain/west-spawn.ts +141 -0
@@ -0,0 +1,53 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Zephyr display op resolver — maps DisplayHALOp → GFX runtime calls
3
+ //
4
+ // resolveZephyrDisplayOp is a pure function of (op, state): the strategy holds
5
+ // a DisplayState (mirrors Arduino's _displayCtx) and passes it in. On
6
+ // display.init the state is seeded with the active profile; subsequent ops
7
+ // lower to the helpers in gfx.ts.
8
+ //
9
+ // Validator probes call fill_rect/draw_text/draw_rect/flush WITHOUT a prior
10
+ // init, so when state is uninitialized we seed the DEFAULT profile and lower
11
+ // anyway (the probe only checks code/expression is non-undefined).
12
+ // ---------------------------------------------------------------------------
13
+ import { DEFAULT_ZEPHYR_DISPLAY_PROFILE } from './profiles.js';
14
+ // Re-export the UI display/touch adapters + profile registry so the strategy
15
+ // and consumers can reach them from the package barrel.
16
+ export { zephyrUiDisplayAdapter, zephyrDisplayAdapterGenerator } from './ui-adapter.js';
17
+ export { zephyrTouchAdapter } from './touch-adapter.js';
18
+ export { ZEPHYR_DISPLAY_PROFILES, DEFAULT_ZEPHYR_DISPLAY_PROFILE } from './profiles.js';
19
+ /** Fresh display state (used by the strategy per-build). */
20
+ export function newDisplayState() {
21
+ return { initialized: false, profile: DEFAULT_ZEPHYR_DISPLAY_PROFILE };
22
+ }
23
+ /**
24
+ * Resolve a display.* op. Returns { code } for statement ops, undefined when
25
+ * the op is not recognized.
26
+ */
27
+ export function resolveZephyrDisplayOp(op, state) {
28
+ const o = op;
29
+ // display.init seeds the state. The probe payload for init has no profile
30
+ // fields, so use the default profile.
31
+ if (op.operation === 'display.init') {
32
+ state.initialized = true;
33
+ return { code: 'display_init();' };
34
+ }
35
+ // For non-init ops: if not initialized (validator probe path), seed the
36
+ // default so the op still lowers.
37
+ if (!state.initialized) {
38
+ state.initialized = true;
39
+ state.profile = DEFAULT_ZEPHYR_DISPLAY_PROFILE;
40
+ }
41
+ switch (op.operation) {
42
+ case 'display.fill_rect':
43
+ return { code: `display_fill_rect(${o.x}, ${o.y}, ${o.w}, ${o.h}, ${o.color});` };
44
+ case 'display.draw_rect':
45
+ return { code: `display_draw_rect(${o.x}, ${o.y}, ${o.w}, ${o.h}, ${o.color});` };
46
+ case 'display.draw_text':
47
+ return { code: `display_draw_text(${o.x}, ${o.y}, "${o.text}", ${o.color});` };
48
+ case 'display.flush':
49
+ return { code: 'display_flush();' };
50
+ default:
51
+ return undefined;
52
+ }
53
+ }
@@ -0,0 +1,25 @@
1
+ export interface ZephyrDisplayProfile {
2
+ /** Driver id, matched against ctx.frameworkData.display / manifest drivers. */
3
+ readonly driver: string;
4
+ /** Devicetree nodelabel, e.g. 'display0'. Emitted as DT_NODELABEL(<dtLabel>). */
5
+ readonly dtLabel: string;
6
+ /** Effective (screen-space) dimensions after rotation. */
7
+ readonly width: number;
8
+ readonly height: number;
9
+ /** Native panel dimensions before rotation, when they differ from the
10
+ * effective size (e.g. a 320x480 panel mounted landscape = 480x320). */
11
+ readonly nativeWidth?: number;
12
+ readonly nativeHeight?: number;
13
+ readonly colorFormat: 'rgb565' | 'mono';
14
+ /** Applied via display_set_orientation (0/90/180/270). */
15
+ readonly rotation?: number;
16
+ /** DT alias for the backlight GPIO (set high at init), if any. */
17
+ readonly backlight?: string;
18
+ }
19
+ /**
20
+ * Built-in profile registry. Looked up by driver id. Add a profile here when a
21
+ * new board's display node is wired into its devicetree.
22
+ */
23
+ export declare const ZEPHYR_DISPLAY_PROFILES: Record<string, ZephyrDisplayProfile>;
24
+ /** The default profile used when resolveDisplayOp is probed without a display.init. */
25
+ export declare const DEFAULT_ZEPHYR_DISPLAY_PROFILE: ZephyrDisplayProfile;
@@ -0,0 +1,41 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Zephyr display profiles — DT-binding descriptors
3
+ //
4
+ // Analog of framework-arduino/src/displays/, but profiles describe a Zephyr
5
+ // devicetree node (DT_NODELABEL) to resolve via DEVICE_DT_GET, not Adafruit
6
+ // pin wiring. The GFX runtime (gfx.ts) reads width/height/colorFormat from the
7
+ // active profile to size its line buffer.
8
+ // ---------------------------------------------------------------------------
9
+ /**
10
+ * Built-in profile registry. Looked up by driver id. Add a profile here when a
11
+ * new board's display node is wired into its devicetree.
12
+ */
13
+ export const ZEPHYR_DISPLAY_PROFILES = {
14
+ 'ili9341-zephyr': {
15
+ driver: 'ili9341-zephyr',
16
+ dtLabel: 'display0',
17
+ width: 320,
18
+ height: 240,
19
+ colorFormat: 'rgb565',
20
+ rotation: 90,
21
+ backlight: 'backlight',
22
+ },
23
+ 'st7796-zephyr': {
24
+ // ST7796S SPI TFT, 320x480 RGB565 mounted landscape (effective 480x320).
25
+ // Same DT nodelabel convention as the ILI9341 — the board's devicetree
26
+ // carries the `display0` node bound to the ST7796 driver; the overlay
27
+ // enables it via status="okay". Effective dims match the Arduino
28
+ // st7796-spi profile (480x320 landscape, rotation 1).
29
+ driver: 'st7796-zephyr',
30
+ dtLabel: 'display0',
31
+ width: 480,
32
+ height: 320,
33
+ nativeWidth: 320,
34
+ nativeHeight: 480,
35
+ colorFormat: 'rgb565',
36
+ rotation: 1,
37
+ backlight: 'backlight',
38
+ },
39
+ };
40
+ /** The default profile used when resolveDisplayOp is probed without a display.init. */
41
+ export const DEFAULT_ZEPHYR_DISPLAY_PROFILE = ZEPHYR_DISPLAY_PROFILES['ili9341-zephyr'];
@@ -0,0 +1,9 @@
1
+ import type { TouchAdapterCodegen } from "@typecad/cuttlefish/api/shared";
2
+ import type { TouchProfile } from "@typecad/cuttlefish/api/shared";
3
+ /**
4
+ * Generate the FT6336U touch adapter for Zephyr. Emits touch_init /
5
+ * touch_isTouched / touch_readRaw — the three symbols the runtime's
6
+ * ui_poll_touch body calls. Returns undefined for other libraries so the
7
+ * strategy can decline.
8
+ */
9
+ export declare function zephyrTouchAdapter(touch: TouchProfile): TouchAdapterCodegen | undefined;
@@ -0,0 +1,95 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Zephyr touch adapter for the Cuttlefish UI rendering pipeline.
3
+ //
4
+ // FT6336U capacitive touch controller over I2C, driven via Zephyr's
5
+ // device-tree-bound I2C API (i2c_write_read_dt). This is the Zephyr analog of
6
+ // the Arduino FT6336U adapter in framework-arduino (touch-adapters-codegen.ts)
7
+ // and the stale native ESP32 reference (demo-display/.../main.cc).
8
+ //
9
+ // The touch node is resolved via DEVICE_DT_GET(DT_NODELABEL(ft6336u)). The
10
+ // board's devicetree must carry an `ft6336u` nodelabel with the I2C spec +
11
+ // the `focaltech,ft6336u` (or compatible) binding so the device is ready.
12
+ //
13
+ // EMIT BOUNDARY: emitted bytes land in user firmware. Covered by the TypeCAD
14
+ // Runtime Exception (RUNTIME_EXCEPTION.md at the repo root).
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Generate the FT6336U touch adapter for Zephyr. Emits touch_init /
18
+ * touch_isTouched / touch_readRaw — the three symbols the runtime's
19
+ * ui_poll_touch body calls. Returns undefined for other libraries so the
20
+ * strategy can decline.
21
+ */
22
+ export function zephyrTouchAdapter(touch) {
23
+ if (touch.library !== "FT6336U")
24
+ return undefined;
25
+ const addr = touch.i2cAddress ?? 0x38;
26
+ const addrHex = "0x" + addr.toString(16).toUpperCase();
27
+ return {
28
+ includes: [
29
+ `#include <zephyr/drivers/i2c.h>`,
30
+ ],
31
+ declaration: [
32
+ `// Zephyr FT6336U touch — I2C device resolved via devicetree.`,
33
+ `// The board DT must define an 'ft6336u' nodelabel on an I2C bus.`,
34
+ `static const struct i2c_dt_spec __tc_touch = I2C_DT_SPEC_GET(DT_NODELABEL(ft6336u));`,
35
+ `static int16_t __tc_touch_cached_x = 0;`,
36
+ `static int16_t __tc_touch_cached_y = 0;`,
37
+ `static int16_t __tc_touch_cached_z = 0;`,
38
+ `static uint8_t __tc_touch_cached_valid = 0;`,
39
+ ].join("\n"),
40
+ functions: [
41
+ `// Read N bytes starting from a register address. Returns 1 on success.`,
42
+ `// Uses i2c_write_read_dt for a combined write-read transaction (register`,
43
+ `// address write, then repeated-start read). The FT6336U is polled every`,
44
+ `// frame from ui_poll_touch, so a failed read (stuck SDA, no controller) is`,
45
+ `// non-fatal — returns 0 and touch_isTreated() returns false.`,
46
+ `static inline uint8_t __tc_touch_read_block(uint8_t reg, uint8_t* buf, uint8_t len) {`,
47
+ ` if (!device_is_ready(__tc_touch.bus)) return 0U;`,
48
+ ` int rc = i2c_write_read_dt(&__tc_touch, &reg, 1U, buf, len);`,
49
+ ` return (rc == 0) ? 1U : 0U;`,
50
+ `}`,
51
+ ``,
52
+ `static inline void touch_init() {`,
53
+ ` // The I2C bus + device are configured by devicetree. The FT6336U needs a`,
54
+ ` // hardware reset (reset pin low → high) to enter normal mode after power-on.`,
55
+ `#if DT_NODE_HAS_STATUS(DT_NODELABEL(ft6336u), okay) && DT_NODE_HAS_PROP(DT_NODELABEL(ft6336u), reset_gpios)`,
56
+ ` static const struct gpio_dt_spec __tc_touch_rst = GPIO_DT_SPEC_GET(DT_NODELABEL(ft6336u), reset_gpios);`,
57
+ ` if (device_is_ready(__tc_touch_rst.port)) {`,
58
+ ` gpio_pin_configure_dt(&__tc_touch_rst, GPIO_OUTPUT_ACTIVE); // assert reset (active=low)`,
59
+ ` k_msleep(10);`,
60
+ ` gpio_pin_set_dt(&__tc_touch_rst, 0); // release reset (inactive=high)`,
61
+ ` k_msleep(200); // FT6336U needs ~50ms after reset before responding`,
62
+ ` }`,
63
+ `#endif`,
64
+ ` (void)device_is_ready(__tc_touch.bus);`,
65
+ `}`,
66
+ ``,
67
+ `static inline bool touch_isTouched() {`,
68
+ ` __tc_touch_cached_valid = 0;`,
69
+ ` __tc_touch_cached_z = 0;`,
70
+ ` // Read TD_STATUS (0x02) + P1_XH/XL/YH/YL — 5 bytes in one transaction.`,
71
+ ` uint8_t buf[5] = {0, 0, 0, 0, 0};`,
72
+ ` if (!__tc_touch_read_block(0x02, buf, 5U)) return false;`,
73
+ ` uint8_t count = buf[0] & 0x0F;`,
74
+ ` if (count == 0U) return false;`,
75
+ ` __tc_touch_cached_x = static_cast<int16_t>((static_cast<uint16_t>(buf[1] & 0x0F) << 8) | buf[2]);`,
76
+ ` __tc_touch_cached_y = static_cast<int16_t>((static_cast<uint16_t>(buf[3] & 0x0F) << 8) | buf[4]);`,
77
+ ` __tc_touch_cached_z = 255;`,
78
+ ` __tc_touch_cached_valid = 1;`,
79
+ ` return true;`,
80
+ `}`,
81
+ ``,
82
+ `static inline void touch_readRaw(int16_t* x, int16_t* y, int16_t* z) {`,
83
+ ` // touch_isTouched() is polled each frame by ui_poll_touch; the cached`,
84
+ ` // values are fresh. If something calls readRaw before isTouched, probe now.`,
85
+ ` if (!__tc_touch_cached_valid) {`,
86
+ ` (void)touch_isTouched();`,
87
+ ` }`,
88
+ ` if (x) *x = __tc_touch_cached_x;`,
89
+ ` if (y) *y = __tc_touch_cached_y;`,
90
+ ` if (z) *z = __tc_touch_cached_z;`,
91
+ ` __tc_touch_cached_valid = 0;`,
92
+ `}`,
93
+ ].join("\n"),
94
+ };
95
+ }
@@ -0,0 +1,21 @@
1
+ import type { DisplayAdapterCode, DisplayAdapterGenerator } from "@typecad/cuttlefish/api/shared";
2
+ import type { ZephyrDisplayProfile } from "./profiles.js";
3
+ /**
4
+ * Build the Zephyr UI display adapter for a profile. Emits the full
5
+ * display_ / display_target_ / display_canvas_ surface the UI runtime expects,
6
+ * driving the panel directly via SPI (CS held across command+data).
7
+ */
8
+ export interface ZephyrDisplayReadbackOptions {
9
+ /** Enable the controller GET_SCANLINE dirty-rectangle experiment. */
10
+ scanlineSync?: boolean;
11
+ /** MISO/SDO GPIO; readback is disabled when it is not explicitly wired. */
12
+ miso?: number;
13
+ }
14
+ export declare function zephyrUiDisplayAdapter(profile: ZephyrDisplayProfile, readback?: ZephyrDisplayReadbackOptions): DisplayAdapterCode;
15
+ /**
16
+ * Strategy-owned display adapter generator. Receives the resolved display and
17
+ * looks up the Zephyr DT-binding profile by driver id. Returns undefined for
18
+ * unknown drivers so resolveDisplayAdapter can decline and
19
+ * generateDisplayAdapter surfaces a clear error.
20
+ */
21
+ export declare const zephyrDisplayAdapterGenerator: DisplayAdapterGenerator;