@typecad/cuttlefish 1.0.0-alpha.13 → 1.0.0-alpha.15

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 (343) hide show
  1. package/README.md +82 -79
  2. package/assets/editor-extensions/typecad-debug/README.md +141 -0
  3. package/assets/editor-extensions/typecad-debug/out/extension.js +347 -0
  4. package/assets/editor-extensions/typecad-debug/out/extension.js.map +1 -0
  5. package/assets/editor-extensions/typecad-debug/package.json +76 -0
  6. package/assets/editor-extensions/typecad-ui/LICENSE +27 -0
  7. package/assets/editor-extensions/typecad-ui/README.md +52 -0
  8. package/assets/editor-extensions/typecad-ui/file-icon-dark.png +0 -0
  9. package/assets/editor-extensions/typecad-ui/file-icon-light.png +0 -0
  10. package/assets/editor-extensions/typecad-ui/icon.png +0 -0
  11. package/assets/editor-extensions/typecad-ui/language-configuration.json +43 -0
  12. package/assets/editor-extensions/typecad-ui/package.json +54 -0
  13. package/assets/editor-extensions/typecad-ui/snippets/typecad-ui.json +80 -0
  14. package/assets/editor-extensions/typecad-ui/syntaxes/markdown-ui.json +45 -0
  15. package/assets/editor-extensions/typecad-ui/syntaxes/typecad-ui.tmLanguage.json +1269 -0
  16. package/dist/api/config.d.ts +30 -27
  17. package/dist/api/schema/types.d.ts +20 -3
  18. package/dist/api/shared/async-runtime-static.d.ts +1 -1
  19. package/dist/api/shared/async-runtime-static.js +5 -5
  20. package/dist/api/shared/async-types.d.ts +3 -2
  21. package/dist/api/shared/board-catalog.d.ts +2 -0
  22. package/dist/api/shared/board-catalog.js +6 -0
  23. package/dist/api/shared/board-resolver.d.ts +4 -7
  24. package/dist/api/shared/board-resolver.js +2 -1
  25. package/dist/api/shared/coop-scheduler.d.ts +1 -1
  26. package/dist/api/shared/coop-scheduler.js +1 -1
  27. package/dist/api/shared/cpp-type-ir.d.ts +1 -1
  28. package/dist/api/shared/cpp-type-ir.js +1 -1
  29. package/dist/api/shared/display-profile.d.ts +1 -1
  30. package/dist/api/shared/display-profile.js +3 -5
  31. package/dist/api/shared/framework-manifest-registry.d.ts +1 -1
  32. package/dist/api/shared/framework-manifest-registry.js +0 -1
  33. package/dist/api/shared/framework-manifest.d.ts +65 -507
  34. package/dist/api/shared/framework-manifest.js +6 -11
  35. package/dist/api/shared/hal-op-ir.d.ts +294 -685
  36. package/dist/api/shared/hal-op-ir.js +31 -65
  37. package/dist/api/shared/index.d.ts +0 -4
  38. package/dist/api/shared/index.js +1 -7
  39. package/dist/api/shared/ir-core.d.ts +6 -0
  40. package/dist/api/shared/ir-declarations.d.ts +4 -0
  41. package/dist/api/shared/ir.d.ts +1 -3
  42. package/dist/api/shared/platform-strategy.d.ts +14 -37
  43. package/dist/api/shared/polyfill-helper-registry.js +0 -5
  44. package/dist/api/shared/polyfill-types.js +0 -27
  45. package/dist/api/shared/promise-runtime.js +3 -3
  46. package/dist/api/shared/spdx-licenses.d.ts +12 -10
  47. package/dist/api/shared/spdx-licenses.js +1 -1
  48. package/dist/api/shared/toolchain-types.d.ts +1 -1
  49. package/dist/api/shared/toolchain-types.js +3 -3
  50. package/dist/api/shared/types.d.ts +0 -3
  51. package/dist/api/shared/validate-framework-manifest.js +13 -33
  52. package/dist/board-catalog/dts-reader.d.ts +220 -0
  53. package/dist/board-catalog/dts-reader.js +1052 -0
  54. package/dist/board-catalog/index.d.ts +11 -0
  55. package/dist/board-catalog/index.js +12 -0
  56. package/dist/board-catalog/pinconfig.d.ts +48 -0
  57. package/dist/board-catalog/pinconfig.js +263 -0
  58. package/dist/board-catalog/sdk.d.ts +82 -0
  59. package/dist/board-catalog/sdk.js +180 -0
  60. package/dist/board-catalog/store.d.ts +196 -0
  61. package/dist/board-catalog/store.js +363 -0
  62. package/dist/board-catalog/types.d.ts +233 -0
  63. package/dist/board-catalog/types.js +7 -0
  64. package/dist/board-catalog/walker.d.ts +112 -0
  65. package/dist/board-catalog/walker.js +1101 -0
  66. package/dist/cli-utils.d.ts +2 -2
  67. package/dist/cli-utils.js +5 -5
  68. package/dist/cli.js +227 -244
  69. package/dist/config-loader.d.ts +14 -19
  70. package/dist/config-loader.js +242 -78
  71. package/dist/config-schema.d.ts +19 -227
  72. package/dist/config-schema.js +9 -8
  73. package/dist/contract/board-generator.d.ts +4 -4
  74. package/dist/contract/board-generator.js +16 -5
  75. package/dist/contract/contract-parser.d.ts +36 -127
  76. package/dist/contract/contract-parser.js +76 -0
  77. package/dist/contract/index.d.ts +1 -1
  78. package/dist/contract/index.js +70 -21
  79. package/dist/create/active-board-catalog.d.ts +9 -0
  80. package/dist/create/active-board-catalog.js +94 -0
  81. package/dist/create/board-catalog.generated.d.ts +96 -0
  82. package/dist/create/board-catalog.generated.js +128737 -0
  83. package/dist/create/board-search.d.ts +23 -0
  84. package/dist/create/board-search.js +88 -0
  85. package/dist/create/editor-integration.d.ts +32 -0
  86. package/dist/create/editor-integration.js +257 -0
  87. package/dist/create/eslint-rules-template.d.ts +2 -2
  88. package/dist/create/framework-catalog.d.ts +48 -8
  89. package/dist/create/framework-catalog.js +58 -44
  90. package/dist/create/index.d.ts +8 -13
  91. package/dist/create/index.js +5 -9
  92. package/dist/create/mcu-target.d.ts +39 -0
  93. package/dist/create/mcu-target.js +80 -0
  94. package/dist/create/pack-targets.d.ts +19 -0
  95. package/dist/create/pack-targets.js +56 -0
  96. package/dist/create/{init-scaffold.d.ts → scaffold.d.ts} +8 -11
  97. package/dist/create/{init-scaffold.js → scaffold.js} +28 -87
  98. package/dist/create/templates.d.ts +51 -0
  99. package/dist/create/{init-templates.js → templates.js} +135 -116
  100. package/dist/create/wizard.d.ts +19 -0
  101. package/dist/create/wizard.js +314 -0
  102. package/dist/debug/preprocessor.d.ts +5 -0
  103. package/dist/debug/preprocessor.js +31 -7
  104. package/dist/diagnostics/diagnostics-report.d.ts +1 -1
  105. package/dist/diagnostics/diagnostics-report.js +3 -11
  106. package/dist/diagnostics/json-schema.d.ts +1 -1
  107. package/dist/diagnostics/md-writer.js +2 -2
  108. package/dist/diagnostics/mermaid-builder.d.ts +1 -1
  109. package/dist/diagnostics/mermaid-builder.js +1 -1
  110. package/dist/emit/cpp-emitter.js +4 -1
  111. package/dist/emit/emitters/class-emitter.js +32 -4
  112. package/dist/emit/emitters/emitter-context.d.ts +11 -0
  113. package/dist/emit/emitters/entrypoint-synthesizer.js +1 -1
  114. package/dist/emit/emitters/function-emitter-impl.js +33 -17
  115. package/dist/emit/emitters/output-finalizer.d.ts +7 -0
  116. package/dist/emit/emitters/output-finalizer.js +31 -23
  117. package/dist/emit/emitters/setup.js +147 -63
  118. package/dist/emit/emitters/top-level-prep.js +1 -1
  119. package/dist/emit/emitters/type-decl-emitter.js +13 -8
  120. package/dist/emit/emitters/ui-emitter.js +1 -1
  121. package/dist/emit/expression-renderer.d.ts +3 -3
  122. package/dist/emit/expression-renderer.js +17 -7
  123. package/dist/emit/route-hal-op.js +17 -48
  124. package/dist/emit/snprintf-helpers.d.ts +1 -3
  125. package/dist/emit/snprintf-helpers.js +1 -39
  126. package/dist/emit/statement-renderer.d.ts +0 -4
  127. package/dist/emit/statement-renderer.js +54 -45
  128. package/dist/emit/utils/async-state-machine.d.ts +16 -9
  129. package/dist/emit/utils/async-state-machine.js +56 -54
  130. package/dist/emit/utils/comment-helpers.d.ts +0 -8
  131. package/dist/emit/utils/comment-helpers.js +1 -1
  132. package/dist/emit/utils/cpp-helpers.d.ts +2 -2
  133. package/dist/emit/utils/cpp-helpers.js +2 -2
  134. package/dist/emit/utils/hal-op-cpp-type.js +4 -6
  135. package/dist/emit/utils/index.d.ts +3 -3
  136. package/dist/emit/utils/index.js +3 -3
  137. package/dist/emit/utils/type-inference.d.ts +1 -29
  138. package/dist/emit/utils/type-inference.js +0 -75
  139. package/dist/framework-package.d.ts +3 -0
  140. package/dist/framework-package.js +23 -6
  141. package/dist/framework-registry.d.ts +5 -5
  142. package/dist/frameworks/native/graphics/terminal-preview.d.ts +5 -0
  143. package/dist/frameworks/native/graphics/terminal-preview.js +33 -0
  144. package/dist/frameworks/native/index.d.ts +3 -0
  145. package/dist/frameworks/native/index.js +15 -0
  146. package/dist/frameworks/native/native-compile.d.ts +17 -0
  147. package/dist/frameworks/native/native-compile.js +170 -0
  148. package/dist/frameworks/native/native-config.d.ts +41 -0
  149. package/dist/frameworks/native/native-config.js +7 -0
  150. package/dist/frameworks/native/strategy.d.ts +97 -0
  151. package/dist/frameworks/native/strategy.js +664 -0
  152. package/dist/ir/board-resolver.d.ts +18 -23
  153. package/dist/ir/board-resolver.js +43 -401
  154. package/dist/ir/build-ir-state.d.ts +3 -0
  155. package/dist/ir/build-ir-state.js +42 -0
  156. package/dist/ir/build-ir.d.ts +1 -1
  157. package/dist/ir/build-ir.js +64 -45
  158. package/dist/ir/declaration-builders.js +1 -0
  159. package/dist/ir/expression-to-ir.js +17 -10
  160. package/dist/ir/hal/hal-emitter.d.ts +0 -2
  161. package/dist/ir/hal/hal-emitter.js +92 -41
  162. package/dist/ir/hal/hal-parser.d.ts +5 -5
  163. package/dist/ir/hal/hal-parser.js +128 -36
  164. package/dist/ir/hal/hal-plugins.d.ts +0 -1
  165. package/dist/ir/hal/hal-plugins.js +425 -716
  166. package/dist/ir/heap-analysis.js +2 -41
  167. package/dist/ir/identifier-collector.js +32 -20
  168. package/dist/ir/network-validation.js +7 -11
  169. package/dist/ir/ownership-analysis.js +75 -13
  170. package/dist/ir/peripheral-usage.d.ts +8 -2
  171. package/dist/ir/peripheral-usage.js +78 -149
  172. package/dist/ir/peripheral-validation.js +23 -3
  173. package/dist/ir/pin-capability-validation.d.ts +12 -0
  174. package/dist/ir/pin-capability-validation.js +61 -97
  175. package/dist/ir/pin-mode-validation.js +5 -5
  176. package/dist/ir/program-analysis.d.ts +8 -15
  177. package/dist/ir/program-analysis.js +140 -323
  178. package/dist/ir/pulldown-validation.js +11 -4
  179. package/dist/ir/resource-analysis.js +15 -3
  180. package/dist/ir/statement-to-ir.js +0 -6
  181. package/dist/ir/timing-validation.js +1 -1
  182. package/dist/ir/transformers/array-methods.js +11 -5
  183. package/dist/ir/transformers/call-statement.js +20 -87
  184. package/dist/ir/transformers/callback-context-registry.d.ts +1 -1
  185. package/dist/ir/transformers/callback-context-registry.js +8 -16
  186. package/dist/ir/transformers/control-flow.js +0 -13
  187. package/dist/ir/transformers/expressions.js +10 -9
  188. package/dist/ir/transformers/hal-call-resolver.d.ts +2 -2
  189. package/dist/ir/transformers/hal-call-resolver.js +24 -10
  190. package/dist/ir/transformers/hal-emit-helpers.d.ts +2 -2
  191. package/dist/ir/transformers/hal-emit-helpers.js +2 -2
  192. package/dist/ir/transformers/namespace-methods.js +1 -1
  193. package/dist/ir/transformers/ui-callback-lowering.d.ts +0 -2
  194. package/dist/ir/transformers/ui-callback-lowering.js +0 -24
  195. package/dist/ir/transformers/variables.js +338 -42
  196. package/dist/ir/try-catch-validation.js +4 -3
  197. package/dist/ir/type-resolution.js +15 -4
  198. package/dist/ir/validation-orchestrator.js +0 -9
  199. package/dist/libdef/cpp-to-decl.d.ts +0 -9
  200. package/dist/libdef/cpp-to-decl.js +0 -72
  201. package/dist/libdef/registry.d.ts +0 -1
  202. package/dist/libdef/registry.js +1 -24
  203. package/dist/library/catalog.d.ts +35 -0
  204. package/dist/library/catalog.js +67 -0
  205. package/dist/library/cli.d.ts +2 -0
  206. package/dist/library/cli.js +168 -0
  207. package/dist/library/init.d.ts +25 -0
  208. package/dist/library/init.js +397 -0
  209. package/dist/library/install.d.ts +9 -0
  210. package/dist/library/install.js +80 -0
  211. package/dist/library/registry-search.d.ts +34 -0
  212. package/dist/library/registry-search.js +50 -0
  213. package/dist/library/validate.d.ts +17 -0
  214. package/dist/library/validate.js +175 -0
  215. package/dist/library-packages.d.ts +95 -0
  216. package/dist/library-packages.js +275 -0
  217. package/dist/mapping/peripheral-names.js +9 -4
  218. package/dist/mapping/source-map.d.ts +3 -4
  219. package/dist/mapping/source-map.js +12 -18
  220. package/dist/orchestrator/graph-builder.d.ts +3 -3
  221. package/dist/orchestrator/graph-builder.js +29 -12
  222. package/dist/orchestrator/type-checker.d.ts +3 -3
  223. package/dist/orchestrator/type-checker.js +3 -3
  224. package/dist/platform/async-runtime.js +1 -1
  225. package/dist/platform/coop-scheduler-runtime.js +2 -2
  226. package/dist/platform/generic-debug-codegen.d.ts +36 -0
  227. package/dist/platform/generic-debug-codegen.js +185 -0
  228. package/dist/platform/generic-strategy.d.ts +3 -4
  229. package/dist/platform/generic-strategy.js +5 -80
  230. package/dist/platform/index.js +1 -1
  231. package/dist/platform/registry.d.ts +2 -2
  232. package/dist/platform/registry.js +2 -2
  233. package/dist/preview/client.js +17 -3
  234. package/dist/safety/asil-decorators.d.ts +32 -0
  235. package/dist/safety/asil-decorators.js +32 -0
  236. package/dist/safety/authoring.d.ts +85 -0
  237. package/dist/safety/authoring.js +61 -0
  238. package/dist/safety/engine.d.ts +3 -0
  239. package/dist/safety/engine.js +83 -0
  240. package/dist/safety/hal/ops.d.ts +48 -0
  241. package/dist/safety/hal/ops.js +46 -0
  242. package/dist/safety/iso26262/analyze.d.ts +13 -0
  243. package/dist/safety/iso26262/analyze.js +29 -0
  244. package/dist/safety/iso26262/asil.d.ts +10 -0
  245. package/dist/safety/iso26262/asil.js +22 -0
  246. package/dist/safety/iso26262/collect.d.ts +14 -0
  247. package/dist/safety/iso26262/collect.js +137 -0
  248. package/dist/safety/iso26262/goto-checker.d.ts +10 -0
  249. package/dist/safety/iso26262/goto-checker.js +72 -0
  250. package/dist/safety/iso26262/heap-checker.d.ts +7 -0
  251. package/dist/safety/iso26262/heap-checker.js +57 -0
  252. package/dist/safety/iso26262/init-checker.d.ts +13 -0
  253. package/dist/safety/iso26262/init-checker.js +127 -0
  254. package/dist/safety/iso26262/loop-checker.d.ts +7 -0
  255. package/dist/safety/iso26262/loop-checker.js +86 -0
  256. package/dist/safety/iso26262/recursion-checker.d.ts +9 -0
  257. package/dist/safety/iso26262/recursion-checker.js +134 -0
  258. package/dist/safety/iso26262/sidecar-writer.d.ts +25 -0
  259. package/dist/safety/iso26262/sidecar-writer.js +13 -0
  260. package/dist/safety/passes/pinMode-intercept.d.ts +3 -0
  261. package/dist/safety/passes/pinMode-intercept.js +60 -0
  262. package/dist/safety/runtime/mode-table.d.ts +5 -0
  263. package/dist/safety/runtime/mode-table.js +55 -0
  264. package/dist/safety/runtime/polyfills.d.ts +6 -0
  265. package/dist/safety/runtime/polyfills.js +12 -0
  266. package/dist/safety/runtime/result-struct.d.ts +11 -0
  267. package/dist/safety/runtime/result-struct.js +98 -0
  268. package/dist/safety/runtime/safe-int.d.ts +33 -0
  269. package/dist/safety/runtime/safe-int.js +170 -0
  270. package/dist/safety/runtime/safe-traits.d.ts +4 -0
  271. package/dist/safety/runtime/safe-traits.js +95 -0
  272. package/dist/safety/runtime/safe-variable.d.ts +39 -0
  273. package/dist/safety/runtime/safe-variable.js +226 -0
  274. package/dist/safety/runtime/vote.d.ts +8 -0
  275. package/dist/safety/runtime/vote.js +92 -0
  276. package/dist/safety/runtime/write-verify.d.ts +8 -0
  277. package/dist/safety/runtime/write-verify.js +71 -0
  278. package/dist/safety/safe-int-types.d.ts +45 -0
  279. package/dist/safety/safe-int-types.js +25 -0
  280. package/dist/safety/safe-variable-types.d.ts +29 -0
  281. package/dist/safety/safe-variable-types.js +19 -0
  282. package/dist/safety/safety-bridge.d.ts +5 -6
  283. package/dist/safety/safety-bridge.js +15 -28
  284. package/dist/safety/sidecar-bridge.d.ts +1 -3
  285. package/dist/safety/sidecar-bridge.js +3 -20
  286. package/dist/safety/specifiers.d.ts +6 -0
  287. package/dist/safety/specifiers.js +14 -0
  288. package/dist/safety-hook.d.ts +8 -7
  289. package/dist/safety-hook.js +12 -13
  290. package/dist/testing.d.ts +5 -6
  291. package/dist/testing.js +5 -5
  292. package/dist/transpile/resolution.d.ts +1 -1
  293. package/dist/transpile/resolution.js +18 -9
  294. package/dist/transpile/test-pins.d.ts +18 -0
  295. package/dist/transpile/test-pins.js +142 -0
  296. package/dist/transpile.d.ts +1 -2
  297. package/dist/transpile.js +90 -29
  298. package/dist/types.d.ts +45 -26
  299. package/dist/ui-hook.d.ts +1 -1
  300. package/dist/utils/cli.d.ts +2 -2
  301. package/dist/utils/cli.js +160 -157
  302. package/dist/utils/fs.d.ts +3 -4
  303. package/dist/utils/fs.js +4 -5
  304. package/dist/utils/strings.d.ts +0 -1
  305. package/dist/utils/strings.js +0 -8
  306. package/dist/utils/ui.d.ts +5 -2
  307. package/dist/utils/ui.js +13 -3
  308. package/package.json +158 -149
  309. package/dist/add-preset.d.ts +0 -4
  310. package/dist/add-preset.js +0 -74
  311. package/dist/api/shared/async-symbol-detector.d.ts +0 -11
  312. package/dist/api/shared/async-symbol-detector.js +0 -140
  313. package/dist/api/shared/native-display-op-resolver.d.ts +0 -10
  314. package/dist/api/shared/native-display-op-resolver.js +0 -64
  315. package/dist/create/board-checklist.d.ts +0 -2
  316. package/dist/create/board-checklist.js +0 -52
  317. package/dist/create/board-codegen.d.ts +0 -9
  318. package/dist/create/board-codegen.js +0 -238
  319. package/dist/create/board-generators.d.ts +0 -12
  320. package/dist/create/board-generators.js +0 -651
  321. package/dist/create/board-spec.d.ts +0 -637
  322. package/dist/create/board-spec.js +0 -214
  323. package/dist/create/init-templates.d.ts +0 -28
  324. package/dist/create/init-wizard.d.ts +0 -8
  325. package/dist/create/init-wizard.js +0 -182
  326. package/dist/install/framework-catalog.d.ts +0 -53
  327. package/dist/install/framework-catalog.js +0 -107
  328. package/dist/install/handle-install.d.ts +0 -35
  329. package/dist/install/handle-install.js +0 -177
  330. package/dist/install/index.d.ts +0 -4
  331. package/dist/install/index.js +0 -3
  332. package/dist/ir/pin-state-tracking.d.ts +0 -58
  333. package/dist/ir/pin-state-tracking.js +0 -182
  334. package/dist/ir/pwm-timer-sharing.d.ts +0 -4
  335. package/dist/ir/pwm-timer-sharing.js +0 -94
  336. package/dist/ir/timer0-pwm-timing-conflict.d.ts +0 -4
  337. package/dist/ir/timer0-pwm-timing-conflict.js +0 -72
  338. package/dist/libdef/component-decls.d.ts +0 -2
  339. package/dist/libdef/component-decls.js +0 -6
  340. package/dist/libdef/component-discovery.d.ts +0 -43
  341. package/dist/libdef/component-discovery.js +0 -83
  342. package/dist/theme-tokens.d.ts +0 -22
  343. package/dist/theme-tokens.js +0 -172
@@ -12,7 +12,6 @@ export function createEmptyPeripheralUsage() {
12
12
  adc: false,
13
13
  pwm: false,
14
14
  externalInterrupts: false,
15
- timer0: false,
16
15
  i2c: false,
17
16
  spi: false,
18
17
  uart: false,
@@ -23,6 +22,9 @@ export function createEmptyPeripheralUsage() {
23
22
  inputPins: new Set(),
24
23
  inputPulldownPins: new Set(),
25
24
  i2cInstancesUsed: new Set(),
25
+ sensor: false,
26
+ sensorPartsUsed: new Set(),
27
+ spiTargetsUsed: new Set(),
26
28
  spiInstancesUsed: new Set(),
27
29
  uartInstancesUsed: new Set(),
28
30
  pinsUsed: new Set(),
@@ -68,25 +70,6 @@ export function analyzePeripheralUsage(program) {
68
70
  }
69
71
  return usage;
70
72
  }
71
- function markTimer0UsageFromText(text, usage) {
72
- if (!text)
73
- return;
74
- const normalized = text.replace(/\s+/g, '');
75
- if (normalized === 'delay' ||
76
- normalized === 'millis' ||
77
- normalized === 'micros' ||
78
- normalized === 'Board.delay' ||
79
- normalized === 'Board.millis' ||
80
- normalized === 'Board.micros' ||
81
- normalized.startsWith('delay(') ||
82
- normalized.startsWith('millis(') ||
83
- normalized.startsWith('micros(') ||
84
- normalized.startsWith('Board.delay(') ||
85
- normalized.startsWith('Board.millis(') ||
86
- normalized.startsWith('Board.micros(')) {
87
- usage.timer0 = true;
88
- }
89
- }
90
73
  function analyzeStatements(statements, usage) {
91
74
  if (!statements || !Array.isArray(statements))
92
75
  return;
@@ -174,8 +157,6 @@ function analyzeEmitString(cpp, usage) {
174
157
  usage.uart = true;
175
158
  usage.uartInstancesUsed.add(uartMatch[1] ? parseInt(uartMatch[1], 10) : 0);
176
159
  }
177
- // delay(), millis(), micros() — timer0
178
- markTimer0UsageFromText(cpp, usage);
179
160
  // tone(N, ...) — also implies PWM output
180
161
  const toneMatch = cpp.match(/^tone\((\d+)/);
181
162
  if (toneMatch) {
@@ -240,7 +221,6 @@ function analyzeCalleeForPeripheralUsage(callee, usage) {
240
221
  usage.uartInstancesUsed.add(instance);
241
222
  }
242
223
  }
243
- markTimer0UsageFromText(callee, usage);
244
224
  }
245
225
  /**
246
226
  * Extract the bus/UART instance number from a name like "Wire" → 0, "Wire1" → 1, "SPI" → 0, "Serial" → 0, "Serial1" → 1.
@@ -254,60 +234,65 @@ function extractBusInstance(busOrPort, prefix) {
254
234
  */
255
235
  function analyzeHALOp(op, usage) {
256
236
  switch (op.operation) {
257
- // GPIO — pin mode configuration
258
- case 'gpio.set_mode': {
259
- trackPinNumberAsName(op.pin, usage);
260
- const mode = op.mode.toLowerCase();
261
- if (mode === 'output') {
262
- usage.outputPins.add(op.pin);
263
- }
264
- else if (mode === 'input_pullup') {
265
- usage.inputPullupPins.add(op.pin);
266
- }
267
- else if (mode === 'input_pulldown') {
268
- usage.inputPulldownPins.add(op.pin);
269
- }
270
- else if (mode === 'input') {
271
- usage.inputPins.add(op.pin);
272
- }
273
- break;
274
- }
237
+ // GPIO
275
238
  case 'gpio.write':
276
239
  case 'gpio.read':
240
+ case 'gpio.read_cfg':
277
241
  case 'gpio.toggle': {
278
242
  trackPinNumberAsName(op.pin, usage);
279
243
  break;
280
244
  }
281
- // PWM
282
- case 'pwm.write': {
283
- trackPinNumberAsName(op.pin, usage);
284
- usage.pwm = true;
285
- usage.pwmPinsUsed.add(op.pin);
245
+ case 'gpio.shift_out':
246
+ case 'gpio.shift_in': {
247
+ trackPinNumberAsName(op.dataPin, usage);
248
+ trackPinNumberAsName(op.clockPin, usage);
249
+ usage.outputPins.add(op.clockPin);
250
+ usage.outputPins.add(op.dataPin);
286
251
  break;
287
252
  }
288
- case 'pwm.get_frequency':
289
- case 'pwm.get_resolution': {
253
+ // Thin GPIO configure — flag-token text feeds the same mode sets the
254
+ // legacy mode-set ops do (diagnostics + conflict checks).
255
+ case 'gpio.configure': {
290
256
  trackPinNumberAsName(op.pin, usage);
257
+ const flags = String(op.flags ?? '');
258
+ if (flags.includes('GPIO.OUTPUT')) {
259
+ usage.outputPins.add(op.pin);
260
+ }
261
+ else {
262
+ if (flags.includes('GPIO.PULL_UP'))
263
+ usage.inputPullupPins.add(op.pin);
264
+ else if (flags.includes('GPIO.PULL_DOWN'))
265
+ usage.inputPulldownPins.add(op.pin);
266
+ else
267
+ usage.inputPins.add(op.pin);
268
+ }
291
269
  break;
292
270
  }
293
- // ADC
294
- case 'adc.read':
295
- case 'adc.read_voltage': {
296
- usage.adc = true;
297
- usage.adcChannelsUsed.add(op.pin);
271
+ // PWM
272
+ case 'pwm.set_pulse':
273
+ case 'pwm.set_duty':
274
+ case 'pwm.set_period': {
275
+ trackPinNumberAsName(op.pin, usage);
276
+ usage.pwm = true;
277
+ usage.pwmPinsUsed.add(op.pin);
298
278
  break;
299
279
  }
300
- case 'adc.get_resolution':
301
- case 'adc.set_reference':
302
- case 'adc.get_reference':
280
+ // ADC
281
+ case 'adc.read_raw':
282
+ case 'adc.read_mv':
283
+ {
284
+ usage.adc = true;
285
+ usage.adcChannelsUsed.add(op.pin);
286
+ break;
287
+ }
303
288
  break;
304
289
  // DAC
305
- case 'dac.write': {
290
+ case 'dac.write_value': {
306
291
  trackPinNumberAsName(op.pin, usage);
307
292
  break;
308
293
  }
309
294
  // Interrupts
310
- case 'interrupt.attach': {
295
+ case 'interrupt.attach_flags': {
311
296
  trackPinNumberAsName(op.pin, usage);
312
297
  usage.externalInterrupts = true;
313
298
  usage.interruptPinsUsed.add(op.pin);
@@ -318,103 +303,48 @@ function analyzeHALOp(op, usage) {
318
303
  break;
319
304
  }
320
305
  // Tone
321
- case 'tone.play': {
322
- usage.pwm = true;
323
- usage.pwmPinsUsed.add(op.pin);
324
- break;
325
- }
326
- case 'tone.stop': {
327
- trackPinNumberAsName(op.pin, usage);
328
- break;
329
- }
330
- // Timing
331
- case 'timing.delay':
332
- case 'timing.delay_microseconds':
333
- case 'timing.millis':
334
- case 'timing.micros': {
335
- usage.timer0 = true;
336
- break;
337
- }
338
- case 'timing.free_heap':
339
- case 'timing.set_interval':
340
- case 'timing.set_timeout':
341
- case 'timing.clear_interval':
342
- case 'timing.clear_timeout':
343
- break;
344
- // I2C
345
- case 'i2c.begin': {
346
- usage.i2c = true;
347
- usage.i2cInstancesUsed.add(extractBusInstance(op.bus, 'Wire'));
348
- break;
349
- }
350
- case 'i2c.end':
351
- case 'i2c.set_clock':
352
- case 'i2c.begin_transmission':
353
- case 'i2c.write':
354
- case 'i2c.end_transmission':
355
- case 'i2c.request_from':
356
- case 'i2c.available':
357
- case 'i2c.read':
358
- case 'i2c.recover': {
359
- usage.i2c = true;
360
- usage.i2cInstancesUsed.add(extractBusInstance(op.bus, 'Wire'));
361
- break;
362
- }
363
- // SPI
364
- case 'spi.begin': {
365
- usage.spi = true;
366
- usage.spiInstancesUsed.add(extractBusInstance(op.bus, 'SPI'));
367
- break;
368
- }
369
- case 'spi.end':
370
- case 'spi.transfer':
371
- case 'spi.begin_transaction':
372
- case 'spi.end_transaction':
373
- case 'spi.set_mode':
374
- case 'spi.set_bit_order': {
306
+ // Tier-2 thin SPI (hal/spi-target.ts) — instances used, plus the distinct
307
+ // constructed targets (bus|cs|hz|mode) that feed the DT child nodes and
308
+ // per-target spi_dt_spec state.
309
+ case 'spi.transceive':
310
+ case 'spi.dev_write':
311
+ case 'spi.reg_read': {
375
312
  usage.spi = true;
376
313
  usage.spiInstancesUsed.add(extractBusInstance(op.bus, 'SPI'));
314
+ usage.spiTargetsUsed.add(`${String(op.bus)}|${op.cs}|${op.hz ?? 0}|${op.mode ?? 0}`);
377
315
  break;
378
316
  }
379
- case 'spi.cs_low':
380
- case 'spi.cs_high': {
381
- trackPinNumberAsName(op.pin, usage);
382
- break;
383
- }
384
- // UART
385
- case 'uart.begin': {
386
- usage.uart = true;
387
- usage.uartInstancesUsed.add(extractBusInstance(op.port, 'Serial'));
317
+ // DT-bound sensor parts (generic catalog). A sensor rides the I2C bus, so
318
+ // each use marks the bus instance used too — the overlay enables exactly
319
+ // the controllers that carry constructed sensors.
320
+ case 'sensor.fetch':
321
+ case 'sensor.get': {
322
+ usage.sensor = true;
323
+ const kind = String(op.busKind ?? 'i2c');
324
+ const part = String(op.part ?? '');
325
+ const busInstance = kind === 'spi' ? extractBusInstance(op.bus, 'SPI') : extractBusInstance(op.bus, 'Wire');
326
+ // Instance-level claims only: the category booleans mean EVERY
327
+ // declared controller is in play to the resource-conflict checker
328
+ // (resource-analysis.ts), which would raise phantom pin conflicts
329
+ // between unused silicon instances.
330
+ if (kind === 'spi') {
331
+ usage.spiInstancesUsed.add(busInstance);
332
+ }
333
+ else {
334
+ usage.i2cInstancesUsed.add(busInstance);
335
+ }
336
+ usage.sensorPartsUsed.add(`${part}|${kind}${busInstance}|${op.port ?? 0}`);
388
337
  break;
389
338
  }
390
- case 'uart.end':
391
- case 'uart.print':
392
- case 'uart.println':
393
- case 'uart.printf':
394
- case 'uart.write':
395
- case 'uart.read':
396
- case 'uart.peek':
397
- case 'uart.available':
398
- case 'uart.flush': {
339
+ // SPI
340
+ // Tier-2 thin UART (hal/uart-port.ts).
341
+ case 'uart.poll_write':
342
+ case 'uart.rx_arm':
343
+ case 'uart.rx_available':
344
+ case 'uart.rx_peek':
345
+ case 'uart.rx_read': {
399
346
  usage.uart = true;
400
- usage.uartInstancesUsed.add(extractBusInstance(op.port, 'Serial'));
401
- break;
402
- }
403
- // Pulse
404
- case 'pulse.in':
405
- case 'pulse.in_long': {
406
- trackPinNumberAsName(op.pin, usage);
407
- break;
408
- }
409
- // Shift
410
- case 'shift.out': {
411
- trackPinNumberAsName(op.dataPin, usage);
412
- trackPinNumberAsName(op.clockPin, usage);
413
- break;
414
- }
415
- case 'shift.in': {
416
- trackPinNumberAsName(op.dataPin, usage);
417
- trackPinNumberAsName(op.clockPin, usage);
347
+ usage.uartInstancesUsed.add(extractBusInstance(op.port, 'UART'));
418
348
  break;
419
349
  }
420
350
  // Board resolve, snprintf, raw — no peripheral tracking needed
@@ -551,7 +481,6 @@ function analyzeExpression(expr, usage) {
551
481
  try {
552
482
  switch (expr.kind) {
553
483
  case 'raw': {
554
- markTimer0UsageFromText(expr.value, usage);
555
484
  break;
556
485
  }
557
486
  case 'method-call': {
@@ -6,6 +6,13 @@
6
6
  // ---------------------------------------------------------------------------
7
7
  /**
8
8
  * Get peripheral capacity from board constants.
9
+ *
10
+ * The count comes from an explicit `peripherals.<bus>.count` key when the
11
+ * board carries one; otherwise it is derived from the flattened instance
12
+ * entries (`peripherals.<bus>.<N>.instance`, produced by the MCU package's
13
+ * *_INSTANCES arrays) so a board whose MCU declares two I2C controllers
14
+ * accepts I2C1 (the Arduino-pico and ESP32 cores both expose the second
15
+ * bus). Only when neither form is present does it fall back to 1.
9
16
  */
10
17
  function getPeripheralCapacity(boardConstants) {
11
18
  const defaultCapacity = {
@@ -16,10 +23,23 @@ function getPeripheralCapacity(boardConstants) {
16
23
  if (!boardConstants) {
17
24
  return defaultCapacity;
18
25
  }
26
+ const capacityFor = (bus) => {
27
+ const explicit = boardConstants.get(`peripherals.${bus}.count`);
28
+ if (typeof explicit === 'number')
29
+ return explicit;
30
+ let highest = -1;
31
+ for (let i = 0; i < 16; i++) {
32
+ const instance = boardConstants.get(`peripherals.${bus}.${i}.instance`);
33
+ if (instance === undefined)
34
+ break;
35
+ highest = i;
36
+ }
37
+ return highest >= 0 ? highest + 1 : 1;
38
+ };
19
39
  return {
20
- i2c: boardConstants.get('peripherals.i2c.count') ?? 1,
21
- spi: boardConstants.get('peripherals.spi.count') ?? 1,
22
- uart: boardConstants.get('peripherals.uart.count') ?? 1,
40
+ i2c: capacityFor('i2c'),
41
+ spi: capacityFor('spi'),
42
+ uart: capacityFor('uart'),
23
43
  };
24
44
  }
25
45
  /**
@@ -1,5 +1,17 @@
1
1
  import type { ProgramIR } from '../api/index.js';
2
+ import type { BoardConstants } from './board-resolver.js';
2
3
  import type { Diagnostic } from '../types.js';
4
+ /**
5
+ * Resolve the `pins.all.<INDEX>` entry for a HAL pin NUMBER.
6
+ *
7
+ * The array is keyed by position, but pin numbers are sparse on MCUs with
8
+ * unbonded pads (STM32F411: PB11 doesn't exist, so PB12 = number 28 sits at
9
+ * array index 27) — keying `pins.all.${number}` reads the WRONG pin's entry
10
+ * for every pin past the first gap. Match by the entry's `number` field; the
11
+ * dense case (index === number) is checked first so the common path stays a
12
+ * single lookup. Returns -1 when no entry matches.
13
+ */
14
+ export declare function pinEntryIndexForNumber(pinNumber: number, boardConstants: BoardConstants | undefined): number;
3
15
  /**
4
16
  * Validate that capability-specific methods are only called on pins that support them.
5
17
  */
@@ -15,16 +15,16 @@ function assertNever(x) {
15
15
  // ---------------------------------------------------------------------------
16
16
  /** Maps a HAL operation string to the board-definition capability flag it requires. */
17
17
  function operationToCapability(op) {
18
- if (op === 'pwm.write' || op === 'pwm.get_frequency' || op === 'pwm.get_resolution' || op === 'tone.play') {
18
+ if (op === 'pwm.set_pulse' || op === 'pwm.set_duty' || op === 'pwm.set_period') {
19
19
  return 'pwm';
20
20
  }
21
- if (op === 'adc.read' || op === 'adc.read_voltage' || op === 'adc.get_resolution') {
21
+ if (op === 'adc.read_raw' || op === 'adc.read_mv') {
22
22
  return 'analogInput';
23
23
  }
24
- if (op === 'dac.write') {
24
+ if (op === 'dac.write_value') {
25
25
  return 'analogOutput';
26
26
  }
27
- if (op === 'interrupt.attach') {
27
+ if (op === 'interrupt.attach_flags') {
28
28
  return 'interrupt';
29
29
  }
30
30
  // GPIO and timing ops are always available — no capability check needed.
@@ -33,11 +33,49 @@ function operationToCapability(op) {
33
33
  // ---------------------------------------------------------------------------
34
34
  // Board constant lookups
35
35
  // ---------------------------------------------------------------------------
36
+ /**
37
+ * The number of `pins.all.*` entries the board declares (dense, from 0). The
38
+ * P3 full-SoC-port sweep can push well past the old 100/200 hard caps (the
39
+ * Teensy 4.1 sweeps 288 pads), so every scan bounds itself by the actual
40
+ * count instead of a magic limit.
41
+ */
42
+ function pinCount(boardConstants) {
43
+ if (!boardConstants)
44
+ return 0;
45
+ let i = 0;
46
+ while (i < 4096 && boardConstants.get(`pins.all.${i}.name`) !== undefined)
47
+ i++;
48
+ return i;
49
+ }
50
+ /**
51
+ * Resolve the `pins.all.<INDEX>` entry for a HAL pin NUMBER.
52
+ *
53
+ * The array is keyed by position, but pin numbers are sparse on MCUs with
54
+ * unbonded pads (STM32F411: PB11 doesn't exist, so PB12 = number 28 sits at
55
+ * array index 27) — keying `pins.all.${number}` reads the WRONG pin's entry
56
+ * for every pin past the first gap. Match by the entry's `number` field; the
57
+ * dense case (index === number) is checked first so the common path stays a
58
+ * single lookup. Returns -1 when no entry matches.
59
+ */
60
+ export function pinEntryIndexForNumber(pinNumber, boardConstants) {
61
+ if (!boardConstants)
62
+ return -1;
63
+ if (Number(boardConstants.get(`pins.all.${pinNumber}.number`)) === pinNumber)
64
+ return pinNumber;
65
+ for (let i = 0; i < pinCount(boardConstants); i++) {
66
+ if (boardConstants.get(`pins.all.${i}.name`) === undefined)
67
+ continue;
68
+ if (Number(boardConstants.get(`pins.all.${i}.number`)) === pinNumber)
69
+ return i;
70
+ }
71
+ return -1;
72
+ }
36
73
  /** Find the human-readable name for a pin number (e.g. 14 → "PC0" or "A0"). */
37
74
  function getPinName(pinNumber, boardConstants) {
38
75
  if (!boardConstants)
39
76
  return `pin ${pinNumber}`;
40
- const name = boardConstants.get(`pins.all.${pinNumber}.name`);
77
+ const idx = pinEntryIndexForNumber(pinNumber, boardConstants);
78
+ const name = idx >= 0 ? boardConstants.get(`pins.all.${idx}.name`) : undefined;
41
79
  return name ? String(name) : `pin ${pinNumber}`;
42
80
  }
43
81
  /** Find all pins on this board that support a given capability. */
@@ -45,67 +83,17 @@ function findPinsWithCapability(capability, boardConstants) {
45
83
  if (!boardConstants)
46
84
  return [];
47
85
  const result = [];
48
- const funcTypeMap = {
49
- pwm: 'pwm',
50
- analogInput: 'adc',
51
- analogOutput: 'dac',
52
- interrupt: 'interrupt',
53
- };
54
- const funcType = funcTypeMap[capability];
55
- for (let i = 0; i < 100; i++) {
86
+ for (let i = 0; i < pinCount(boardConstants); i++) {
56
87
  const name = boardConstants.get(`pins.all.${i}.name`);
57
88
  if (name === undefined)
58
89
  continue;
59
- // Check capabilities flag first
60
90
  const capFlag = boardConstants.get(`pins.all.${i}.capabilities.${capability}`);
61
91
  if (capFlag === true || capFlag === 'true') {
62
92
  result.push(String(name));
63
- continue;
64
- }
65
- // Fallback: check functions array
66
- if (funcType) {
67
- for (let j = 0; j < 10; j++) {
68
- const type = boardConstants.get(`pins.all.${i}.functions.${j}.type`);
69
- if (type === undefined)
70
- break;
71
- if (String(type) === funcType) {
72
- result.push(String(name));
73
- break;
74
- }
75
- }
76
93
  }
77
94
  }
78
95
  return result;
79
96
  }
80
- /**
81
- * Does the board declare ANY per-pin `type:'pwm'` function entry anywhere?
82
- *
83
- * AVR-family boards (atmega328p, etc.) hardwire PWM to specific timer-output
84
- * pins, so their MCU descriptors list `{ type:'pwm', ... }` per pin and the
85
- * capability check correctly rejects PWM on non-timer pins. ESP32-family
86
- * boards route LEDC to ANY output GPIO via the GPIO matrix, so their MCU
87
- * descriptors carry zero `type:'pwm'` entries — PWM is a board-wide property
88
- * (the `pins.pwm` collection), not a per-pin function. On such boards the
89
- * per-pin capability check would false-positive on every pin, so the caller
90
- * skips it when this returns false. This distinguishes the two families
91
- * cleanly (AVR has entries, ESP32 has none) without special-casing arch names.
92
- */
93
- function boardHasAnyPwmFunctionEntries(boardConstants) {
94
- if (!boardConstants)
95
- return false;
96
- for (let i = 0; i < 100; i++) {
97
- if (boardConstants.get(`pins.all.${i}.name`) === undefined)
98
- continue;
99
- for (let j = 0; j < 10; j++) {
100
- const type = boardConstants.get(`pins.all.${i}.functions.${j}.type`);
101
- if (type === undefined)
102
- break;
103
- if (String(type) === 'pwm')
104
- return true;
105
- }
106
- }
107
- return false;
108
- }
109
97
  // ---------------------------------------------------------------------------
110
98
  // Capability check for a single HAL operation
111
99
  // ---------------------------------------------------------------------------
@@ -117,53 +105,29 @@ function checkCapability(operation, sourceLine, sourceCol, filePath, boardConsta
117
105
  const capability = operationToCapability(op);
118
106
  if (!capability)
119
107
  return; // GPIO/timing — always available.
120
- // ESP32-family boards route PWM (LEDC) to any output GPIO via the GPIO
121
- // matrix, so they carry zero per-pin `type:'pwm'` entries (unlike AVR,
122
- // which hardwires PWM to timer-output pins). On such boards the per-pin PWM
123
- // capability check would reject every pin; skip it and let the framework's
124
- // LEDC driver handle routing. This does NOT weaken AVR, which has entries.
125
- if (capability === 'pwm' && !boardHasAnyPwmFunctionEntries(boardConstants))
108
+ // Construction-time routing overrides (the escape hatch) let a user vouch
109
+ // for a pin the facts layer doesn't cover skip the capability check so
110
+ // an explicit channel/device/controller/pinctrl override is never rejected
111
+ // by the per-pin flag.
112
+ const override = operation;
113
+ if ((override.channelOverride !== undefined && override.channelOverride !== -1)
114
+ || override.deviceOverride
115
+ || override.pinctrlOverride
116
+ || override.controllerOverride) {
126
117
  return;
118
+ }
127
119
  const pin = operation.pin;
128
120
  if (typeof pin !== 'number' || pin < 0)
129
121
  return;
130
- // ADC channel reads (ADC.read(channel)) use channel numbers, not pin
131
- // numbers skip capability checking for adc ops where the "pin" is
132
- // actually a channel index (0-7 range, below the first analog pin).
133
- if (capability === 'analogInput' && op.startsWith('adc.') && pin < 14)
134
- return;
135
- // Check the pin's capability via the board definition.
136
- // Try the capabilities flag first, then fall back to scanning the
137
- // functions array (functions.N.type === capability prefix).
138
- const capFlag = boardConstants?.get(`pins.all.${pin}.capabilities.${capability}`);
122
+ // Check the pin's capability via the board definition's per-pin flag.
123
+ // The entry is resolved by pin NUMBER the array index diverges from the
124
+ // number on MCUs with unbonded pads (see pinEntryIndexForNumber).
125
+ const entryIdx = pinEntryIndexForNumber(pin, boardConstants);
126
+ if (entryIdx < 0)
127
+ return; // Unknown pin — the emitter's own resolution reports it.
128
+ const capFlag = boardConstants?.get(`pins.all.${entryIdx}.capabilities.${capability}`);
139
129
  if (capFlag === true || capFlag === 'true')
140
130
  return; // Capability confirmed.
141
- // Fallback: scan the functions array for a matching type.
142
- // PWM capability is indicated by functions[N].type === 'pwm',
143
- // ADC by 'adc', interrupts by 'interrupt' (external), DAC by 'dac'.
144
- const funcTypeMap = {
145
- pwm: 'pwm',
146
- analogInput: 'adc',
147
- analogOutput: 'dac',
148
- interrupt: 'interrupt',
149
- };
150
- const funcType = funcTypeMap[capability];
151
- if (funcType) {
152
- let hasCapabilityData = false;
153
- for (let i = 0; i < 10; i++) {
154
- const type = boardConstants?.get(`pins.all.${pin}.functions.${i}.type`);
155
- if (type === undefined)
156
- break;
157
- hasCapabilityData = true;
158
- if (String(type) === funcType)
159
- return; // Capability confirmed via functions.
160
- }
161
- // If the pin has NO functions entries at all AND the capability we're
162
- // checking is interrupt (which is stored in capabilities, not functions),
163
- // we can't determine support — skip to avoid false positives.
164
- if (!hasCapabilityData && capability === 'interrupt')
165
- return;
166
- }
167
131
  // Capability NOT supported — emit a diagnostic.
168
132
  const pinName = getPinName(pin, boardConstants);
169
133
  const validPins = findPinsWithCapability(capability, boardConstants);
@@ -17,7 +17,7 @@ const READ_METHODS = new Set([
17
17
  ]);
18
18
  /** Write operations that implicitly set OUTPUT mode on Wiring-derived frameworks. */
19
19
  const WRITE_METHODS = new Set([
20
- 'write', 'high', 'low', 'toggle', 'pulse', 'pwm', 'tone',
20
+ 'write', 'high', 'low', 'toggle', 'pulse', 'pwm',
21
21
  ]);
22
22
  /** Receiver kinds that represent GPIO pins. */
23
23
  const PIN_RECEIVER_KINDS = new Set([
@@ -85,7 +85,7 @@ export function validatePinModeConfig(program) {
85
85
  const inferReceiverKind = (method) => {
86
86
  if (method === 'readAnalog' || method === 'readVoltage')
87
87
  return 'analog-input';
88
- if (method === 'pwm' || method === 'tone')
88
+ if (method === 'pwm')
89
89
  return 'pwm';
90
90
  // Methods in the read/write/mode sets that aren't analog/pwm are digital.
91
91
  if (READ_METHODS.has(method) || WRITE_METHODS.has(method) || MODE_SET_METHODS.has(method))
@@ -99,11 +99,11 @@ export function validatePinModeConfig(program) {
99
99
  if (!op)
100
100
  return;
101
101
  const pinKey = `pin${op.pin}`;
102
- if (op.operation === 'gpio.set_mode') {
102
+ if (op.operation === 'gpio.configure' || op.operation === 'gpio.read_cfg') {
103
103
  pinModeSet.add(pinKey);
104
104
  analogDrivenPins.delete(pinKey);
105
105
  }
106
- else if (op.operation === 'pwm.write' || op.operation === 'tone.play') {
106
+ else if (op.operation === 'pwm.set_pulse' || op.operation === 'pwm.set_duty') {
107
107
  analogDrivenPins.add(pinKey);
108
108
  }
109
109
  else if (op.operation === 'gpio.write' || op.operation === 'gpio.toggle') {
@@ -270,7 +270,7 @@ export function validatePinModeConfig(program) {
270
270
  const checkStatement = (stmt) => {
271
271
  if (!stmt || typeof stmt !== 'object')
272
272
  return;
273
- // HAL-op statements: track pin-mode state from gpio.set_mode and warn on
273
+ // HAL-op statements: track pin-mode state from gpio.configure and warn on
274
274
  // gpio.read/write/toggle without prior mode configuration. After HAL
275
275
  // resolution, pin method calls (D2.isHigh(), D2.high()) become these
276
276
  // structured ops — the method-call form no longer exists at validation time.