@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
package/dist/utils/cli.js CHANGED
@@ -17,7 +17,7 @@ export function printHelp() {
17
17
  console.log(` cuttlefish board add <spec.jsonc> [--force] Generate board + MCU packages from a chip spec`);
18
18
  console.log(` cuttlefish gen-decls <input.cpp|--all <directory>>`);
19
19
  console.log(` cuttlefish map-error <mapFile> [options]`);
20
- console.log(` cuttlefish doctor Check that arduino-cli is installed and the board's core is present`);
20
+ console.log(` cuttlefish doctor Check the active framework's environment (e.g. toolchain + board core)`);
21
21
  console.log(` cuttlefish licenses [--all] [--strict] Scan this project's Arduino libraries for SPDX licenses (--all: every installed library)`);
22
22
  console.log();
23
23
  console.log(chalk.gray(`Transpilation is always performed first. Use --compile, --upload, and`));
@@ -39,6 +39,16 @@ export function printHelp() {
39
39
  console.log(` --emit-maps <bool> Emit source maps: "true" or "false" (default: true)`);
40
40
  console.log(` Source maps enable mapping C++ errors back to TypeScript`);
41
41
  console.log();
42
+ console.log(` --autosar[=<mode>] AUTOSAR C++14 compliance mode for emitted code:`);
43
+ console.log(` off no enforcement (default)`);
44
+ console.log(` warn emit AUTOSAR_* diagnostics + sidecar, build still succeeds`);
45
+ console.log(` strict abort emit on unrecorded required violations`);
46
+ console.log(` A sidecar <name>.autosar-deviations.json is written next to the`);
47
+ console.log(` emitted artifact in warn/strict modes. See COMPLIANCE.md.`);
48
+ console.log();
49
+ console.log(` --autosar-arxml Also write <name>.autosar-deviations.arxml (Artop/DaVinci).`);
50
+ console.log(` No-op unless --autosar is warn or strict.`);
51
+ console.log();
42
52
  console.log(chalk.cyan(`BUILD COMMANDS`) + chalk.gray(` (chain in order: --compile → --upload → --monitor)`));
43
53
  console.log();
44
54
  console.log(` --compile Compile the generated output using the framework toolchain.`);
@@ -104,6 +114,12 @@ export function printHelp() {
104
114
  console.log(` --diagnostics Generate diagnostics.md and diagnostics.json reports`);
105
115
  console.log(` Includes IR graph, heap analysis, and task analysis`);
106
116
  console.log();
117
+ console.log(` --debug Inject Serial.println instrumentation at breakpoints.`);
118
+ console.log(` Reads .cuttlefish/breakpoints.json (written by the`);
119
+ console.log(` TypeCAD Debug VS Code extension). At each breakpoint the`);
120
+ console.log(` firmware prints the location, original line, and in-scope`);
121
+ console.log(` variables, then halts — press ENTER over serial to continue.`);
122
+ console.log();
107
123
  console.log(` --help, -h Show this help message`);
108
124
  console.log();
109
125
  console.log(chalk.cyan(`PROJECT CREATION`));
@@ -211,7 +227,11 @@ function parsePipelineCommand(argv, command, inputFile) {
211
227
  const emitMapsFlag = readFirstFlagValue(argv, ["--emit-maps"]);
212
228
  const buildTarget = readFirstFlagValue(argv, ["--build-target"]);
213
229
  const port = readFirstFlagValue(argv, ["--port"]);
214
- const baud = readNumberFlag(argv, ["--baud"], 9600) ?? 9600;
230
+ // Default to undefined (NOT 9600) so the build/upload/monitor flow's
231
+ // `options.baud ?? config.console.baudRate` falls through to the configured
232
+ // baud. Hardcoding 9600 here shadowed config.console.baudRate whenever --baud
233
+ // was absent (the monitor then opened the port at 9600, ignoring the config).
234
+ const baud = readNumberFlag(argv, ["--baud"]);
215
235
  const frameworkFlag = readFirstFlagValue(argv, ["--framework"]);
216
236
  const compile = readBooleanFlag(argv, ["--compile"]);
217
237
  const upload = readBooleanFlag(argv, ["--upload"]);
@@ -231,6 +251,32 @@ function parsePipelineCommand(argv, command, inputFile) {
231
251
  const keepUnusedTypes = readBooleanFlag(argv, ["--keep-unused-types"]);
232
252
  const keepUnusedVariables = readBooleanFlag(argv, ["--keep-unused-variables"]);
233
253
  const entryPoints = readRepeatedFlag(argv, "--entry-point");
254
+ // AUTOSAR C++14 compliance mode for emitted code. Accepts both
255
+ // `--autosar=strict` (= syntax) and `--autosar strict` (space syntax),
256
+ // plus the bare `--autosar` (treated as "strict"). Defaults to undefined,
257
+ // which the emitter treats as "off".
258
+ let autosar;
259
+ const autosarFlagIdx = argv.findIndex((a) => a === "--autosar" || a.startsWith("--autosar="));
260
+ if (autosarFlagIdx !== -1) {
261
+ const raw = argv[autosarFlagIdx];
262
+ if (raw === "--autosar") {
263
+ // Bare flag → strict. (No following value consumed.)
264
+ autosar = "strict";
265
+ }
266
+ else {
267
+ // --autosar=<mode>
268
+ const value = raw.slice("--autosar=".length);
269
+ if (value === "strict" || value === "warn" || value === "off") {
270
+ autosar = value;
271
+ }
272
+ else {
273
+ throw new Error(`--autosar must be one of: strict, warn, off (got: ${value})`);
274
+ }
275
+ }
276
+ }
277
+ // --autosar-arxml: also write the .autosar-deviations.arxml sidecar
278
+ // (Artop/DaVinci tooling). No-op unless --autosar is warn or strict.
279
+ const autosarArxml = readBooleanFlag(argv, ["--autosar-arxml"]);
234
280
  const emitMode = emitFlag === "cpp" || emitFlag === "split" ? emitFlag : "split";
235
281
  const emitMaps = emitMapsFlag === undefined ? true : emitMapsFlag !== "false";
236
282
  // Accept any target string — the framework package registers its own strategy id.
@@ -281,6 +327,8 @@ function parsePipelineCommand(argv, command, inputFile) {
281
327
  expect,
282
328
  expectFile,
283
329
  frameworkPackage: frameworkFlag,
330
+ autosar,
331
+ autosarArxml,
284
332
  };
285
333
  }
286
334
  export function parseCommandLine(argv) {
@@ -339,7 +387,7 @@ export function parseCommandLine(argv) {
339
387
  port: port ? String(port) : undefined,
340
388
  };
341
389
  }
342
- // doctor subcommand — verify arduino-cli + board core presence
390
+ // doctor subcommand — verify the active framework's environment
343
391
  if (firstArg === "doctor") {
344
392
  return {
345
393
  command: "doctor",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typecad/cuttlefish",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-alpha.8",
4
4
  "description": "TypeScript to C++ transpiler — native, Arduino, and bare-metal targets",
5
5
  "type": "module",
6
6
  "main": "./dist/transpile.js",
@@ -29,10 +29,22 @@
29
29
  "types": "./dist/ui-hook.d.ts",
30
30
  "default": "./dist/ui-hook.js"
31
31
  },
32
+ "./safety-hook-types": {
33
+ "types": "./dist/safety-hook.d.ts",
34
+ "default": "./dist/safety-hook.js"
35
+ },
36
+ "./build-ir-state": {
37
+ "types": "./dist/ir/build-ir-state.d.ts",
38
+ "default": "./dist/ir/build-ir-state.js"
39
+ },
32
40
  "./config-loader": {
33
41
  "types": "./dist/config-loader.d.ts",
34
42
  "default": "./dist/config-loader.js"
35
43
  },
44
+ "./utils/ui": {
45
+ "types": "./dist/utils/ui.d.ts",
46
+ "default": "./dist/utils/ui.js"
47
+ },
36
48
  "./stores/display-profile-store": {
37
49
  "types": "./dist/stores/display-profile-store.d.ts",
38
50
  "default": "./dist/stores/display-profile-store.js"
@@ -84,19 +96,22 @@
84
96
  "dependencies": {
85
97
  "chalk": "^4.1.2",
86
98
  "typescript": "^5.7.3",
87
- "zod": "^3.24.0",
88
- "@typecad/arduino-cli": "1.0.0-alpha.7"
99
+ "zod": "^3.24.0"
89
100
  },
90
101
  "peerDependencies": {
91
- "@typecad/ui": "1.0.0-alpha.7"
102
+ "@typecad/ui": "1.0.0-alpha.8",
103
+ "@typecad/safety": "1.0.0-alpha.8"
92
104
  },
93
105
  "peerDependenciesMeta": {
94
106
  "@typecad/ui": {
95
107
  "optional": true
108
+ },
109
+ "@typecad/safety": {
110
+ "optional": true
96
111
  }
97
112
  },
98
113
  "optionalDependencies": {
99
- "@typecad/framework-native": "1.0.0-alpha.7"
114
+ "@typecad/framework-native": "1.0.0-alpha.8"
100
115
  },
101
116
  "devDependencies": {
102
117
  "@types/node": "^22.10.7"
@@ -1,2 +0,0 @@
1
- import type { DisplayAdapterGenerator } from "../display-adapter.js";
2
- export declare const einkMonoAdapter: DisplayAdapterGenerator;
@@ -1,53 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // eink-mono display adapter — 1-bit B&W e-ink panels (SSD1680-class, e.g. the
3
- // common 296×128 / 250×122 breakouts). Deferred refresh: no fillScreen on init
4
- // (a full clear flashes), and a partial-refresh entry point the runtime's dirty-
5
- // rect union calls once per frame.
6
- //
7
- // Library note: targets Adafruit_EPD (Adafruit_SSD168x). The exact partial-
8
- // refresh method name varies by library (Adafruit_EPD: refreshPartial / GxEPD:
9
- // updateWindow). Verify against the target library before flashing — the shim
10
- // shape is correct; the method call is library-specific. TODO Phase 5.
11
- // ---------------------------------------------------------------------------
12
- export const einkMonoAdapter = (display) => {
13
- const cs = display._mountCs;
14
- const dc = display._mountDc;
15
- const rst = display._mountRst;
16
- const rotation = display.rotation ?? 0;
17
- const w = display.width;
18
- const h = display.height;
19
- return {
20
- includes: [
21
- "#include <Adafruit_GFX.h>",
22
- "#include <Adafruit_EPD.h>",
23
- ].join("\n"),
24
- // busy pin = -1 (unused); SRCS+D/C+RST+CS wiring. Adafruit_SSD168x(width, height, dc, rst, cs, busy).
25
- declaration: `Adafruit_SSD168x __tc_display(${w}, ${h}, ${dc}, ${rst}, ${cs}, -1);`,
26
- functions: [
27
- "// --- Display adapter: eink-mono (SSD1680-class, 1-bit, deferred refresh) ---",
28
- "static inline void display_init() {",
29
- " __tc_display.begin();",
30
- ` __tc_display.setRotation(${rotation});`,
31
- " // No full-screen clear here — e-ink flashes on a full clear. The runtime",
32
- " // marks all nodes dirty (UI_REFRESH_DEFERRED) and the first flush repaints",
33
- " // via partial refresh instead.",
34
- "}",
35
- "",
36
- "static inline CuttlefishDisplayTarget* display_defaultTarget() { return &__tc_display; }",
37
- "static inline int16_t display_width() { return __tc_display.width(); }",
38
- "static inline int16_t display_height() { return __tc_display.height(); }",
39
- "static inline void display_startWrite() {}",
40
- "static inline void display_endWrite() {}",
41
- "static inline void display_setAddrWindow(int16_t x, int16_t y, int16_t w, int16_t h) { (void)x; (void)y; (void)w; (void)h; }",
42
- // Partial refresh: push just the dirty region. The runtime draws into the
43
- // EPD's built-in GFX buffer (the display IS the backing store for 1-bit),
44
- // then calls this with the unioned dirty rect. TODO Phase 5: verify the
45
- // exact partial-refresh API for the target EPD library.
46
- "static inline void display_partial_refresh(int16_t x, int16_t y, int16_t w, int16_t h) {",
47
- " __tc_display.refreshPartial(x, y, (uint16_t)w, (uint16_t)h);",
48
- "}",
49
- // drawPixel goes through GFX into the EPD buffer; partial_refresh publishes it.
50
- "static inline void display_fillScreen(uint32_t color) { __tc_display.fillScreen(color ? EPD_WHITE : EPD_BLACK); }",
51
- ].join("\n"),
52
- };
53
- };
@@ -1,2 +0,0 @@
1
- import type { DisplayAdapterGenerator } from "../display-adapter.js";
2
- export declare const ssd1309Adapter: DisplayAdapterGenerator;
@@ -1,136 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // SSD1309 OLED display adapter — 1-bit monochrome OLED panels over I2C.
3
- //
4
- // Targets the Adafruit_SSD1306 library (which supports SSD1309 via the same
5
- // API). The SSD1306 is a page-buffered Adafruit_GFX subclass: draw into its
6
- // buffer via drawPixel/fillRect, then call display() to flush over I2C.
7
- // Colors are 1-bit (SSD1306_WHITE / SSD1306_BLACK). The runtime's
8
- // UI_NATIVE_MONO snap converts 565 → black/white at the draw choke points.
9
- //
10
- // The SSD1306 IS the backing store (its internal buffer), so this adapter
11
- // follows the e-ink deferred-refresh pattern: the runtime draws dirty rects
12
- // into the buffer, then display_partial_refresh() flushes. The SSD1306 has
13
- // no true partial refresh — display() flushes the full page buffer — but
14
- // the dirty-rect tracking still minimizes draw calls into the buffer.
15
- //
16
- // I2C wiring: SDA/SCL (Wire bus) + reset pin + I2C address (default 0x3C).
17
- // ---------------------------------------------------------------------------
18
- export const ssd1309Adapter = (display) => {
19
- const w = display.width;
20
- const h = display.height;
21
- const reset = display._mountReset;
22
- const address = display._mountAddress;
23
- const rotation = display.rotation ?? 0;
24
- return {
25
- includes: [
26
- `#define CuttlefishDisplayTarget Adafruit_GFX`,
27
- `#define CuttlefishCanvas16 GFXcanvas16`,
28
- `#define SSD1306_NO_SPLASH`,
29
- `#include <Adafruit_GFX.h>`,
30
- `#include <Adafruit_SSD1306.h>`,
31
- `#include <Wire.h>`,
32
- ].join("\n"),
33
- // I2C constructor: Adafruit_SSD1306(width, height, &Wire, resetPin)
34
- declaration: `Adafruit_SSD1306 __tc_display(${w}, ${h}, &Wire, ${reset});`,
35
- functions: [
36
- `// --- Display adapter: SSD1309 OLED (1-bit mono, I2C, page-buffered) ---`,
37
- `static inline void display_init() {`,
38
- ` // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally.`,
39
- ` __tc_display.begin(SSD1306_SWITCHCAPVCC, 0x${address.toString(16)});`,
40
- ` __tc_display.setRotation(${rotation});`,
41
- ` __tc_display.clearDisplay();`,
42
- ` __tc_display.display();`,
43
- `}`,
44
- ``,
45
- `static inline void display_fillScreen(uint32_t color) {`,
46
- ` __tc_display.fillScreen(color ? SSD1306_WHITE : SSD1306_BLACK);`,
47
- `}`,
48
- `static inline CuttlefishDisplayTarget* display_defaultTarget() { return &__tc_display; }`,
49
- `static inline int16_t display_width() { return __tc_display.width(); }`,
50
- `static inline int16_t display_height() { return __tc_display.height(); }`,
51
- `static inline void display_startWrite() {}`,
52
- `static inline void display_endWrite() {}`,
53
- `static int16_t __ssd1309_addr_x = 0;`,
54
- `static int16_t __ssd1309_addr_y = 0;`,
55
- `static int16_t __ssd1309_addr_w = 0;`,
56
- `static int16_t __ssd1309_addr_h = 0;`,
57
- `static uint32_t __ssd1309_addr_cursor = 0;`,
58
- `static inline void display_setAddrWindow(int16_t x, int16_t y, int16_t w, int16_t h) {`,
59
- ` __ssd1309_addr_x = x;`,
60
- ` __ssd1309_addr_y = y;`,
61
- ` __ssd1309_addr_w = w;`,
62
- ` __ssd1309_addr_h = h;`,
63
- ` __ssd1309_addr_cursor = 0;`,
64
- `}`,
65
- `static inline void display_writePixels(UI_COLOR_T* pixels, uint32_t count) {`,
66
- ` // SSD1306 is page-buffered — write into the GFX buffer via drawPixel.`,
67
- ` if (__ssd1309_addr_w <= 0 || __ssd1309_addr_h <= 0) return;`,
68
- ` uint32_t windowPixels = (uint32_t)__ssd1309_addr_w * (uint32_t)__ssd1309_addr_h;`,
69
- ` for (uint32_t i = 0; i < count; i++) {`,
70
- ` if (__ssd1309_addr_cursor >= windowPixels) break;`,
71
- ` uint32_t pos = __ssd1309_addr_cursor++;`,
72
- ` int16_t px = (int16_t)(__ssd1309_addr_x + (int16_t)(pos % (uint32_t)__ssd1309_addr_w));`,
73
- ` int16_t py = (int16_t)(__ssd1309_addr_y + (int16_t)(pos / (uint32_t)__ssd1309_addr_w));`,
74
- ` __tc_display.drawPixel(px, py, pixels[i] ? SSD1306_WHITE : SSD1306_BLACK);`,
75
- ` }`,
76
- `}`,
77
- ``,
78
- `// The SSD1306 has no true partial refresh — display() flushes the full`,
79
- `// page buffer. The runtime's dirty-rect tracking still minimizes the draw`,
80
- `// calls INTO the buffer (only dirty nodes are redrawn); this just publishes`,
81
- `// the result. Called once per frame after the dirty-rect union is drawn.`,
82
- `static inline void display_partial_refresh(int16_t x, int16_t y, int16_t w, int16_t h) {`,
83
- ` (void)x; (void)y; (void)w; (void)h;`,
84
- ` __tc_display.display();`,
85
- `}`,
86
- // ── Canvas (offscreen GFXcanvas16 for AA text / scroll compositing) ──
87
- `static inline uint16_t ssd_mono(uint16_t c);`,
88
- `static inline CuttlefishCanvas16* display_createCanvas(int16_t w, int16_t h) { return new GFXcanvas16(w, h); }`,
89
- `static inline CuttlefishCanvas16* display_createCanvasPsram(int16_t w, int16_t h) {`,
90
- `#if defined(ESP32) && defined(BOARD_HAS_PSRAM)`,
91
- ` return new (ps_malloc(sizeof(GFXcanvas16))) GFXcanvas16(w, h);`,
92
- `#else`,
93
- ` (void)w; (void)h;`,
94
- ` return nullptr;`,
95
- `#endif`,
96
- `}`,
97
- `static inline void display_deleteCanvas(CuttlefishCanvas16* canvas) { delete canvas; }`,
98
- `static inline int16_t display_canvasWidth(CuttlefishCanvas16* c) { return c->width(); }`,
99
- `static inline int16_t display_canvasHeight(CuttlefishCanvas16* c) { return c->height(); }`,
100
- `static inline uint16_t* display_canvasBuffer(CuttlefishCanvas16* c) { return c->getBuffer(); }`,
101
- `static inline uint16_t display_canvasGetPixel(CuttlefishCanvas16* c, int16_t x, int16_t y) { return c->getPixel(x, y); }`,
102
- `static inline void display_canvasFillScreen(CuttlefishCanvas16* c, UI_COLOR_T color) { c->fillScreen(ssd_mono((uint16_t)color)); }`,
103
- `static inline void display_canvasFillRect(CuttlefishCanvas16* c, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { c->fillRect(x, y, w, h, ssd_mono((uint16_t)color)); }`,
104
- // ── Color conversion: runtime uses 0xffff/0x0000 (565 mono snap), but the
105
- // SSD1306's drawPixel switch only accepts 0/1/2. Convert any nonzero to 1. ──
106
- `static inline uint16_t ssd_mono(uint16_t c) { return c ? SSD1306_WHITE : SSD1306_BLACK; }`,
107
- // ── Target-polymorphic draw (panel + canvas share CuttlefishDisplayTarget*) ──
108
- `static inline void display_targetDrawPixel(CuttlefishDisplayTarget* t, int16_t x, int16_t y, UI_COLOR_T color) { t->drawPixel(x, y, ssd_mono((uint16_t)color)); }`,
109
- `static inline int16_t display_targetWidth(CuttlefishDisplayTarget* t) { return t->width(); }`,
110
- `static inline int16_t display_targetHeight(CuttlefishDisplayTarget* t) { return t->height(); }`,
111
- `static inline void display_targetDrawRGBBitmap(CuttlefishDisplayTarget* t, int16_t x, int16_t y, const UI_COLOR_T* b, int16_t w, int16_t h) {`,
112
- ` if (!b || w <= 0 || h <= 0) return;`,
113
- ` for (int16_t yy = 0; yy < h; yy++) {`,
114
- ` for (int16_t xx = 0; xx < w; xx++) {`,
115
- ` t->drawPixel((int16_t)(x + xx), (int16_t)(y + yy), ssd_mono((uint16_t)b[(int32_t)yy * w + xx]));`,
116
- ` }`,
117
- ` }`,
118
- `}`,
119
- `static inline void display_targetFillRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { t->fillRect(x, y, w, h, ssd_mono((uint16_t)color)); }`,
120
- `static inline void display_targetDrawFastHLine(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, UI_COLOR_T color) { t->drawFastHLine(x, y, w, ssd_mono((uint16_t)color)); }`,
121
- `static inline void display_targetDrawFastVLine(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t h, UI_COLOR_T color) { t->drawFastVLine(x, y, h, ssd_mono((uint16_t)color)); }`,
122
- `static inline void display_targetFillRoundRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) { t->fillRoundRect(x, y, w, h, r, ssd_mono((uint16_t)color)); }`,
123
- `static inline void display_targetDrawRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) { t->drawRect(x, y, w, h, ssd_mono((uint16_t)color)); }`,
124
- `static inline void display_targetDrawRoundRect(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) { t->drawRoundRect(x, y, w, h, r, ssd_mono((uint16_t)color)); }`,
125
- `static inline void display_targetDrawLine(CuttlefishDisplayTarget* t, int16_t x0, int16_t y0, int16_t x1, int16_t y1, UI_COLOR_T color) { t->drawLine(x0, y0, x1, y1, ssd_mono((uint16_t)color)); }`,
126
- `static inline void display_targetFillCircle(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) { t->fillCircle(x, y, r, ssd_mono((uint16_t)color)); }`,
127
- `static inline void display_targetDrawCircle(CuttlefishDisplayTarget* t, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) { t->drawCircle(x, y, r, ssd_mono((uint16_t)color)); }`,
128
- `static inline void display_targetSetCursor(CuttlefishDisplayTarget* t, int16_t x, int16_t y) { t->setCursor(x, y); }`,
129
- `static inline void display_targetSetTextColor(CuttlefishDisplayTarget* t, UI_COLOR_T fg) { t->setTextColor(ssd_mono((uint16_t)fg)); }`,
130
- `static inline void display_targetSetTextColorBg(CuttlefishDisplayTarget* t, UI_COLOR_T fg, UI_COLOR_T bg) { t->setTextColor(ssd_mono((uint16_t)fg), ssd_mono((uint16_t)bg)); }`,
131
- `static inline void display_targetSetTextSize(CuttlefishDisplayTarget* t, uint8_t s) { t->setTextSize(s); }`,
132
- `static inline void display_targetSetTextWrap(CuttlefishDisplayTarget* t, bool w) { t->setTextWrap(w); }`,
133
- `static inline void display_targetPrint(CuttlefishDisplayTarget* t, const char* s) { t->print(s); }`,
134
- ].join("\n"),
135
- };
136
- };
@@ -1,2 +0,0 @@
1
- import type { DisplayAdapterGenerator } from "../display-adapter.js";
2
- export declare const st7796Adapter: DisplayAdapterGenerator;
@@ -1,132 +0,0 @@
1
- // ---------------------------------------------------------------------------
2
- // ST7796S display adapter — targets the Adafruit_ST7735_and_ST7789_Library
3
- // fork that exposes the Adafruit_ST7796S class (320×480 SPI TFT).
4
- //
5
- // Color mode: RGB565 only. The Adafruit_ST7796S init sequence hardcodes
6
- // ST77XX_COLMOD = 0x55 (16-bit/pixel). RGB666/18-bit would require patching
7
- // the library's init array (0x55 → 0x66) AND overriding Adafruit_SPITFT's
8
- // 565-native writePixels — out of scope for v1. Requesting rgb666 throws.
9
- //
10
- // Init API: Adafruit_ST7796S requires init(w,h,rowOff,colOff,colorOrder) to
11
- // send the panel init sequence. begin(freq) alone would skip it (blank panel).
12
- // SPI frequency handling: init() runs the panel command sequence and initializes
13
- // Adafruit_SPITFT. If the profile requests a frequency, update the transaction
14
- // settings with setSPISpeed() after init; do not call initSPI() a second time.
15
- // ---------------------------------------------------------------------------
16
- export const st7796Adapter = (display) => {
17
- const cs = display._mountCs;
18
- const dc = display._mountDc;
19
- const rst = display._mountRst;
20
- const rotation = display.rotation ?? 1;
21
- const spiFreq = display.spiFrequency;
22
- const invertDisplay = display.invertDisplay;
23
- const colorOrder = display.colorOrder === "bgr" ? "ST7796S_BGR" : "ST7796S_RGB";
24
- if (display.colorFormat === "rgb666" || display.colorFormat === "rgb888") {
25
- throw new Error(`RGB666/RGB888 is not supported by the Adafruit_ST7796S library: ` +
26
- `its init sequence hardcodes COLMOD=0x55 (RGB565). Use colorFormat: "rgb565". ` +
27
- `True 18-bit support requires patching the library init array and overriding ` +
28
- `Adafruit_SPITFT's 565-native writePixels — tracked as a follow-up.`);
29
- }
30
- const includes = [
31
- "#define CuttlefishDisplayTarget Adafruit_GFX",
32
- "#define CuttlefishCanvas16 GFXcanvas16",
33
- "#include <Adafruit_GFX.h>",
34
- "#include <Adafruit_ST7796S.h>",
35
- ].join("\n");
36
- const inversionLines = invertDisplay === undefined
37
- ? []
38
- : [
39
- ` __tc_display.startWrite();`,
40
- ` __tc_display.writeCommand(${invertDisplay ? "ST77XX_INVON" : "ST77XX_INVOFF"});`,
41
- ` __tc_display.endWrite();`,
42
- ];
43
- return {
44
- includes,
45
- declaration: `Adafruit_ST7796S __tc_display = Adafruit_ST7796S(${cs}, ${dc}, ${rst});`,
46
- functions: [
47
- `// --- Display adapter: ST7796S (RGB565) ---`,
48
- `static inline void display_init() {`,
49
- ` __tc_display.init(320, 480, 0, 0, ${colorOrder});`,
50
- spiFreq ? ` __tc_display.setSPISpeed(${spiFreq});` : ``,
51
- ...inversionLines,
52
- ` __tc_display.setRotation(${rotation});`,
53
- ` __tc_display.fillScreen(0x0000);`,
54
- `}`,
55
- ``,
56
- `static inline void display_fillScreen(UI_COLOR_T color) { __tc_display.fillScreen((uint16_t)color); }`,
57
- `static inline CuttlefishDisplayTarget* display_defaultTarget() { return &__tc_display; }`,
58
- `static inline int16_t display_width() { return __tc_display.width(); }`,
59
- `static inline int16_t display_height() { return __tc_display.height(); }`,
60
- ``,
61
- `static inline void display_startWrite() { __tc_display.startWrite(); }`,
62
- `static inline void display_endWrite() { __tc_display.endWrite(); }`,
63
- `static inline void display_setAddrWindow(int16_t x, int16_t y, int16_t w, int16_t h) {`,
64
- ` __tc_display.setAddrWindow(x, y, w, h);`,
65
- `}`,
66
- `static inline void display_writePixels(uint16_t* pixels, uint32_t count) {`,
67
- ` __tc_display.writePixels(pixels, count);`,
68
- `}`,
69
- ``,
70
- `static inline CuttlefishCanvas16* display_createCanvas(int16_t w, int16_t h) {`,
71
- ` return new GFXcanvas16(w, h);`,
72
- `}`,
73
- `static inline CuttlefishCanvas16* display_createCanvasPsram(int16_t w, int16_t h) {`,
74
- `#if defined(ESP32) && defined(BOARD_HAS_PSRAM)`,
75
- ` return new (ps_malloc(sizeof(GFXcanvas16))) GFXcanvas16(w, h);`,
76
- `#else`,
77
- ` (void)w; (void)h;`,
78
- ` return nullptr;`,
79
- `#endif`,
80
- `}`,
81
- `static inline void display_deleteCanvas(CuttlefishCanvas16* canvas) { delete canvas; }`,
82
- `static inline int16_t display_canvasWidth(CuttlefishCanvas16* canvas) { return canvas->width(); }`,
83
- `static inline int16_t display_canvasHeight(CuttlefishCanvas16* canvas) { return canvas->height(); }`,
84
- `static inline uint16_t* display_canvasBuffer(CuttlefishCanvas16* canvas) { return canvas->getBuffer(); }`,
85
- `static inline uint16_t display_canvasGetPixel(CuttlefishCanvas16* canvas, int16_t x, int16_t y) { return canvas->getPixel(x, y); }`,
86
- `static inline void display_canvasFillScreen(CuttlefishCanvas16* canvas, UI_COLOR_T color) { canvas->fillScreen((uint16_t)color); }`,
87
- `static inline void display_canvasFillRect(CuttlefishCanvas16* canvas, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) {`,
88
- ` canvas->fillRect(x, y, w, h, (uint16_t)color);`,
89
- `}`,
90
- ``,
91
- `static inline void display_targetDrawPixel(CuttlefishDisplayTarget* target, int16_t x, int16_t y, UI_COLOR_T color) { target->drawPixel(x, y, (uint16_t)color); }`,
92
- `static inline int16_t display_targetWidth(CuttlefishDisplayTarget* target) { return target->width(); }`,
93
- `static inline int16_t display_targetHeight(CuttlefishDisplayTarget* target) { return target->height(); }`,
94
- `static inline void display_targetDrawRGBBitmap(CuttlefishDisplayTarget* target, int16_t x, int16_t y, const uint16_t* bitmap, int16_t w, int16_t h) {`,
95
- ` target->drawRGBBitmap(x, y, bitmap, w, h);`,
96
- `}`,
97
- `static inline void display_targetFillRect(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) {`,
98
- ` target->fillRect(x, y, w, h, (uint16_t)color);`,
99
- `}`,
100
- `static inline void display_targetDrawFastHLine(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t w, UI_COLOR_T color) {`,
101
- ` target->drawFastHLine(x, y, w, (uint16_t)color);`,
102
- `}`,
103
- `static inline void display_targetDrawFastVLine(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t h, UI_COLOR_T color) {`,
104
- ` target->drawFastVLine(x, y, h, (uint16_t)color);`,
105
- `}`,
106
- `static inline void display_targetFillRoundRect(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) {`,
107
- ` target->fillRoundRect(x, y, w, h, r, (uint16_t)color);`,
108
- `}`,
109
- `static inline void display_targetDrawRect(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t w, int16_t h, UI_COLOR_T color) {`,
110
- ` target->drawRect(x, y, w, h, (uint16_t)color);`,
111
- `}`,
112
- `static inline void display_targetDrawRoundRect(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t w, int16_t h, int16_t r, UI_COLOR_T color) {`,
113
- ` target->drawRoundRect(x, y, w, h, r, (uint16_t)color);`,
114
- `}`,
115
- `static inline void display_targetDrawLine(CuttlefishDisplayTarget* target, int16_t x0, int16_t y0, int16_t x1, int16_t y1, UI_COLOR_T color) {`,
116
- ` target->drawLine(x0, y0, x1, y1, (uint16_t)color);`,
117
- `}`,
118
- `static inline void display_targetFillCircle(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) {`,
119
- ` target->fillCircle(x, y, r, (uint16_t)color);`,
120
- `}`,
121
- `static inline void display_targetDrawCircle(CuttlefishDisplayTarget* target, int16_t x, int16_t y, int16_t r, UI_COLOR_T color) {`,
122
- ` target->drawCircle(x, y, r, (uint16_t)color);`,
123
- `}`,
124
- `static inline void display_targetSetCursor(CuttlefishDisplayTarget* target, int16_t x, int16_t y) { target->setCursor(x, y); }`,
125
- `static inline void display_targetSetTextColor(CuttlefishDisplayTarget* target, UI_COLOR_T fg) { target->setTextColor((uint16_t)fg); }`,
126
- `static inline void display_targetSetTextColorBg(CuttlefishDisplayTarget* target, UI_COLOR_T fg, UI_COLOR_T bg) { target->setTextColor((uint16_t)fg, (uint16_t)bg); }`,
127
- `static inline void display_targetSetTextSize(CuttlefishDisplayTarget* target, uint8_t size) { target->setTextSize(size); }`,
128
- `static inline void display_targetSetTextWrap(CuttlefishDisplayTarget* target, bool wrap) { target->setTextWrap(wrap); }`,
129
- `static inline void display_targetPrint(CuttlefishDisplayTarget* target, const char* text) { target->print(text); }`,
130
- ].join("\n"),
131
- };
132
- };
@@ -1,7 +0,0 @@
1
- /**
2
- * Discover an ESP-IDF install root by checking $IDF_PATH first, then
3
- * well-known install locations. Returns the absolute path if found and
4
- * the `components/` subdir exists (the only thing gen-decls needs), or
5
- * undefined otherwise.
6
- */
7
- export declare function discoverIdfRootForGenDecls(): string | undefined;
@@ -1,59 +0,0 @@
1
- // Minimal IDF discovery for the gen-decls pre-transpile pass.
2
- //
3
- // We can't import framework-esp32's discovery from cuttlefish (it would
4
- // create a package dependency from core → framework). This module mirrors
5
- // the cheapest strategies from framework-esp32/src/toolchain/discover.ts:
6
- // $IDF_PATH env var, well-known install locations, and a version-dir scan
7
- // under <sysdrive>/esp/ (where the Espressif Windows installer puts
8
- // `v6.0.2/esp-idf`, etc.). It is good enough to find an IDF install on a
9
- // developer machine so the .d.ts cache can be populated before type-checking.
10
- //
11
- // For richer discovery (EIM manifest, PATH search) the framework-esp32
12
- // compile path performs its own discovery at compile time and regenerates
13
- // the cache — this minimal version is only for the pre-transpile pass.
14
- import { existsSync, readdirSync } from 'node:fs';
15
- import { join } from 'node:path';
16
- const IS_WIN = process.platform === 'win32';
17
- function wellKnownPaths() {
18
- const paths = [];
19
- if (IS_WIN) {
20
- const sysDrive = process.env.SystemDrive ?? 'C:';
21
- paths.push(join(`${sysDrive}\\esp`, 'esp-idf'), join(`${sysDrive}\\Espressif`, 'esp-idf'));
22
- // Versioned subdir scan: <sysdrive>/esp/v*/esp-idf (Windows installer layout).
23
- const espRoot = `${sysDrive}\\esp`;
24
- if (existsSync(espRoot)) {
25
- try {
26
- for (const entry of readdirSync(espRoot)) {
27
- if (/^v/i.test(entry)) {
28
- paths.push(join(espRoot, entry, 'esp-idf'));
29
- }
30
- }
31
- }
32
- catch {
33
- // readdir failed; skip.
34
- }
35
- }
36
- }
37
- else {
38
- const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
39
- paths.push(join(home, 'esp', 'esp-idf'), join(home, '.espressif', 'esp-idf'), '/opt/esp/esp-idf');
40
- }
41
- return paths;
42
- }
43
- /**
44
- * Discover an ESP-IDF install root by checking $IDF_PATH first, then
45
- * well-known install locations. Returns the absolute path if found and
46
- * the `components/` subdir exists (the only thing gen-decls needs), or
47
- * undefined otherwise.
48
- */
49
- export function discoverIdfRootForGenDecls() {
50
- const candidates = [
51
- process.env.IDF_PATH,
52
- ...wellKnownPaths(),
53
- ].filter((p) => typeof p === 'string' && p.length > 0);
54
- for (const p of candidates) {
55
- if (existsSync(join(p, 'components')))
56
- return p;
57
- }
58
- return undefined;
59
- }