@typecad/cuttlefish 1.0.0-alpha.7 → 1.0.0-alpha.8

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 (160) hide show
  1. package/dist/api/config.d.ts +32 -0
  2. package/dist/api/index.d.ts +1 -1
  3. package/dist/api/schema/types.d.ts +15 -0
  4. package/dist/api/shared/async-runtime-static.d.ts +12 -1
  5. package/dist/api/shared/async-runtime-static.js +69 -24
  6. package/dist/api/shared/async-symbol-detector.d.ts +11 -0
  7. package/dist/api/shared/async-symbol-detector.js +140 -0
  8. package/dist/api/shared/async-types.d.ts +24 -0
  9. package/dist/api/shared/coop-scheduler.d.ts +60 -0
  10. package/dist/api/shared/coop-scheduler.js +149 -0
  11. package/dist/api/shared/display-adapter.d.ts +2 -2
  12. package/dist/api/shared/display-adapter.js +9 -119
  13. package/dist/api/shared/display-adapters/sdl.js +29 -29
  14. package/dist/api/shared/display-profile.d.ts +38 -33
  15. package/dist/api/shared/display-profile.js +22 -170
  16. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  17. package/dist/api/shared/framework-manifest-registry.js +8 -6
  18. package/dist/api/shared/framework-manifest.d.ts +147 -28
  19. package/dist/api/shared/framework-manifest.js +35 -2
  20. package/dist/api/shared/graphics-strategy.d.ts +15 -6
  21. package/dist/api/shared/hal-op-ir.d.ts +340 -3
  22. package/dist/api/shared/hal-op-ir.js +34 -0
  23. package/dist/api/shared/index.d.ts +9 -1
  24. package/dist/api/shared/index.js +11 -1
  25. package/dist/api/shared/ir-core.d.ts +4 -0
  26. package/dist/api/shared/ir-declarations.d.ts +6 -0
  27. package/dist/api/shared/platform-strategy.d.ts +104 -2
  28. package/dist/api/shared/polyfill-helper-registry.js +18 -1
  29. package/dist/api/shared/promise-runtime.d.ts +1 -1
  30. package/dist/api/shared/promise-runtime.js +17 -13
  31. package/dist/api/shared/toolchain-types.d.ts +17 -0
  32. package/dist/api/shared/validate-framework-manifest.js +77 -0
  33. package/dist/api/shared/worker-runtime-polyfill.d.ts +22 -0
  34. package/dist/api/shared/worker-runtime-polyfill.js +34 -0
  35. package/dist/api/shared/worker-runtime.d.ts +69 -0
  36. package/dist/api/shared/worker-runtime.js +163 -0
  37. package/dist/cli.js +120 -121
  38. package/dist/config-loader.d.ts +7 -2
  39. package/dist/config-loader.js +20 -19
  40. package/dist/config-schema.d.ts +107 -65
  41. package/dist/config-schema.js +14 -0
  42. package/dist/contract/board-generator.d.ts +17 -0
  43. package/dist/contract/board-generator.js +57 -0
  44. package/dist/contract/contract-parser.d.ts +217 -0
  45. package/dist/contract/contract-parser.js +224 -0
  46. package/dist/contract/index.d.ts +22 -0
  47. package/dist/contract/index.js +68 -0
  48. package/dist/create/board-codegen.js +4 -4
  49. package/dist/create/board-generators.js +4 -5
  50. package/dist/create/board-spec.d.ts +74 -77
  51. package/dist/create/board-spec.js +0 -1
  52. package/dist/create/init-scaffold.d.ts +7 -3
  53. package/dist/create/init-scaffold.js +0 -62
  54. package/dist/create/init-templates.js +62 -16
  55. package/dist/create/init-wizard.js +32 -27
  56. package/dist/debug/preprocessor.js +178 -39
  57. package/dist/debug/types.d.ts +23 -0
  58. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  59. package/dist/diagnostics/mermaid-builder.js +34 -24
  60. package/dist/emit/compliance/arxml-writer.d.ts +11 -0
  61. package/dist/emit/compliance/arxml-writer.js +34 -0
  62. package/dist/emit/compliance/compliance-context.d.ts +57 -0
  63. package/dist/emit/compliance/compliance-context.js +113 -0
  64. package/dist/emit/compliance/deviation-ledger.d.ts +27 -0
  65. package/dist/emit/compliance/deviation-ledger.js +47 -0
  66. package/dist/emit/compliance/deviation-writer.d.ts +30 -0
  67. package/dist/emit/compliance/deviation-writer.js +37 -0
  68. package/dist/emit/compliance/index.d.ts +7 -0
  69. package/dist/emit/compliance/index.js +6 -0
  70. package/dist/emit/compliance/rule-engine.d.ts +13 -0
  71. package/dist/emit/compliance/rule-engine.js +101 -0
  72. package/dist/emit/compliance/rules.d.ts +16 -0
  73. package/dist/emit/compliance/rules.js +191 -0
  74. package/dist/emit/compliance/types.d.ts +59 -0
  75. package/dist/emit/compliance/types.js +8 -0
  76. package/dist/emit/emitters/class-emitter.js +6 -1
  77. package/dist/emit/emitters/emitter-context.d.ts +23 -1
  78. package/dist/emit/emitters/function-emitter-impl.js +96 -6
  79. package/dist/emit/emitters/line-appender.js +19 -0
  80. package/dist/emit/emitters/line-marker.d.ts +38 -0
  81. package/dist/emit/emitters/line-marker.js +39 -0
  82. package/dist/emit/emitters/output-finalizer.js +80 -1
  83. package/dist/emit/emitters/setup.d.ts +17 -0
  84. package/dist/emit/emitters/setup.js +217 -36
  85. package/dist/emit/emitters/top-level-prep.js +6 -0
  86. package/dist/emit/emitters/type-decl-emitter.js +28 -3
  87. package/dist/emit/emitters/ui-emitter.js +17 -8
  88. package/dist/emit/expression-renderer.d.ts +1 -1
  89. package/dist/emit/expression-renderer.js +81 -5
  90. package/dist/emit/route-hal-op.js +18 -5
  91. package/dist/emit/snprintf-helpers.js +7 -4
  92. package/dist/emit/statement-renderer.d.ts +10 -0
  93. package/dist/emit/statement-renderer.js +21 -5
  94. package/dist/emit/utils/async-state-machine.js +39 -12
  95. package/dist/framework-package.js +2 -0
  96. package/dist/framework-registry.d.ts +17 -0
  97. package/dist/ir/adc-range-validation.js +14 -1
  98. package/dist/ir/build-ir-state.d.ts +1 -0
  99. package/dist/ir/build-ir-state.js +14 -0
  100. package/dist/ir/build-ir.js +4 -4
  101. package/dist/ir/call-graph.js +16 -0
  102. package/dist/ir/expression-to-ir.js +150 -0
  103. package/dist/ir/function-builder.js +22 -0
  104. package/dist/ir/hal/hal-emitter.js +10 -6
  105. package/dist/ir/hal/hal-parser.js +16 -9
  106. package/dist/ir/hal/hal-plugins.js +164 -3
  107. package/dist/ir/identifier-collector.js +21 -4
  108. package/dist/ir/interrupt-analysis.d.ts +5 -1
  109. package/dist/ir/interrupt-analysis.js +8 -16
  110. package/dist/ir/ownership-analysis.js +6 -0
  111. package/dist/ir/pin-capability-validation.js +37 -0
  112. package/dist/ir/pin-mode-validation.d.ts +2 -2
  113. package/dist/ir/pin-mode-validation.js +49 -18
  114. package/dist/ir/program-analysis.d.ts +42 -0
  115. package/dist/ir/program-analysis.js +243 -6
  116. package/dist/ir/render-expr.js +11 -0
  117. package/dist/ir/timing-validation.js +11 -2
  118. package/dist/ir/transformers/call-statement.js +105 -0
  119. package/dist/ir/transformers/expressions.js +4 -0
  120. package/dist/ir/transformers/hal-call-resolver.js +21 -0
  121. package/dist/ir/transformers/namespace-methods.js +17 -12
  122. package/dist/ir/transformers/ui-reactive.js +2 -2
  123. package/dist/ir/transformers/variables.js +51 -0
  124. package/dist/ir/type-resolution.js +18 -0
  125. package/dist/ir/ui-element-auto-wire.js +7 -5
  126. package/dist/ir/utils/map-statements.d.ts +4 -0
  127. package/dist/ir/utils/map-statements.js +79 -0
  128. package/dist/ir/validation-orchestrator.js +6 -1
  129. package/dist/ir/worker-analysis.d.ts +10 -0
  130. package/dist/ir/worker-analysis.js +261 -0
  131. package/dist/orchestrator/graph-builder.js +8 -7
  132. package/dist/platform/coop-scheduler-runtime.d.ts +19 -0
  133. package/dist/platform/coop-scheduler-runtime.js +41 -0
  134. package/dist/platform/generic-strategy.d.ts +15 -3
  135. package/dist/platform/generic-strategy.js +49 -4
  136. package/dist/safety/safety-bridge.d.ts +11 -0
  137. package/dist/safety/safety-bridge.js +48 -0
  138. package/dist/safety/sidecar-bridge.d.ts +5 -0
  139. package/dist/safety/sidecar-bridge.js +22 -0
  140. package/dist/safety-hook.d.ts +79 -0
  141. package/dist/safety-hook.js +35 -0
  142. package/dist/stores/display-profile-store.d.ts +0 -1
  143. package/dist/stores/display-profile-store.js +0 -1
  144. package/dist/testing.d.ts +4 -0
  145. package/dist/testing.js +5 -0
  146. package/dist/transpile.js +124 -35
  147. package/dist/types.d.ts +13 -2
  148. package/dist/ui-hook.d.ts +0 -2
  149. package/dist/utils/cli.js +51 -3
  150. package/package.json +20 -5
  151. package/dist/api/shared/display-adapters/eink-mono.d.ts +0 -2
  152. package/dist/api/shared/display-adapters/eink-mono.js +0 -53
  153. package/dist/api/shared/display-adapters/ssd1309.d.ts +0 -2
  154. package/dist/api/shared/display-adapters/ssd1309.js +0 -136
  155. package/dist/api/shared/display-adapters/st7796.d.ts +0 -2
  156. package/dist/api/shared/display-adapters/st7796.js +0 -132
  157. package/dist/libdef/idf-discovery.d.ts +0 -7
  158. package/dist/libdef/idf-discovery.js +0 -59
  159. package/dist/licenses.d.ts +0 -185
  160. package/dist/licenses.js +0 -963
@@ -9,12 +9,6 @@
9
9
  import path from "node:path";
10
10
  import fs from "node:fs";
11
11
  import ts from "typescript";
12
- /** True for the framework-esp32 package or any path that resolves to it.
13
- * Used to decide whether to route frameworkData → frameworkConfig so the
14
- * ESP-IDF toolchain can read components, target, etc. */
15
- function isEspIdfFramework(framework) {
16
- return framework === "@typecad/framework-esp32" || framework.endsWith("framework-esp32");
17
- }
18
12
  import { safeValidateConfig } from "./config-schema.js";
19
13
  /** The filename we search for when walking up directories. */
20
14
  const CONFIG_FILENAME = "cuttlefish.config.ts";
@@ -303,6 +297,9 @@ export function parseConfigFile(configPath) {
303
297
  const framework = flat.get("framework");
304
298
  if (typeof framework === "string")
305
299
  resolved.framework = framework;
300
+ const psram = flat.get("psram");
301
+ if (psram === "opi" || psram === "quad")
302
+ resolved.psram = psram;
306
303
  const outputFramework = flat.get("output.framework");
307
304
  if (typeof outputFramework === "string")
308
305
  resolved.outputFramework = outputFramework;
@@ -332,17 +329,16 @@ export function parseConfigFile(configPath) {
332
329
  if (nativeSection) {
333
330
  resolved.frameworkConfig = nativeSection;
334
331
  }
335
- else if (resolved.framework && isEspIdfFramework(resolved.framework)) {
336
- // ESP-IDF: route frameworkData through frameworkConfig so the toolchain
337
- // can read components, target, and other framework-specific fields.
338
- // extractFrameworkSection walks the AST and preserves nested shapes
339
- // (components.managed, components.local, etc.).
340
- const frameworkData = configObject
341
- ? extractFrameworkSection(configObject, "frameworkData")
342
- : undefined;
343
- if (frameworkData) {
344
- resolved.frameworkConfig = frameworkData;
345
- }
332
+ // Parse zephyr-specific config section.
333
+ const zephyrKconfig = extractStringRecord(configObject, ["zephyr", "kconfig"]);
334
+ const zephyrCmakeArgs = extractStringArray(configObject, ["zephyr", "cmakeArgs"]);
335
+ const zephyrRunner = flat.get("zephyr.runner");
336
+ if (zephyrKconfig || zephyrCmakeArgs || typeof zephyrRunner === "string") {
337
+ resolved.zephyrConfig = {
338
+ ...(zephyrKconfig ? { kconfig: zephyrKconfig } : {}),
339
+ ...(zephyrCmakeArgs ? { cmakeArgs: zephyrCmakeArgs } : {}),
340
+ ...(typeof zephyrRunner === "string" ? { runner: zephyrRunner } : {}),
341
+ };
346
342
  }
347
343
  // Parse display profile config (nested object with profile name, wiring, touch)
348
344
  const displaySection = extractFrameworkSection(configObject, "display");
@@ -363,6 +359,8 @@ export function parseConfigFile(configPath) {
363
359
  structuredForValidation.entry = resolved.entry;
364
360
  if (resolved.framework)
365
361
  structuredForValidation.framework = resolved.framework;
362
+ if (resolved.psram)
363
+ structuredForValidation.psram = resolved.psram;
366
364
  if (resolved.outputFramework || resolved.outputOptimize || resolved.outputOutDir || resolved.outputExtraFlags || resolved.outputDefines) {
367
365
  structuredForValidation.output = {
368
366
  ...(resolved.outputFramework ? { framework: resolved.outputFramework } : {}),
@@ -374,6 +372,8 @@ export function parseConfigFile(configPath) {
374
372
  }
375
373
  if (resolved.console)
376
374
  structuredForValidation.console = resolved.console;
375
+ if (resolved.zephyrConfig)
376
+ structuredForValidation.zephyr = resolved.zephyrConfig;
377
377
  if (resolved.buildTarget) {
378
378
  structuredForValidation.frameworkData = { buildTarget: resolved.buildTarget };
379
379
  }
@@ -497,8 +497,9 @@ export function generateVirtualTypeDeclaration(config, platformDeclarations) {
497
497
  // `declare module` in cuttlefish-env.d.ts is treated as module augmentation
498
498
  // (because that file has `export {}`), which can't define a new module.
499
499
  //
500
- // For contract-based configs, board.ts is generated by the board-codegen
501
- // system, so don't overwrite it here.
500
+ // For contract-based configs, the narrowed board.ts is generated by the
501
+ // contract reader (`contract/board-generator.ts`, invoked from cli.ts before
502
+ // this function runs), so don't overwrite it with the generic re-export here.
502
503
  if (!config.contract && (config.board || config.mcu)) {
503
504
  const reExportSource = config.board ?? config.mcu;
504
505
  const boardTsPath = path.join(cuttlefishDir, "board.ts");
@@ -11,6 +11,11 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
11
11
  board: z.ZodOptional<z.ZodString>;
12
12
  contract: z.ZodOptional<z.ZodString>;
13
13
  framework: z.ZodOptional<z.ZodString>;
14
+ /** ESP32 PSRAM type. When set, the framework emits the PSRAM-enabling
15
+ * Kconfig/define so canvas allocations prefer external RAM (large scroll
16
+ * viewports/lists stop failing on PSRAM targets). No effect on boards
17
+ * without PSRAM (the runtime falls back to SRAM then the band renderer). */
18
+ psram: z.ZodOptional<z.ZodEnum<["opi", "quad"]>>;
14
19
  output: z.ZodOptional<z.ZodObject<{
15
20
  framework: z.ZodOptional<z.ZodString>;
16
21
  optimize: z.ZodOptional<z.ZodEnum<["none", "size", "speed", "balanced"]>>;
@@ -19,14 +24,14 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
19
24
  extraFlags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
20
25
  }, "strict", z.ZodTypeAny, {
21
26
  framework?: string | undefined;
27
+ optimize?: "none" | "size" | "speed" | "balanced" | undefined;
22
28
  outDir?: string | undefined;
23
- optimize?: "size" | "none" | "speed" | "balanced" | undefined;
24
29
  defines?: Record<string, string> | undefined;
25
30
  extraFlags?: string[] | undefined;
26
31
  }, {
27
32
  framework?: string | undefined;
33
+ optimize?: "none" | "size" | "speed" | "balanced" | undefined;
28
34
  outDir?: string | undefined;
29
- optimize?: "size" | "none" | "speed" | "balanced" | undefined;
30
35
  defines?: Record<string, string> | undefined;
31
36
  extraFlags?: string[] | undefined;
32
37
  }>>;
@@ -42,18 +47,18 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
42
47
  board: z.ZodOptional<z.ZodString>;
43
48
  }, "strict", z.ZodTypeAny, {
44
49
  board?: string | undefined;
50
+ include?: string[] | undefined;
45
51
  port?: string | undefined;
46
- buildTarget?: string | undefined;
47
52
  baudRate?: number | undefined;
48
- include?: string[] | undefined;
49
53
  timeout?: number | undefined;
54
+ buildTarget?: string | undefined;
50
55
  }, {
51
56
  board?: string | undefined;
57
+ include?: string[] | undefined;
52
58
  port?: string | undefined;
53
- buildTarget?: string | undefined;
54
59
  baudRate?: number | undefined;
55
- include?: string[] | undefined;
56
60
  timeout?: number | undefined;
61
+ buildTarget?: string | undefined;
57
62
  }>>;
58
63
  toolchain: z.ZodOptional<z.ZodObject<{
59
64
  type: z.ZodOptional<z.ZodString>;
@@ -76,141 +81,178 @@ export declare const CuttlefishConfigSchema: z.ZodEffects<z.ZodObject<{
76
81
  baudRate?: number | undefined;
77
82
  }>>;
78
83
  native: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
84
+ zephyr: z.ZodOptional<z.ZodObject<{
85
+ kconfig: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
86
+ cmakeArgs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
87
+ runner: z.ZodOptional<z.ZodString>;
88
+ }, "strict", z.ZodTypeAny, {
89
+ kconfig?: Record<string, string> | undefined;
90
+ cmakeArgs?: string[] | undefined;
91
+ runner?: string | undefined;
92
+ }, {
93
+ kconfig?: Record<string, string> | undefined;
94
+ cmakeArgs?: string[] | undefined;
95
+ runner?: string | undefined;
96
+ }>>;
79
97
  }, "strict", z.ZodTypeAny, {
80
- console?: {
81
- port?: string | undefined;
82
- baudRate?: number | undefined;
83
- } | undefined;
84
- frameworkData?: Record<string, unknown> | undefined;
98
+ entry?: string | undefined;
85
99
  target?: string | undefined;
100
+ mcu?: string | undefined;
86
101
  board?: string | undefined;
87
- exclude?: string[] | undefined;
88
- toolchain?: {
89
- type?: string | undefined;
90
- frameworkOptions?: Record<string, unknown> | undefined;
91
- } | undefined;
102
+ contract?: string | undefined;
92
103
  framework?: string | undefined;
93
- native?: Record<string, unknown> | undefined;
104
+ psram?: "opi" | "quad" | undefined;
94
105
  output?: {
95
106
  framework?: string | undefined;
107
+ optimize?: "none" | "size" | "speed" | "balanced" | undefined;
96
108
  outDir?: string | undefined;
97
- optimize?: "size" | "none" | "speed" | "balanced" | undefined;
98
109
  defines?: Record<string, string> | undefined;
99
110
  extraFlags?: string[] | undefined;
100
111
  } | undefined;
101
- mcu?: string | undefined;
112
+ frameworkData?: Record<string, unknown> | undefined;
102
113
  include?: string[] | undefined;
103
- entry?: string | undefined;
104
- contract?: string | undefined;
114
+ exclude?: string[] | undefined;
105
115
  test?: {
106
116
  board?: string | undefined;
117
+ include?: string[] | undefined;
107
118
  port?: string | undefined;
108
- buildTarget?: string | undefined;
109
119
  baudRate?: number | undefined;
110
- include?: string[] | undefined;
111
120
  timeout?: number | undefined;
121
+ buildTarget?: string | undefined;
122
+ } | undefined;
123
+ toolchain?: {
124
+ type?: string | undefined;
125
+ frameworkOptions?: Record<string, unknown> | undefined;
112
126
  } | undefined;
113
- }, {
114
127
  console?: {
115
128
  port?: string | undefined;
116
129
  baudRate?: number | undefined;
117
130
  } | undefined;
118
- frameworkData?: Record<string, unknown> | undefined;
131
+ native?: Record<string, unknown> | undefined;
132
+ zephyr?: {
133
+ kconfig?: Record<string, string> | undefined;
134
+ cmakeArgs?: string[] | undefined;
135
+ runner?: string | undefined;
136
+ } | undefined;
137
+ }, {
138
+ entry?: string | undefined;
119
139
  target?: string | undefined;
140
+ mcu?: string | undefined;
120
141
  board?: string | undefined;
121
- exclude?: string[] | undefined;
122
- toolchain?: {
123
- type?: string | undefined;
124
- frameworkOptions?: Record<string, unknown> | undefined;
125
- } | undefined;
142
+ contract?: string | undefined;
126
143
  framework?: string | undefined;
127
- native?: Record<string, unknown> | undefined;
144
+ psram?: "opi" | "quad" | undefined;
128
145
  output?: {
129
146
  framework?: string | undefined;
147
+ optimize?: "none" | "size" | "speed" | "balanced" | undefined;
130
148
  outDir?: string | undefined;
131
- optimize?: "size" | "none" | "speed" | "balanced" | undefined;
132
149
  defines?: Record<string, string> | undefined;
133
150
  extraFlags?: string[] | undefined;
134
151
  } | undefined;
135
- mcu?: string | undefined;
152
+ frameworkData?: Record<string, unknown> | undefined;
136
153
  include?: string[] | undefined;
137
- entry?: string | undefined;
138
- contract?: string | undefined;
154
+ exclude?: string[] | undefined;
139
155
  test?: {
140
156
  board?: string | undefined;
157
+ include?: string[] | undefined;
141
158
  port?: string | undefined;
142
- buildTarget?: string | undefined;
143
159
  baudRate?: number | undefined;
144
- include?: string[] | undefined;
145
160
  timeout?: number | undefined;
161
+ buildTarget?: string | undefined;
162
+ } | undefined;
163
+ toolchain?: {
164
+ type?: string | undefined;
165
+ frameworkOptions?: Record<string, unknown> | undefined;
146
166
  } | undefined;
147
- }>, {
148
167
  console?: {
149
168
  port?: string | undefined;
150
169
  baudRate?: number | undefined;
151
170
  } | undefined;
152
- frameworkData?: Record<string, unknown> | undefined;
171
+ native?: Record<string, unknown> | undefined;
172
+ zephyr?: {
173
+ kconfig?: Record<string, string> | undefined;
174
+ cmakeArgs?: string[] | undefined;
175
+ runner?: string | undefined;
176
+ } | undefined;
177
+ }>, {
178
+ entry?: string | undefined;
153
179
  target?: string | undefined;
180
+ mcu?: string | undefined;
154
181
  board?: string | undefined;
155
- exclude?: string[] | undefined;
156
- toolchain?: {
157
- type?: string | undefined;
158
- frameworkOptions?: Record<string, unknown> | undefined;
159
- } | undefined;
182
+ contract?: string | undefined;
160
183
  framework?: string | undefined;
161
- native?: Record<string, unknown> | undefined;
184
+ psram?: "opi" | "quad" | undefined;
162
185
  output?: {
163
186
  framework?: string | undefined;
187
+ optimize?: "none" | "size" | "speed" | "balanced" | undefined;
164
188
  outDir?: string | undefined;
165
- optimize?: "size" | "none" | "speed" | "balanced" | undefined;
166
189
  defines?: Record<string, string> | undefined;
167
190
  extraFlags?: string[] | undefined;
168
191
  } | undefined;
169
- mcu?: string | undefined;
192
+ frameworkData?: Record<string, unknown> | undefined;
170
193
  include?: string[] | undefined;
171
- entry?: string | undefined;
172
- contract?: string | undefined;
194
+ exclude?: string[] | undefined;
173
195
  test?: {
174
196
  board?: string | undefined;
197
+ include?: string[] | undefined;
175
198
  port?: string | undefined;
176
- buildTarget?: string | undefined;
177
199
  baudRate?: number | undefined;
178
- include?: string[] | undefined;
179
200
  timeout?: number | undefined;
201
+ buildTarget?: string | undefined;
202
+ } | undefined;
203
+ toolchain?: {
204
+ type?: string | undefined;
205
+ frameworkOptions?: Record<string, unknown> | undefined;
180
206
  } | undefined;
181
- }, {
182
207
  console?: {
183
208
  port?: string | undefined;
184
209
  baudRate?: number | undefined;
185
210
  } | undefined;
186
- frameworkData?: Record<string, unknown> | undefined;
211
+ native?: Record<string, unknown> | undefined;
212
+ zephyr?: {
213
+ kconfig?: Record<string, string> | undefined;
214
+ cmakeArgs?: string[] | undefined;
215
+ runner?: string | undefined;
216
+ } | undefined;
217
+ }, {
218
+ entry?: string | undefined;
187
219
  target?: string | undefined;
220
+ mcu?: string | undefined;
188
221
  board?: string | undefined;
189
- exclude?: string[] | undefined;
190
- toolchain?: {
191
- type?: string | undefined;
192
- frameworkOptions?: Record<string, unknown> | undefined;
193
- } | undefined;
222
+ contract?: string | undefined;
194
223
  framework?: string | undefined;
195
- native?: Record<string, unknown> | undefined;
224
+ psram?: "opi" | "quad" | undefined;
196
225
  output?: {
197
226
  framework?: string | undefined;
227
+ optimize?: "none" | "size" | "speed" | "balanced" | undefined;
198
228
  outDir?: string | undefined;
199
- optimize?: "size" | "none" | "speed" | "balanced" | undefined;
200
229
  defines?: Record<string, string> | undefined;
201
230
  extraFlags?: string[] | undefined;
202
231
  } | undefined;
203
- mcu?: string | undefined;
232
+ frameworkData?: Record<string, unknown> | undefined;
204
233
  include?: string[] | undefined;
205
- entry?: string | undefined;
206
- contract?: string | undefined;
234
+ exclude?: string[] | undefined;
207
235
  test?: {
208
236
  board?: string | undefined;
237
+ include?: string[] | undefined;
209
238
  port?: string | undefined;
210
- buildTarget?: string | undefined;
211
239
  baudRate?: number | undefined;
212
- include?: string[] | undefined;
213
240
  timeout?: number | undefined;
241
+ buildTarget?: string | undefined;
242
+ } | undefined;
243
+ toolchain?: {
244
+ type?: string | undefined;
245
+ frameworkOptions?: Record<string, unknown> | undefined;
246
+ } | undefined;
247
+ console?: {
248
+ port?: string | undefined;
249
+ baudRate?: number | undefined;
250
+ } | undefined;
251
+ native?: Record<string, unknown> | undefined;
252
+ zephyr?: {
253
+ kconfig?: Record<string, string> | undefined;
254
+ cmakeArgs?: string[] | undefined;
255
+ runner?: string | undefined;
214
256
  } | undefined;
215
257
  }>;
216
258
  /** Inferred TypeScript type from the Zod schema. */
@@ -8,6 +8,8 @@
8
8
  import { z } from 'zod';
9
9
  /** Optimization levels accepted by the output.optimize field. */
10
10
  const OptimizationLevel = z.enum(['none', 'size', 'speed', 'balanced']);
11
+ /** PSRAM types accepted by the top-level `psram` field (ESP32 PSRAM variants). */
12
+ const PsramType = z.enum(['opi', 'quad']);
11
13
  /** Schema for the `output` section. */
12
14
  const OutputConfig = z.object({
13
15
  framework: z.string().min(1).optional(),
@@ -35,6 +37,12 @@ const ToolchainConfig = z.object({
35
37
  type: z.string().optional(),
36
38
  frameworkOptions: z.record(z.string(), z.unknown()).optional(),
37
39
  }).strict();
40
+ /** Schema for the `zephyr` section. */
41
+ const ZephyrConfig = z.object({
42
+ kconfig: z.record(z.string(), z.string()).optional(),
43
+ cmakeArgs: z.array(z.string()).optional(),
44
+ runner: z.string().optional(),
45
+ }).strict();
38
46
  /**
39
47
  * Schema for the full CuttlefishConfig shape.
40
48
  *
@@ -47,6 +55,11 @@ export const CuttlefishConfigSchema = z.object({
47
55
  board: z.string().optional(),
48
56
  contract: z.string().optional(),
49
57
  framework: z.string().optional(),
58
+ /** ESP32 PSRAM type. When set, the framework emits the PSRAM-enabling
59
+ * Kconfig/define so canvas allocations prefer external RAM (large scroll
60
+ * viewports/lists stop failing on PSRAM targets). No effect on boards
61
+ * without PSRAM (the runtime falls back to SRAM then the band renderer). */
62
+ psram: PsramType.optional(),
50
63
  output: OutputConfig.optional(),
51
64
  frameworkData: z.record(z.string(), z.unknown()).optional(),
52
65
  include: z.array(z.string()).optional(),
@@ -55,6 +68,7 @@ export const CuttlefishConfigSchema = z.object({
55
68
  toolchain: ToolchainConfig.optional(),
56
69
  console: ConsoleConfig.optional(),
57
70
  native: z.record(z.string(), z.unknown()).optional(),
71
+ zephyr: ZephyrConfig.optional(),
58
72
  }).strict().refine(data => !(data.board && data.contract), {
59
73
  message: "Specifying both 'board' and 'contract' is not allowed. Choose one.",
60
74
  path: ['board'],
@@ -0,0 +1,17 @@
1
+ /** The directory (relative to the project root) where board.ts is generated. */
2
+ export declare const CUTTLEFISH_DIR = ".cuttlefish";
3
+ export interface GenerateBoardOptions {
4
+ /** Absolute project root dir (where .cuttlefish/ lives). */
5
+ projectDir: string;
6
+ /** MCU package specifier, e.g. '@typecad/mcu-atmega328p'. */
7
+ mcuPackage: string;
8
+ /** Matched MCU pin names to re-export (e.g. ['PB5','PC4']). */
9
+ connectedPins: string[];
10
+ /** Selected peripheral instance names to re-export (e.g. ['I2C0']). */
11
+ peripherals: string[];
12
+ }
13
+ /**
14
+ * Writes the narrowed `.cuttlefish/board.ts`.
15
+ * @returns the absolute path to the generated file.
16
+ */
17
+ export declare function generateBoardFile(opts: GenerateBoardOptions): string;
@@ -0,0 +1,57 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Board generator — emits the narrowed `.cuttlefish/board.ts` for a contract
3
+ //
4
+ // Given the MCU package name plus the matched pin and peripheral names, writes
5
+ // a board.ts that:
6
+ // - re-exports the full HAL surface from @typecad/hal (constants, functions,
7
+ // timing, math, GPIO/Pin helpers, buses) so firmware has the complete
8
+ // runtime vocabulary; and
9
+ // - re-exports ONLY the connected pins and selected peripherals from the MCU
10
+ // package, so any pin the PCB did not wire is absent from `@typecad/board`
11
+ // and using it becomes a compile error.
12
+ //
13
+ // The emitted file is consumed via cuttlefish-env.d.ts, which emits
14
+ // `declare module '@typecad/board' { export * from './board.js'; ... }`
15
+ // for contract-based configs (see config-loader.ts). The './board.js' relative
16
+ // specifier resolves to this file in the same `.cuttlefish/` directory.
17
+ // ---------------------------------------------------------------------------
18
+ import fs from 'node:fs';
19
+ import path from 'node:path';
20
+ /** The directory (relative to the project root) where board.ts is generated. */
21
+ export const CUTTLEFISH_DIR = '.cuttlefish';
22
+ /**
23
+ * Writes the narrowed `.cuttlefish/board.ts`.
24
+ * @returns the absolute path to the generated file.
25
+ */
26
+ export function generateBoardFile(opts) {
27
+ const { projectDir, mcuPackage, connectedPins, peripherals } = opts;
28
+ const cuttlefishDir = path.join(projectDir, CUTTLEFISH_DIR);
29
+ if (!fs.existsSync(cuttlefishDir)) {
30
+ fs.mkdirSync(cuttlefishDir, { recursive: true });
31
+ }
32
+ const lines = [
33
+ '// Auto-generated by the cuttlefish transpiler from a TypeCAD contract.',
34
+ '// Do not edit manually — regenerate by re-running cuttlefish.',
35
+ '//',
36
+ '// This board exposes only the pins and peripherals that the source contract',
37
+ `// (${mcuPackage}) declares as connected on the PCB. Pins the board did not wire`,
38
+ '// are intentionally absent: using one is a compile error.',
39
+ '',
40
+ '// Full HAL runtime surface (constants, timing, math, GPIO/bus helpers).',
41
+ "export * from '@typecad/hal';",
42
+ '',
43
+ '// Narrowed pin set — only pins the contract declares connected.',
44
+ ];
45
+ if (connectedPins.length > 0) {
46
+ lines.push(`export { ${connectedPins.join(', ')} } from '${mcuPackage}';`);
47
+ }
48
+ if (peripherals.length > 0) {
49
+ lines.push('');
50
+ lines.push('// Narrowed peripheral set — only buses whose pins are wired on the PCB.');
51
+ lines.push(`export { ${peripherals.join(', ')} } from '${mcuPackage}';`);
52
+ }
53
+ lines.push(''); // trailing newline
54
+ const outPath = path.join(cuttlefishDir, 'board.ts');
55
+ fs.writeFileSync(outPath, lines.join('\n'), 'utf-8');
56
+ return outPath;
57
+ }