@typecad/framework-zephyr 1.0.0-alpha.16 → 1.0.0-alpha.19

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 (210) hide show
  1. package/LICENSE +202 -21
  2. package/README.md +49 -87
  3. package/dist/as-built.d.ts +2 -2
  4. package/dist/as-built.js +2 -2
  5. package/dist/audit.d.ts +111 -0
  6. package/dist/audit.js +416 -0
  7. package/dist/boardgen.d.ts +1 -9
  8. package/dist/boardgen.js +288 -47
  9. package/dist/chips/resolve.js +20 -0
  10. package/dist/chips/types.d.ts +22 -1
  11. package/dist/debug-codegen.js +1 -1
  12. package/dist/display/bindings.d.ts +55 -0
  13. package/dist/display/bindings.js +316 -0
  14. package/dist/display/gfx.d.ts +2 -3
  15. package/dist/display/gfx.js +166 -154
  16. package/dist/display/index.js +20 -1
  17. package/dist/display/mipi-dbi-host.d.ts +9 -0
  18. package/dist/display/mipi-dbi-host.js +174 -0
  19. package/dist/display/profiles.d.ts +109 -4
  20. package/dist/display/profiles.js +270 -7
  21. package/dist/display/touch-adapter.js +119 -49
  22. package/dist/display/ui-adapter-eink.d.ts +2 -0
  23. package/dist/display/ui-adapter-eink.js +4 -0
  24. package/dist/display/ui-adapter-gray.d.ts +8 -0
  25. package/dist/display/ui-adapter-gray.js +170 -0
  26. package/dist/display/ui-adapter-mono.d.ts +13 -0
  27. package/dist/display/ui-adapter-mono.js +230 -0
  28. package/dist/display/ui-adapter-native.d.ts +10 -0
  29. package/dist/display/ui-adapter-native.js +295 -0
  30. package/dist/display/ui-adapter-shared.d.ts +11 -0
  31. package/dist/display/ui-adapter-shared.js +122 -0
  32. package/dist/display/ui-adapter.js +510 -558
  33. package/dist/doctor.js +4 -4
  34. package/dist/dt-config/custom-board.js +2 -2
  35. package/dist/dt-config/kconfig.d.ts +62 -1
  36. package/dist/dt-config/kconfig.js +141 -38
  37. package/dist/dt-config/overlay.d.ts +15 -2
  38. package/dist/dt-config/overlay.js +433 -18
  39. package/dist/framework.manifest.d.ts +10 -4
  40. package/dist/framework.manifest.js +133 -17
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.js +14 -6
  43. package/dist/licenses.d.ts +2 -2
  44. package/dist/licenses.js +13 -92
  45. package/dist/lowering/can.d.ts +25 -0
  46. package/dist/lowering/can.js +97 -0
  47. package/dist/lowering/clock.d.ts +17 -0
  48. package/dist/lowering/clock.js +58 -0
  49. package/dist/lowering/fs.js +1 -1
  50. package/dist/lowering/gpio.js +0 -32
  51. package/dist/lowering/hid.d.ts +27 -0
  52. package/dist/lowering/hid.js +244 -0
  53. package/dist/lowering/http.js +264 -32
  54. package/dist/lowering/i2c.d.ts +8 -0
  55. package/dist/lowering/i2c.js +137 -5
  56. package/dist/lowering/i2s.d.ts +27 -0
  57. package/dist/lowering/i2s.js +98 -0
  58. package/dist/lowering/index.d.ts +9 -1
  59. package/dist/lowering/index.js +25 -1
  60. package/dist/lowering/interrupts.js +6 -0
  61. package/dist/lowering/matrix.d.ts +15 -0
  62. package/dist/lowering/matrix.js +63 -0
  63. package/dist/lowering/mqtt.js +110 -8
  64. package/dist/lowering/power.d.ts +3 -2
  65. package/dist/lowering/power.js +20 -45
  66. package/dist/lowering/pwm.js +25 -0
  67. package/dist/lowering/sensor.d.ts +2 -2
  68. package/dist/lowering/sensor.js +8 -4
  69. package/dist/lowering/strip.d.ts +16 -0
  70. package/dist/lowering/strip.js +70 -0
  71. package/dist/lowering/thread.js +5 -1
  72. package/dist/lowering/trace.d.ts +44 -0
  73. package/dist/lowering/trace.js +239 -0
  74. package/dist/lowering/uart.js +6 -1
  75. package/dist/lowering/usb.d.ts +3 -1
  76. package/dist/lowering/usb.js +16 -13
  77. package/dist/lowering/wdt.js +2 -29
  78. package/dist/sbom.d.ts +181 -0
  79. package/dist/sbom.js +901 -0
  80. package/dist/sdk/board-catalog-sync.d.ts +1 -3
  81. package/dist/sdk/board-catalog-sync.js +4 -10
  82. package/dist/strategy.d.ts +82 -46
  83. package/dist/strategy.js +639 -182
  84. package/dist/tmp-probe.d.ts +2 -0
  85. package/dist/tmp-probe.js +9 -0
  86. package/dist/toolchain/debug-config.d.ts +50 -90
  87. package/dist/toolchain/debug-config.js +239 -510
  88. package/dist/toolchain/env-check.d.ts +1 -3
  89. package/dist/toolchain/env-check.js +2 -7
  90. package/dist/toolchain/index.d.ts +28 -3
  91. package/dist/toolchain/index.js +498 -62
  92. package/dist/toolchain/runners.d.ts +16 -0
  93. package/dist/toolchain/runners.js +75 -0
  94. package/dist/toolchain/scaffold.d.ts +5 -2
  95. package/dist/toolchain/scaffold.js +79 -15
  96. package/dist/toolchain/west-discover.d.ts +6 -0
  97. package/dist/toolchain/west-discover.js +36 -13
  98. package/dist/toolchain/west-spawn.js +8 -2
  99. package/dist/west-inventory.d.ts +25 -0
  100. package/dist/west-inventory.js +97 -0
  101. package/installer/README.md +328 -328
  102. package/installer/install.sh +2 -2
  103. package/installer/templates/project/.typecad/activate-zephyr.ps1 +1 -1
  104. package/installer/templates/project/.typecad/activate-zephyr.sh +1 -1
  105. package/installer/templates/project/.vscode/settings.json +1 -1
  106. package/installer/templates/project/README.md +2 -2
  107. package/package.json +5 -5
  108. package/src/as-built.ts +206 -206
  109. package/src/audit.ts +529 -0
  110. package/src/boardgen.ts +265 -50
  111. package/src/chips/resolve.ts +21 -0
  112. package/src/chips/types.ts +10 -1
  113. package/src/display/bindings.ts +347 -0
  114. package/src/display/gfx.ts +318 -306
  115. package/src/display/index.ts +87 -70
  116. package/src/display/mipi-dbi-host.ts +183 -0
  117. package/src/display/profiles.ts +458 -139
  118. package/src/display/touch-adapter.ts +119 -49
  119. package/src/display/ui-adapter-eink.ts +13 -0
  120. package/src/display/ui-adapter-gray.ts +178 -0
  121. package/src/display/ui-adapter-mono.ts +238 -0
  122. package/src/display/ui-adapter-native.ts +304 -0
  123. package/src/display/ui-adapter-shared.ts +125 -0
  124. package/src/display/ui-adapter.ts +732 -781
  125. package/src/doctor.ts +4 -4
  126. package/src/dt-config/custom-board.ts +2 -2
  127. package/src/dt-config/kconfig.ts +647 -505
  128. package/src/dt-config/overlay.ts +1475 -1058
  129. package/src/framework.manifest.ts +659 -535
  130. package/src/index.ts +16 -6
  131. package/src/licenses.ts +346 -425
  132. package/src/lowering/can.ts +140 -0
  133. package/src/lowering/clock.ts +91 -0
  134. package/src/lowering/fs.ts +135 -135
  135. package/src/lowering/gpio.ts +0 -33
  136. package/src/lowering/hid.ts +261 -0
  137. package/src/lowering/http.ts +264 -32
  138. package/src/lowering/i2c.ts +142 -5
  139. package/src/lowering/i2s.ts +143 -0
  140. package/src/lowering/index.ts +18 -1
  141. package/src/lowering/interrupts.ts +6 -0
  142. package/src/lowering/matrix.ts +70 -0
  143. package/src/lowering/mqtt.ts +109 -8
  144. package/src/lowering/power.ts +41 -0
  145. package/src/lowering/pwm.ts +192 -167
  146. package/src/lowering/sensor.ts +159 -155
  147. package/src/lowering/strip.ts +81 -0
  148. package/src/lowering/thread.ts +5 -1
  149. package/src/lowering/trace.ts +270 -0
  150. package/src/lowering/uart.ts +6 -1
  151. package/src/lowering/usb.ts +16 -13
  152. package/src/lowering/wdt.ts +2 -25
  153. package/src/sbom.ts +1117 -0
  154. package/src/sdk/board-catalog-sync.ts +4 -25
  155. package/src/strategy.ts +2680 -2309
  156. package/src/toolchain/debug-config.ts +262 -522
  157. package/src/toolchain/env-check.ts +279 -285
  158. package/src/toolchain/index.ts +1792 -1359
  159. package/src/toolchain/runners.ts +80 -0
  160. package/src/toolchain/scaffold.ts +355 -296
  161. package/src/toolchain/west-discover.ts +35 -13
  162. package/src/toolchain/west-spawn.ts +174 -168
  163. package/src/west-inventory.ts +102 -0
  164. package/dist/async/timer-polyfill.d.ts +0 -10
  165. package/dist/async/timer-polyfill.js +0 -95
  166. package/dist/chips/board-overrides.d.ts +0 -7
  167. package/dist/chips/board-overrides.js +0 -11
  168. package/dist/chips/esp32.d.ts +0 -2
  169. package/dist/chips/esp32.js +0 -71
  170. package/dist/chips/esp32s3.d.ts +0 -2
  171. package/dist/chips/esp32s3.js +0 -103
  172. package/dist/chips/soc/.d.ts +0 -2
  173. package/dist/chips/soc/.js +0 -129
  174. package/dist/chips/soc/esp32.d.ts +0 -2
  175. package/dist/chips/soc/esp32.js +0 -120
  176. package/dist/chips/soc/esp32c3.d.ts +0 -2
  177. package/dist/chips/soc/esp32c3.js +0 -90
  178. package/dist/chips/soc/esp32c6.d.ts +0 -2
  179. package/dist/chips/soc/esp32c6.js +0 -109
  180. package/dist/chips/soc/esp32s3.d.ts +0 -2
  181. package/dist/chips/soc/esp32s3.js +0 -189
  182. package/dist/chips/soc/index.d.ts +0 -2
  183. package/dist/chips/soc/index.js +0 -23
  184. package/dist/chips/soc/nrf52840.d.ts +0 -2
  185. package/dist/chips/soc/nrf52840.js +0 -130
  186. package/dist/chips/soc/rp2040.d.ts +0 -2
  187. package/dist/chips/soc/rp2040.js +0 -141
  188. package/dist/chips/soc/rp2350a.d.ts +0 -2
  189. package/dist/chips/soc/rp2350a.js +0 -145
  190. package/dist/chips/soc/samd21g18a.d.ts +0 -2
  191. package/dist/chips/soc/samd21g18a.js +0 -143
  192. package/dist/chips/soc/stm32f411xe.d.ts +0 -2
  193. package/dist/chips/soc/stm32f411xe.js +0 -251
  194. package/dist/chips/xiao-ble.d.ts +0 -2
  195. package/dist/chips/xiao-ble.js +0 -100
  196. package/dist/lowering/pulse.d.ts +0 -7
  197. package/dist/lowering/pulse.js +0 -51
  198. package/dist/lowering/tone.d.ts +0 -10
  199. package/dist/lowering/tone.js +0 -63
  200. package/dist/lowering/worker-backing.d.ts +0 -14
  201. package/dist/lowering/worker-backing.js +0 -79
  202. package/dist/lowering/worker.d.ts +0 -6
  203. package/dist/lowering/worker.js +0 -14
  204. package/dist/sdk/board-data.generated.d.ts +0 -2
  205. package/dist/sdk/board-data.generated.js +0 -4
  206. package/dist/sdk/catalog-walker.d.ts +0 -90
  207. package/dist/sdk/catalog-walker.js +0 -682
  208. package/dist/sdk/dts-reader.d.ts +0 -83
  209. package/dist/sdk/dts-reader.js +0 -596
  210. package/src/debug-codegen.ts +0 -207
@@ -0,0 +1,55 @@
1
+ /** A required property as harvested from a binding. */
2
+ export interface RequiredProp {
3
+ /** Binding type string (e.g. 'int', 'uint8-array', 'boolean'). */
4
+ type?: string;
5
+ /** The binding's default, when it ships one (some props are deliberately
6
+ * default-free — "panel specific" per the sitronix gamma bindings). */
7
+ default?: BindingDefault;
8
+ }
9
+ /** A harvested display binding: what the overlay generator needs. */
10
+ export interface DisplayBindingInfo {
11
+ /** The compatible string this binding documents. */
12
+ compatible: string;
13
+ /** Transport family from the include chain — decides the overlay node
14
+ * shape (I2C child vs mipi-dbi SPI child) and the Kconfig bus. */
15
+ busFamily: 'i2c' | 'spi';
16
+ /** Required properties (DT name → binding facts). */
17
+ required: Map<string, RequiredProp>;
18
+ /** Every property name the binding (or its include chain) declares,
19
+ * optional ones included — rotation-style props (madctl) are optional
20
+ * with neutral defaults, but the drop-in path expresses config rotation
21
+ * through them, so their presence matters. */
22
+ props: Set<string>;
23
+ /** True when the include chain pulls in lcd-controller.yaml — that family
24
+ * makes `pixel-format` required (0 = RGB565 per dt-bindings/display/panel.h). */
25
+ requiresPixelFormat: boolean;
26
+ }
27
+ /** A parsed binding default: scalar or byte-array. */
28
+ export type BindingDefault = {
29
+ kind: 'int';
30
+ value: number;
31
+ } | {
32
+ kind: 'bool';
33
+ value: boolean;
34
+ } | {
35
+ kind: 'string';
36
+ value: string;
37
+ } | {
38
+ kind: 'bytes';
39
+ value: number[];
40
+ };
41
+ /** @internal Replace the Zephyr tree root (tests only). */
42
+ export declare function __setDisplayBindingRootOverride(root: string | undefined): void;
43
+ /** Locate the Zephyr tree via the board catalog's canonical discovery
44
+ * ($ZEPHYR_BASE → well-known workspaces → installer env-vars). Cached. */
45
+ export declare function findZephyrBase(): string | undefined;
46
+ /** Harvest a display binding by compatible string. Walks the include chain
47
+ * (child requirements win; the lcd-controller family is detected anywhere
48
+ * in the chain). Returns undefined for unknown compatibles or when no
49
+ * Zephyr tree is discoverable. */
50
+ export declare function readDisplayBinding(compatible: string): DisplayBindingInfo | undefined;
51
+ /** @internal Same harvest against an explicit root (tests). */
52
+ export declare function readDisplayBindingFrom(compatible: string, root: string): DisplayBindingInfo | undefined;
53
+ /** All display-panel compatibles with bindings in the tree (for mount
54
+ * validation: ui.mount accepts any of these driver strings). */
55
+ export declare function listBoundDisplayCompatibles(): string[];
@@ -0,0 +1,316 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Display binding harvest — the Zephyr tree IS the panel catalog.
3
+ //
4
+ // Drop-in display support ("no special profiles"): a project declares a DT
5
+ // compatible string (display.driver, e.g. 'sitronix,st7796s') plus wiring and
6
+ // geometry; everything the devicetree overlay needs to emit a VALID node for
7
+ // that panel comes from the binding YAMLs in the user's Zephyr checkout —
8
+ // required properties, their defaults, and the include chain (e.g. whether
9
+ // the lcd-controller family makes pixel-format mandatory). Same doctrine as
10
+ // the board catalog: the installed SDK is the source of truth; no curated
11
+ // per-panel database in this package.
12
+ //
13
+ // The parser is deliberately a shape-reader, not a YAML implementation: it
14
+ // extracts `compatible:`, `include:` lists, and per-property `required:`/
15
+ // `default:` scalars from Zephyr's binding grammar (2-space nesting, inline
16
+ // flow arrays). Anything else is ignored — bindings carry descriptions and
17
+ // constraints this consumer does not need.
18
+ // ---------------------------------------------------------------------------
19
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
20
+ import { join } from 'node:path';
21
+ import { locateZephyrBaseCheap } from '@typecad/cuttlefish/board-catalog';
22
+ /** Test seam: override the Zephyr root for hermetic fixtures. */
23
+ let rootOverride;
24
+ /** @internal Replace the Zephyr tree root (tests only). */
25
+ export function __setDisplayBindingRootOverride(root) {
26
+ rootOverride = root;
27
+ yamlIndex = undefined;
28
+ }
29
+ let cachedBase;
30
+ let yamlIndex;
31
+ /** Locate the Zephyr tree via the board catalog's canonical discovery
32
+ * ($ZEPHYR_BASE → well-known workspaces → installer env-vars). Cached. */
33
+ export function findZephyrBase() {
34
+ if (rootOverride)
35
+ return rootOverride;
36
+ if (cachedBase !== undefined)
37
+ return cachedBase;
38
+ cachedBase = locateZephyrBaseCheap() ?? undefined;
39
+ return cachedBase;
40
+ }
41
+ /** Index every binding YAML under dts/bindings by filename (bindings include
42
+ * each other by bare filename across subdirectories — e.g. a display
43
+ * binding includes i2c-device.yaml, which lives in bindings/i2c/). */
44
+ function bindingIndex(root) {
45
+ if (yamlIndex)
46
+ return yamlIndex;
47
+ const index = new Map();
48
+ const walk = (dir) => {
49
+ for (const entry of readdirSync(dir)) {
50
+ const full = join(dir, entry);
51
+ const st = statSync(full);
52
+ if (st.isDirectory())
53
+ walk(full);
54
+ else if (entry.endsWith('.yaml') || entry.endsWith('.yml'))
55
+ index.set(entry, full);
56
+ }
57
+ };
58
+ walk(join(root, 'dts', 'bindings'));
59
+ yamlIndex = index;
60
+ return index;
61
+ }
62
+ /** Parse one binding file's shape: compatible, includes, required props. */
63
+ function parseBinding(path) {
64
+ const text = readFileSync(path, 'utf8');
65
+ const includes = [];
66
+ const required = new Map();
67
+ const props = new Set();
68
+ let compatible;
69
+ let section = 'none';
70
+ let currentProp;
71
+ let currentDefault;
72
+ let currentType;
73
+ const commitProp = () => {
74
+ if (currentProp !== undefined && propIsRequired) {
75
+ const prev = required.get(currentProp);
76
+ required.set(currentProp, {
77
+ type: currentType ?? prev?.type,
78
+ default: finalizeDefault(currentDefault, defaultItems) ?? prev?.default,
79
+ });
80
+ }
81
+ currentProp = undefined;
82
+ currentDefault = undefined;
83
+ currentType = undefined;
84
+ defaultItems = null;
85
+ propIsRequired = false;
86
+ };
87
+ let propIsRequired = false;
88
+ let defaultItems = null;
89
+ for (const rawLine of text.split(/\r?\n/)) {
90
+ if (!rawLine.trim() || rawLine.trimStart().startsWith('#'))
91
+ continue;
92
+ const indent = rawLine.length - rawLine.trimStart().length;
93
+ const line = rawLine.trim();
94
+ // Block-style default list (default: followed by '- item' lines) —
95
+ // common for long byte arrays the real bindings ship multi-line.
96
+ if (defaultItems !== null) {
97
+ if (indent > 4 && line.startsWith('- ')) {
98
+ defaultItems.push(line.slice(2).trim());
99
+ continue;
100
+ }
101
+ // Dedent ends the list; fall through to normal handling of this line.
102
+ const items = defaultItems;
103
+ defaultItems = null;
104
+ currentDefault = itemsToDefault(items);
105
+ }
106
+ if (indent === 0) {
107
+ commitProp();
108
+ const key = line.split(':')[0].trim();
109
+ if (key === 'include') {
110
+ section = 'include';
111
+ collectIncludes(line.slice(line.indexOf(':') + 1), includes);
112
+ }
113
+ else if (key === 'properties') {
114
+ section = 'properties';
115
+ }
116
+ else {
117
+ section = 'none';
118
+ if (key === 'compatible') {
119
+ const v = scalarString(line.slice(line.indexOf(':') + 1));
120
+ if (v !== undefined)
121
+ compatible = v;
122
+ }
123
+ }
124
+ continue;
125
+ }
126
+ if (section === 'include' && indent === 2 && line.startsWith('- ')) {
127
+ collectIncludes(line.slice(2), includes);
128
+ }
129
+ else if (section === 'properties' && indent === 2) {
130
+ commitProp();
131
+ currentProp = line.split(':')[0].trim();
132
+ if (currentProp)
133
+ props.add(currentProp);
134
+ }
135
+ else if (section === 'properties' && indent === 4 && currentProp) {
136
+ const key = line.split(':')[0].trim();
137
+ const rest = line.slice(line.indexOf(':') + 1).trim();
138
+ if (key === 'required' && rest === 'true') {
139
+ propIsRequired = true;
140
+ }
141
+ else if (key === 'type') {
142
+ currentType = rest.replace(/["']/g, '') || undefined;
143
+ }
144
+ else if (key === 'default') {
145
+ if (rest === '') {
146
+ defaultItems = []; // block list follows
147
+ }
148
+ else {
149
+ currentDefault = parseDefault(rest);
150
+ }
151
+ }
152
+ }
153
+ }
154
+ commitProp();
155
+ return { compatible, includes, required, props };
156
+ }
157
+ function finalizeDefault(inline, items) {
158
+ if (items !== null && items.length > 0)
159
+ return itemsToDefault(items);
160
+ return inline ?? (items !== null ? { kind: 'bytes', value: [] } : undefined);
161
+ }
162
+ function itemsToDefault(items) {
163
+ if (items.length === 1)
164
+ return parseDefault(items[0]);
165
+ const bytes = items
166
+ .map((t) => {
167
+ const c = t.replace(/["']/g, '');
168
+ return c.toLowerCase().startsWith('0x') ? parseInt(c.slice(2), 16) : parseInt(c, 10);
169
+ })
170
+ .filter((n) => !Number.isNaN(n));
171
+ return { kind: 'bytes', value: bytes };
172
+ }
173
+ function collectIncludes(fragment, out) {
174
+ const f = fragment.trim();
175
+ if (!f)
176
+ return;
177
+ if (f.startsWith('[')) {
178
+ // Extract filename tokens by pattern (commas INCLUDED — binding
179
+ // filenames are vendor,panel.yaml and cannot be split or excluded on commas) — NEVER split on commas: binding
180
+ // filenames themselves contain commas (vendor,panel.yaml), and a comma
181
+ // split silently mangles them into nonexistent includes.
182
+ for (const m of f.matchAll(/[A-Za-z0-9_.,-]+\.ya?ml/g))
183
+ out.push(m[0]);
184
+ }
185
+ else if (f.startsWith('- ')) {
186
+ pushInclude(f.slice(2).trim(), out);
187
+ }
188
+ else {
189
+ pushInclude(f, out);
190
+ }
191
+ }
192
+ function pushInclude(item, out) {
193
+ // The `- name: foo.yaml` include form (with optional property-blocklist).
194
+ // The match is ANCHORED: an unanchored /name:/ can false-match inside
195
+ // filenames (e.g. vendor,panel-common.yaml) and silently mangle the
196
+ // include chain — the missing-prop class this harvest exists to prevent.
197
+ let name = item.trim().replace(/["']/g, '');
198
+ const m = name.match(/^name:\s*(\S+)$/);
199
+ if (m)
200
+ name = m[1];
201
+ if (name.endsWith('.yaml') || name.endsWith('.yml'))
202
+ out.push(name);
203
+ }
204
+ function scalarString(fragment) {
205
+ const f = fragment.trim().replace(/["']/g, '');
206
+ return f || undefined;
207
+ }
208
+ function parseDefault(rest) {
209
+ const f = rest.trim();
210
+ if (f === 'true' || f === 'false')
211
+ return { kind: 'bool', value: f === 'true' };
212
+ if (f.startsWith('[')) {
213
+ const bytes = f
214
+ .slice(1, f.endsWith(']') ? -1 : undefined)
215
+ .split(',')
216
+ .map((s) => {
217
+ const t = s.trim().replace(/["']/g, '');
218
+ return t.toLowerCase().startsWith('0x')
219
+ ? parseInt(t.slice(2), 16)
220
+ : parseInt(t, 10);
221
+ })
222
+ .filter((n) => !Number.isNaN(n));
223
+ return { kind: 'bytes', value: bytes };
224
+ }
225
+ if (/^-?\d+$/.test(f))
226
+ return { kind: 'int', value: parseInt(f, 10) };
227
+ return { kind: 'string', value: f.replace(/["']/g, '') };
228
+ }
229
+ /** Harvest a display binding by compatible string. Walks the include chain
230
+ * (child requirements win; the lcd-controller family is detected anywhere
231
+ * in the chain). Returns undefined for unknown compatibles or when no
232
+ * Zephyr tree is discoverable. */
233
+ export function readDisplayBinding(compatible) {
234
+ const root = findZephyrBase();
235
+ if (!root)
236
+ return undefined;
237
+ return readDisplayBindingFrom(compatible, root);
238
+ }
239
+ /** @internal Same harvest against an explicit root (tests). */
240
+ export function readDisplayBindingFrom(compatible, root) {
241
+ const index = bindingIndex(root);
242
+ const visited = new Set();
243
+ const required = new Map();
244
+ const props = new Set();
245
+ let requiresPixelFormat = false;
246
+ let busFamily = 'spi';
247
+ const noteFamily = (fileName) => {
248
+ if (fileName === 'i2c-device.yaml')
249
+ busFamily = 'i2c';
250
+ if (fileName === 'mipi-dbi-spi-device.yaml' || fileName === 'spi-device.yaml')
251
+ busFamily = 'spi';
252
+ };
253
+ const load = (fileName) => {
254
+ const path = index.get(fileName);
255
+ if (!path || visited.has(fileName))
256
+ return;
257
+ visited.add(fileName);
258
+ const raw = parseBinding(path);
259
+ noteFamily(fileName);
260
+ if (fileName === 'lcd-controller.yaml')
261
+ requiresPixelFormat = true;
262
+ for (const [prop, info] of raw.required) {
263
+ const prev = required.get(prop);
264
+ required.set(prop, {
265
+ type: info.type ?? prev?.type,
266
+ default: info.default ?? prev?.default,
267
+ });
268
+ }
269
+ for (const inc of raw.includes)
270
+ load(inc);
271
+ };
272
+ const noteProps = (fileName) => {
273
+ const path = index.get(fileName);
274
+ if (!path)
275
+ return;
276
+ const raw = parseBinding(path);
277
+ for (const p of raw.props)
278
+ props.add(p);
279
+ for (const inc of raw.includes)
280
+ noteProps(inc);
281
+ };
282
+ // Find the binding whose declared compatible matches.
283
+ for (const [fileName, path] of index) {
284
+ if (!fileName.includes(','))
285
+ continue; // compatibles are vendor,name.yaml
286
+ const raw = parseBinding(path);
287
+ if (raw.compatible === compatible) {
288
+ load(fileName);
289
+ noteProps(fileName);
290
+ return { compatible, required, requiresPixelFormat, props, busFamily };
291
+ }
292
+ }
293
+ return undefined;
294
+ }
295
+ /** All display-panel compatibles with bindings in the tree (for mount
296
+ * validation: ui.mount accepts any of these driver strings). */
297
+ export function listBoundDisplayCompatibles() {
298
+ const root = findZephyrBase();
299
+ if (!root)
300
+ return [];
301
+ const index = bindingIndex(root);
302
+ const out = [];
303
+ for (const [fileName, path] of index) {
304
+ if (!fileName.includes(','))
305
+ continue; // compatibles are vendor,name.yaml
306
+ // Panel bindings live under dts/bindings/display/ — match the path
307
+ // segment, not the filename (compatibles don't contain "display").
308
+ const normalized = path.replace(/\\/g, '/');
309
+ if (!/\/bindings\/display\//.test(normalized))
310
+ continue;
311
+ const raw = parseBinding(path);
312
+ if (raw.compatible)
313
+ out.push(raw.compatible);
314
+ }
315
+ return out.sort();
316
+ }
@@ -19,8 +19,7 @@ export interface DisplayRuntimeResult {
19
19
  * - `'mono'` (OLED, e.g. SSD1306): a full framebuffer — the standard model
20
20
  * for page-buffered monochrome panels (the AGENTS.md "no full framebuffer"
21
21
  * guardrail targets RGB SPI TFTs, not mono OLEDs). draw ops set bits;
22
- * display_flush pushes the whole framebuffer. The MONO01 packing is
23
- * horizontal, MSB-first (Zephyr convention): byte = (y*rowBytes)+(x>>3),
24
- * bit = 0x80>>(x&7).
22
+ * display_flush pushes the whole framebuffer as VTILED MONO01 (the layout
23
+ * the driver consumes; see monoHelpers).
25
24
  */
26
25
  export declare function buildDisplayRuntime(profile: ZephyrDisplayProfile): DisplayRuntimeResult;