@typecad/framework-zephyr 1.0.0-alpha.12 → 1.0.0-alpha.14

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 (67) hide show
  1. package/README.md +13 -1
  2. package/dist/chips/controllers.d.ts +28 -8
  3. package/dist/chips/controllers.js +49 -12
  4. package/dist/chips/resolve.js +32 -6
  5. package/dist/chips/types.d.ts +63 -12
  6. package/dist/chips/xiao-ble.js +12 -0
  7. package/dist/display/index.d.ts +1 -1
  8. package/dist/display/index.js +1 -1
  9. package/dist/display/profiles.d.ts +8 -0
  10. package/dist/display/profiles.js +19 -0
  11. package/dist/display/ui-adapter.d.ts +4 -0
  12. package/dist/display/ui-adapter.js +46 -0
  13. package/dist/dt-config/kconfig.d.ts +11 -0
  14. package/dist/dt-config/kconfig.js +1 -1
  15. package/dist/dt-config/overlay.d.ts +8 -1
  16. package/dist/dt-config/overlay.js +104 -1
  17. package/dist/framework.manifest.d.ts +20 -30
  18. package/dist/framework.manifest.js +12 -3
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +5 -0
  21. package/dist/lowering/adc.d.ts +7 -4
  22. package/dist/lowering/adc.js +25 -11
  23. package/dist/lowering/gpio.js +15 -8
  24. package/dist/lowering/mqtt.js +9 -1
  25. package/dist/lowering/pulse.js +7 -7
  26. package/dist/lowering/pwm.d.ts +21 -3
  27. package/dist/lowering/pwm.js +28 -4
  28. package/dist/lowering/spi.js +2 -2
  29. package/dist/lowering/tone.js +3 -2
  30. package/dist/lowering/wifi.js +28 -5
  31. package/dist/strategy.d.ts +20 -0
  32. package/dist/strategy.js +295 -119
  33. package/dist/toolchain/debug-config.d.ts +43 -2
  34. package/dist/toolchain/debug-config.js +129 -17
  35. package/dist/toolchain/index.d.ts +14 -1
  36. package/dist/toolchain/index.js +146 -20
  37. package/dist/toolchain/scaffold.d.ts +9 -0
  38. package/dist/toolchain/scaffold.js +84 -19
  39. package/dist/toolchain/west-discover.d.ts +4 -1
  40. package/dist/toolchain/west-discover.js +2 -0
  41. package/dist/toolchain/west-spawn.js +17 -5
  42. package/package.json +5 -5
  43. package/src/chips/controllers.ts +61 -12
  44. package/src/chips/resolve.ts +32 -5
  45. package/src/chips/types.ts +63 -12
  46. package/src/chips/xiao-ble.ts +82 -70
  47. package/src/display/index.ts +1 -1
  48. package/src/display/profiles.ts +23 -0
  49. package/src/display/ui-adapter.ts +51 -0
  50. package/src/dt-config/kconfig.ts +12 -1
  51. package/src/dt-config/overlay.ts +123 -0
  52. package/src/framework.manifest.ts +12 -3
  53. package/src/index.ts +6 -0
  54. package/src/lowering/adc.ts +28 -12
  55. package/src/lowering/gpio.ts +15 -8
  56. package/src/lowering/mqtt.ts +9 -1
  57. package/src/lowering/pulse.ts +7 -7
  58. package/src/lowering/pwm.ts +29 -4
  59. package/src/lowering/spi.ts +2 -2
  60. package/src/lowering/tone.ts +3 -3
  61. package/src/lowering/wifi.ts +29 -5
  62. package/src/strategy.ts +320 -123
  63. package/src/toolchain/debug-config.ts +137 -14
  64. package/src/toolchain/index.ts +645 -513
  65. package/src/toolchain/scaffold.ts +81 -17
  66. package/src/toolchain/west-discover.ts +321 -316
  67. package/src/toolchain/west-spawn.ts +17 -5
@@ -10,6 +10,7 @@
10
10
  import { writeFileSync, existsSync, mkdirSync, readFileSync, readdirSync } from 'node:fs';
11
11
  import { join } from 'node:path';
12
12
  import { resolveKconfigFragments, type KconfigUsage } from '../dt-config/kconfig.js';
13
+ import { readCuttlefishLibrarySidecar } from '@typecad/cuttlefish/library-packages';
13
14
 
14
15
  /** Write a file only if the content differs from the existing file.
15
16
  * Returns true when the file was written (content changed or file was new). */
@@ -25,24 +26,58 @@ export function writeIfChanged(filePath: string, content: string): boolean {
25
26
  return true;
26
27
  }
27
28
 
29
+ /**
30
+ * Names of the cuttlefish-emitted C/C++ sources under src/ (top level only,
31
+ * matching the old `src/*.cpp src/*.c` glob; sorted so the generated
32
+ * CMakeLists.txt is stable across readdir orderings). Empty when no sources
33
+ * exist yet (first prepare call).
34
+ */
35
+ function listEmittedSources(srcDir: string): string[] {
36
+ if (!existsSync(srcDir)) return [];
37
+ const names = readdirSync(srcDir).filter((name) => name.endsWith('.cpp') || name.endsWith('.c'));
38
+ names.sort();
39
+ return names;
40
+ }
41
+
28
42
  /**
29
43
  * Concatenate all emitted source under src/ so the scaffold can detect which
30
44
  * peripherals the program actually uses. The cuttlefish lowering emits
31
45
  * well-known driver API tokens (adc_read, spi_transceive, bt_*, …), so scanning
32
- * the post-transpile source is an authoritative usage signal — and it keeps the
33
- * scaffold self-contained (no need to thread analysis through the toolchain
46
+ * the post-transpile source is an authoritative usage signal — and it keeps
47
+ * the scaffold self-contained (no need to thread analysis through the toolchain
34
48
  * contract). Returns '' when no sources exist yet (first prepare call).
35
49
  */
36
50
  function readEmittedSources(srcDir: string): string {
37
- if (!existsSync(srcDir)) return '';
38
51
  let out = '';
39
- for (const name of readdirSync(srcDir)) {
40
- if (name.endsWith('.cpp') || name.endsWith('.c')) {
41
- try {
42
- out += readFileSync(join(srcDir, name), 'utf8');
43
- } catch {
44
- // ignore unreadable files
52
+ for (const name of listEmittedSources(srcDir)) {
53
+ try {
54
+ out += readFileSync(join(srcDir, name), 'utf8');
55
+ } catch {
56
+ // ignore unreadable files
57
+ }
58
+ }
59
+ return out;
60
+ }
61
+
62
+ /**
63
+ * Append cuttlefish library packages' devicetree overlay fragments to the
64
+ * generated overlay. Library entries come from the transpiler's libraries.json
65
+ * sidecar (next to the emitted sources) and are already gated on the
66
+ * library's include token appearing in the emitted sources — no re-detection.
67
+ * Fragments merge after the framework overlay so library nodes (e.g.
68
+ * @typecad/zephyr-esp32s3-rgb's WS2812 node on I2S0) layer over it.
69
+ */
70
+ export function appendLibraryOverlayFragments(overlay: string, projectRoot: string): string {
71
+ let out = overlay;
72
+ for (const entry of readCuttlefishLibrarySidecar(join(projectRoot, 'src'))) {
73
+ if (!entry.overlay) continue;
74
+ try {
75
+ const fragment = readFileSync(entry.overlay, 'utf8').trim();
76
+ if (fragment.length > 0) {
77
+ out += (out.endsWith('\n') ? '' : '\n') + '\n' + fragment + '\n';
45
78
  }
79
+ } catch {
80
+ // best-effort; a missing fragment surfaces as a DT error
46
81
  }
47
82
  }
48
83
  return out;
@@ -120,8 +155,13 @@ export function scaffoldZephyrProject(projectRoot: string, debug = false, userKc
120
155
  let changed = false;
121
156
 
122
157
  // ── Root CMakeLists.txt ─────────────────────────────────────────────────
123
- // The canonical Zephyr CMake application. GLOB src/*.cpp so future multi-
124
- // file emits are picked up automatically; cuttlefish owns the file contents.
158
+ // The canonical Zephyr CMake application. The emitted source list is
159
+ // explicit (no file(GLOB CONFIGURE_DEPENDS ...)): CONFIGURE_DEPENDS puts a
160
+ // cmake.verify_globs step in the ninja graph that spawns CMake to re-check
161
+ // the glob on every build, and the scaffold already rewrites this file via
162
+ // writeIfChanged whenever the emitted file set changes — which flips
163
+ // configChanged and reconfigures with the new list baked in.
164
+ const sourceFiles = listEmittedSources(srcDir);
125
165
  const cmakeLists = [
126
166
  '# Auto-generated by @typecad/framework-zephyr from cuttlefish.config.ts.',
127
167
  'cmake_minimum_required(VERSION 3.20.0)',
@@ -130,12 +170,18 @@ export function scaffoldZephyrProject(projectRoot: string, debug = false, userKc
130
170
  '',
131
171
  'project(zephyr_app)',
132
172
  '',
133
- '# Collect cuttlefish-emitted sources. CONFIGURE_DEPENDS makes CMake re-',
134
- '# check the glob when the source set changes (e.g. the transpiler removes',
135
- '# a stale entry), instead of linking a file list from the last configure.',
136
- 'file(GLOB app_sources CONFIGURE_DEPENDS src/*.cpp src/*.c)',
137
- '',
138
- 'target_sources(app PRIVATE ${app_sources})',
173
+ ...(sourceFiles.length > 0
174
+ ? [
175
+ '# Cuttlefish-emitted sources. This list is regenerated whenever the',
176
+ '# emitted file set changes (the scaffold rewrites CMakeLists.txt).',
177
+ 'target_sources(app PRIVATE',
178
+ ...sourceFiles.map((name) => ` src/${name}`),
179
+ ')',
180
+ ]
181
+ : [
182
+ '# No emitted sources yet — the scaffold regenerates this list on the',
183
+ '# next compile once src/ contains .cpp/.c files.',
184
+ ]),
139
185
  // When PSRAM is configured, define BOARD_HAS_PSRAM so the UI runtime's
140
186
  // PSRAM canvas allocator (ui_create_canvas_best) is compiled in.
141
187
  ...(psram ? ['', '# PSRAM enabled: activate the runtime PSRAM canvas paths.', 'target_compile_definitions(app PRIVATE BOARD_HAS_PSRAM)', ''] : ['']),
@@ -184,6 +230,24 @@ export function scaffoldZephyrProject(projectRoot: string, debug = false, userKc
184
230
  if (userKconfig && userKconfig.hasOwnProperty(sym)) continue;
185
231
  prjConf.push(`${sym}=${val}`);
186
232
  }
233
+ // ── Cuttlefish library packages ─────────────────────────────────────────
234
+ // Libraries the program imports (recorded in the transpiler's libraries.json
235
+ // sidecar, next to the emitted sources) contribute their manifest's kconfig
236
+ // lines — e.g. @typecad/zephyr-esp32s3-rgb contributes CONFIG_LED_STRIP.
237
+ // Sidecar entries are already gated on the library's include token
238
+ // appearing in the emitted sources, so no re-detection here. User
239
+ // zephyr.kconfig overrides still win.
240
+ const libraryEntries = readCuttlefishLibrarySidecar(srcDir);
241
+ if (libraryEntries.length > 0) {
242
+ prjConf.push('', '# Library packages (cuttlefish.library.json contributions).');
243
+ for (const entry of libraryEntries) {
244
+ for (const line of entry.kconfig) {
245
+ const sym = line.split('=')[0];
246
+ if (userKconfig && sym !== undefined && userKconfig.hasOwnProperty(sym)) continue;
247
+ prjConf.push(line);
248
+ }
249
+ }
250
+ }
187
251
  // Emit user-specified Kconfig from cuttlefish.config.ts zephyr.kconfig.
188
252
  // These override any matching auto-detected symbol (skipped above).
189
253
  if (userKconfig) {