@typecad/framework-zephyr 1.0.0-alpha.18 → 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.
- package/dist/audit.d.ts +111 -0
- package/dist/audit.js +416 -0
- package/dist/boardgen.js +63 -5
- package/dist/chips/resolve.js +20 -0
- package/dist/chips/types.d.ts +21 -0
- package/dist/display/bindings.d.ts +55 -0
- package/dist/display/bindings.js +316 -0
- package/dist/display/gfx.d.ts +2 -3
- package/dist/display/gfx.js +166 -154
- package/dist/display/index.js +20 -1
- package/dist/display/mipi-dbi-host.d.ts +9 -0
- package/dist/display/mipi-dbi-host.js +174 -0
- package/dist/display/profiles.d.ts +109 -4
- package/dist/display/profiles.js +270 -7
- package/dist/display/touch-adapter.js +118 -48
- package/dist/display/ui-adapter-eink.d.ts +2 -0
- package/dist/display/ui-adapter-eink.js +4 -0
- package/dist/display/ui-adapter-gray.d.ts +8 -0
- package/dist/display/ui-adapter-gray.js +170 -0
- package/dist/display/ui-adapter-mono.d.ts +13 -0
- package/dist/display/ui-adapter-mono.js +230 -0
- package/dist/display/ui-adapter-native.d.ts +10 -0
- package/dist/display/ui-adapter-native.js +295 -0
- package/dist/display/ui-adapter-shared.d.ts +11 -0
- package/dist/display/ui-adapter-shared.js +122 -0
- package/dist/display/ui-adapter.js +53 -101
- package/dist/dt-config/kconfig.d.ts +62 -1
- package/dist/dt-config/kconfig.js +123 -26
- package/dist/dt-config/overlay.d.ts +13 -0
- package/dist/dt-config/overlay.js +431 -16
- package/dist/framework.manifest.d.ts +9 -3
- package/dist/framework.manifest.js +123 -10
- package/dist/index.d.ts +2 -0
- package/dist/index.js +9 -1
- package/dist/licenses.js +5 -84
- package/dist/lowering/can.d.ts +25 -0
- package/dist/lowering/can.js +97 -0
- package/dist/lowering/clock.d.ts +17 -0
- package/dist/lowering/clock.js +58 -0
- package/dist/lowering/hid.d.ts +27 -0
- package/dist/lowering/hid.js +244 -0
- package/dist/lowering/i2c.d.ts +8 -0
- package/dist/lowering/i2c.js +140 -0
- package/dist/lowering/i2s.d.ts +27 -0
- package/dist/lowering/i2s.js +98 -0
- package/dist/lowering/index.d.ts +9 -1
- package/dist/lowering/index.js +25 -1
- package/dist/lowering/matrix.d.ts +15 -0
- package/dist/lowering/matrix.js +63 -0
- package/dist/lowering/power.d.ts +10 -0
- package/dist/lowering/power.js +35 -0
- package/dist/lowering/pwm.js +25 -0
- package/dist/lowering/sensor.d.ts +2 -2
- package/dist/lowering/sensor.js +8 -4
- package/dist/lowering/strip.d.ts +16 -0
- package/dist/lowering/strip.js +70 -0
- package/dist/lowering/thread.js +5 -1
- package/dist/lowering/trace.d.ts +44 -0
- package/dist/lowering/trace.js +239 -0
- package/dist/lowering/uart.js +6 -1
- package/dist/lowering/usb.d.ts +3 -1
- package/dist/lowering/usb.js +6 -3
- package/dist/sbom.d.ts +181 -0
- package/dist/sbom.js +901 -0
- package/dist/strategy.d.ts +60 -2
- package/dist/strategy.js +485 -25
- package/dist/toolchain/index.d.ts +12 -1
- package/dist/toolchain/index.js +115 -27
- package/dist/toolchain/scaffold.d.ts +4 -1
- package/dist/toolchain/scaffold.js +67 -3
- package/dist/west-inventory.d.ts +25 -0
- package/dist/west-inventory.js +97 -0
- package/package.json +3 -3
- package/src/audit.ts +529 -0
- package/src/boardgen.ts +54 -5
- package/src/chips/resolve.ts +21 -0
- package/src/chips/types.ts +576 -567
- package/src/display/bindings.ts +347 -0
- package/src/display/gfx.ts +318 -306
- package/src/display/index.ts +87 -70
- package/src/display/mipi-dbi-host.ts +183 -0
- package/src/display/profiles.ts +458 -139
- package/src/display/touch-adapter.ts +274 -204
- package/src/display/ui-adapter-eink.ts +13 -0
- package/src/display/ui-adapter-gray.ts +178 -0
- package/src/display/ui-adapter-mono.ts +238 -0
- package/src/display/ui-adapter-native.ts +304 -0
- package/src/display/ui-adapter-shared.ts +125 -0
- package/src/display/ui-adapter.ts +51 -100
- package/src/dt-config/kconfig.ts +647 -511
- package/src/dt-config/overlay.ts +433 -16
- package/src/framework.manifest.ts +131 -10
- package/src/index.ts +11 -1
- package/src/licenses.ts +5 -84
- package/src/lowering/can.ts +140 -0
- package/src/lowering/clock.ts +91 -0
- package/src/lowering/hid.ts +261 -0
- package/src/lowering/i2c.ts +146 -0
- package/src/lowering/i2s.ts +143 -0
- package/src/lowering/index.ts +18 -1
- package/src/lowering/matrix.ts +70 -0
- package/src/lowering/power.ts +41 -0
- package/src/lowering/pwm.ts +192 -167
- package/src/lowering/sensor.ts +159 -155
- package/src/lowering/strip.ts +81 -0
- package/src/lowering/thread.ts +5 -1
- package/src/lowering/trace.ts +270 -0
- package/src/lowering/uart.ts +6 -1
- package/src/lowering/usb.ts +224 -221
- package/src/sbom.ts +1117 -0
- package/src/strategy.ts +440 -25
- package/src/toolchain/index.ts +117 -28
- package/src/toolchain/scaffold.ts +62 -3
- package/src/west-inventory.ts +102 -0
package/dist/strategy.js
CHANGED
|
@@ -168,6 +168,66 @@ function collectPwmOverrideSpecs(program) {
|
|
|
168
168
|
* -Wunused-variable (Zephyr builds with warnings-as-errors), the same
|
|
169
169
|
* hygiene collectUsedPins enforces for per-channel ADC/PWM state.
|
|
170
170
|
*/
|
|
171
|
+
/**
|
|
172
|
+
* Strips the program drives, keyed by SPI controller index → the
|
|
173
|
+
* construction chain length (the buffer size). Collected from strip.* ops.
|
|
174
|
+
*/
|
|
175
|
+
/** Which HID protocol the program drives — 'mixed' when verbs from BOTH
|
|
176
|
+
* classes appear (one interface per program is the v1 ceiling; the caller
|
|
177
|
+
* turns mixed into a #error so the build names it clearly). */
|
|
178
|
+
function collectHidProtocol(program) {
|
|
179
|
+
if (!program)
|
|
180
|
+
return undefined;
|
|
181
|
+
let kb = false;
|
|
182
|
+
let mouse = false;
|
|
183
|
+
const visit = (node) => {
|
|
184
|
+
if (!node || typeof node !== 'object')
|
|
185
|
+
return;
|
|
186
|
+
const n = node;
|
|
187
|
+
const op = n.operation;
|
|
188
|
+
if (op && typeof op === 'object') {
|
|
189
|
+
const name = op.operation;
|
|
190
|
+
if (typeof name === 'string') {
|
|
191
|
+
if (name.startsWith('hid.kb_'))
|
|
192
|
+
kb = true;
|
|
193
|
+
if (name.startsWith('hid.mouse_'))
|
|
194
|
+
mouse = true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
for (const v of Object.values(n))
|
|
198
|
+
if (v && typeof v === 'object')
|
|
199
|
+
visit(v);
|
|
200
|
+
};
|
|
201
|
+
visit(program);
|
|
202
|
+
if (kb && mouse)
|
|
203
|
+
return 'mixed';
|
|
204
|
+
return kb ? 'keyboard' : mouse ? 'mouse' : undefined;
|
|
205
|
+
}
|
|
206
|
+
function collectStrips(program) {
|
|
207
|
+
if (!program)
|
|
208
|
+
return undefined;
|
|
209
|
+
const strips = new Map();
|
|
210
|
+
const visit = (node) => {
|
|
211
|
+
if (!node || typeof node !== 'object')
|
|
212
|
+
return;
|
|
213
|
+
const n = node;
|
|
214
|
+
const op = n.operation;
|
|
215
|
+
if (op && typeof op === 'object') {
|
|
216
|
+
const o = op;
|
|
217
|
+
if (o.operation === 'strip.set_pixel' || o.operation === 'strip.fill' || o.operation === 'strip.show') {
|
|
218
|
+
const m = String(o.bus ?? '').match(/(\d+)$/);
|
|
219
|
+
const idx = m ? parseInt(m[1], 10) : 0;
|
|
220
|
+
const count = Number(o.count ?? 1) || 1;
|
|
221
|
+
strips.set(idx, Math.max(strips.get(idx) ?? 0, count));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
for (const v of Object.values(n))
|
|
225
|
+
if (v && typeof v === 'object')
|
|
226
|
+
visit(v);
|
|
227
|
+
};
|
|
228
|
+
visit(program);
|
|
229
|
+
return strips;
|
|
230
|
+
}
|
|
171
231
|
function collectUsedBusIndices(program) {
|
|
172
232
|
if (!program)
|
|
173
233
|
return undefined;
|
|
@@ -233,9 +293,13 @@ export function collectSensors(program) {
|
|
|
233
293
|
const spiHz = o.spiHz ?? 0;
|
|
234
294
|
const spiMode = o.spiMode ?? 0;
|
|
235
295
|
const alertPin = o.alertPin ?? -1;
|
|
296
|
+
const resolution = o.resolution ?? 12;
|
|
236
297
|
const key = `${part}|${bus}|${port}|${busKind}`;
|
|
237
|
-
|
|
238
|
-
|
|
298
|
+
const existing = sensors.get(key);
|
|
299
|
+
if (!existing)
|
|
300
|
+
sensors.set(key, { part, bus, port, busKind, spiHz, spiMode, alertPin, resolution });
|
|
301
|
+
else if (o.resolution !== undefined)
|
|
302
|
+
existing.resolution = resolution;
|
|
239
303
|
}
|
|
240
304
|
}
|
|
241
305
|
for (const v of Object.values(n)) {
|
|
@@ -251,6 +315,173 @@ export function collectSensors(program) {
|
|
|
251
315
|
visitResolvedHalOps(program, visit);
|
|
252
316
|
return sensors;
|
|
253
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* The I2S construction facts the program's ops carry (the shim's slab and
|
|
320
|
+
* init helpers size from these) — first-seen wins, keyed by instance.
|
|
321
|
+
*/
|
|
322
|
+
export function collectI2s(program) {
|
|
323
|
+
if (!program)
|
|
324
|
+
return undefined;
|
|
325
|
+
const out = new Map();
|
|
326
|
+
const visit = (node) => {
|
|
327
|
+
if (!node || typeof node !== 'object')
|
|
328
|
+
return;
|
|
329
|
+
const n = node;
|
|
330
|
+
const op = n.operation;
|
|
331
|
+
if (op && typeof op === 'object') {
|
|
332
|
+
const o = op;
|
|
333
|
+
const name = o.operation;
|
|
334
|
+
if (name === 'i2s.write' || name === 'i2s.read') {
|
|
335
|
+
// Raw instance (no clamp): the strategy loop folds usage through
|
|
336
|
+
// lowerI2s's clamp, so the facts must stay keyed by what the ops
|
|
337
|
+
// actually carry.
|
|
338
|
+
const inst = Number(o.instance ?? 0);
|
|
339
|
+
if (!out.has(inst)) {
|
|
340
|
+
out.set(inst, {
|
|
341
|
+
hz: Number(o.hz ?? 16000),
|
|
342
|
+
channels: Number(o.channels ?? 2),
|
|
343
|
+
bits: Number(o.bits ?? 16),
|
|
344
|
+
blockFrames: Number(o.blockFrames ?? 64),
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
for (const v of Object.values(n)) {
|
|
350
|
+
if (Array.isArray(v)) {
|
|
351
|
+
for (const item of v)
|
|
352
|
+
visit(item);
|
|
353
|
+
}
|
|
354
|
+
else if (v && typeof v === 'object')
|
|
355
|
+
visit(v);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
visit(program);
|
|
359
|
+
visitResolvedHalOps(program, visit);
|
|
360
|
+
return out;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Which can / i2s / clock verbs the program's ops actually use — the init
|
|
364
|
+
* blocks emit only the state those verbs reference (Zephyr's -Werror turns
|
|
365
|
+
* an unreferenced static function/variable into a build failure: a
|
|
366
|
+
* send-only CAN program must not carry the rx trampoline, a now()-only
|
|
367
|
+
* Clock program must not carry the set() conversion helper). Returns
|
|
368
|
+
* undefined when there is no program to scan (probe flows) — callers then
|
|
369
|
+
* fall back to emitting every controller with the full state set.
|
|
370
|
+
*/
|
|
371
|
+
export function collectVerbUsage(program) {
|
|
372
|
+
if (!program)
|
|
373
|
+
return undefined;
|
|
374
|
+
const out = {
|
|
375
|
+
can: new Map(),
|
|
376
|
+
i2s: new Map(),
|
|
377
|
+
clock: { set: false, now: false },
|
|
378
|
+
};
|
|
379
|
+
const canFlags = (inst) => {
|
|
380
|
+
let f = out.can.get(inst);
|
|
381
|
+
if (!f) {
|
|
382
|
+
f = { begin: false, send: false, onReceive: false };
|
|
383
|
+
out.can.set(inst, f);
|
|
384
|
+
}
|
|
385
|
+
return f;
|
|
386
|
+
};
|
|
387
|
+
const i2sFlags = (inst) => {
|
|
388
|
+
let f = out.i2s.get(inst);
|
|
389
|
+
if (!f) {
|
|
390
|
+
f = { write: false, read: false, readAt: false };
|
|
391
|
+
out.i2s.set(inst, f);
|
|
392
|
+
}
|
|
393
|
+
return f;
|
|
394
|
+
};
|
|
395
|
+
const visit = (node) => {
|
|
396
|
+
if (!node || typeof node !== 'object')
|
|
397
|
+
return;
|
|
398
|
+
const n = node;
|
|
399
|
+
const op = n.operation;
|
|
400
|
+
if (op && typeof op === 'object') {
|
|
401
|
+
const o = op;
|
|
402
|
+
const name = o.operation;
|
|
403
|
+
const inst = Number(o.instance ?? 0);
|
|
404
|
+
switch (name) {
|
|
405
|
+
case 'can.begin':
|
|
406
|
+
canFlags(inst).begin = true;
|
|
407
|
+
break;
|
|
408
|
+
case 'can.send':
|
|
409
|
+
canFlags(inst).send = true;
|
|
410
|
+
break;
|
|
411
|
+
case 'can.on_receive':
|
|
412
|
+
canFlags(inst).onReceive = true;
|
|
413
|
+
break;
|
|
414
|
+
case 'i2s.write':
|
|
415
|
+
i2sFlags(inst).write = true;
|
|
416
|
+
break;
|
|
417
|
+
case 'i2s.read':
|
|
418
|
+
i2sFlags(inst).read = true;
|
|
419
|
+
break;
|
|
420
|
+
case 'i2s.read_at':
|
|
421
|
+
i2sFlags(inst).readAt = true;
|
|
422
|
+
break;
|
|
423
|
+
case 'clock.set':
|
|
424
|
+
out.clock.set = true;
|
|
425
|
+
break;
|
|
426
|
+
case 'clock.now':
|
|
427
|
+
out.clock.now = true;
|
|
428
|
+
break;
|
|
429
|
+
default: break;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
for (const v of Object.values(n)) {
|
|
433
|
+
if (Array.isArray(v)) {
|
|
434
|
+
for (const item of v)
|
|
435
|
+
visit(item);
|
|
436
|
+
}
|
|
437
|
+
else if (v && typeof v === 'object')
|
|
438
|
+
visit(v);
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
visit(program);
|
|
442
|
+
visitResolvedHalOps(program, visit);
|
|
443
|
+
return out;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Collect the distinct I2C responders the program's ops reference
|
|
447
|
+
* (i2c.resp_*), keyed `${bus}|${address}` — one target-mode address per
|
|
448
|
+
* constructed responder. Mirrors collectSpiTargets: the construction facts
|
|
449
|
+
* (rx/tx sizes) ride every op, so the first seen wins and the state block
|
|
450
|
+
* cannot drift from the call sites.
|
|
451
|
+
*/
|
|
452
|
+
export function collectI2cResponders(program) {
|
|
453
|
+
if (!program)
|
|
454
|
+
return undefined;
|
|
455
|
+
const responders = new Map();
|
|
456
|
+
const visit = (node) => {
|
|
457
|
+
if (!node || typeof node !== 'object')
|
|
458
|
+
return;
|
|
459
|
+
const n = node;
|
|
460
|
+
const op = n.operation;
|
|
461
|
+
if (op && typeof op === 'object') {
|
|
462
|
+
const o = op;
|
|
463
|
+
if (String(o.operation).startsWith('i2c.resp_')) {
|
|
464
|
+
const bus = String(o.bus ?? '');
|
|
465
|
+
const address = Number(o.address ?? 0);
|
|
466
|
+
const key = `${bus}|${address}`;
|
|
467
|
+
if (!responders.has(key)) {
|
|
468
|
+
responders.set(key, { bus, address, rx: Number(o.rx ?? 64), tx: Number(o.tx ?? 32) });
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
for (const v of Object.values(n)) {
|
|
473
|
+
if (Array.isArray(v)) {
|
|
474
|
+
for (const item of v)
|
|
475
|
+
visit(item);
|
|
476
|
+
}
|
|
477
|
+
else if (v && typeof v === 'object')
|
|
478
|
+
visit(v);
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
visit(program);
|
|
482
|
+
visitResolvedHalOps(program, visit);
|
|
483
|
+
return responders;
|
|
484
|
+
}
|
|
254
485
|
/**
|
|
255
486
|
* Collect the distinct thin SPI targets the program's ops reference
|
|
256
487
|
* (spi.transceive / spi.dev_write), keyed `${bus}|${cs}`. Mirrors
|
|
@@ -371,10 +602,18 @@ import { pwmInitLines } from './lowering/pwm.js';
|
|
|
371
602
|
import { dacInitLines } from './lowering/dac.js';
|
|
372
603
|
import { fsInitLines } from './lowering/fs.js';
|
|
373
604
|
import { hwtimerInitLines } from './lowering/hwtimer.js';
|
|
374
|
-
import { i2cInitLines } from './lowering/i2c.js';
|
|
605
|
+
import { i2cInitLines, i2cResponderStateLines } from './lowering/i2c.js';
|
|
606
|
+
import { parseControllerIndex } from './lowering/util.js';
|
|
607
|
+
import { stripInitLines } from './lowering/strip.js';
|
|
608
|
+
import { hidInitLines } from './lowering/hid.js';
|
|
609
|
+
import { matrixInitLines } from './lowering/matrix.js';
|
|
610
|
+
import { clockInitLines } from './lowering/clock.js';
|
|
611
|
+
import { canInitLines } from './lowering/can.js';
|
|
612
|
+
import { i2sInitLines } from './lowering/i2s.js';
|
|
375
613
|
import { sensorStateLines } from './lowering/sensor.js';
|
|
376
614
|
import { spiTargetStateLines } from './lowering/spi.js';
|
|
377
615
|
import { threadStateLines } from './lowering/thread.js';
|
|
616
|
+
import { traceHeartbeatLines, uiFrameTraceLines, clampTraceIntervalMs } from './lowering/trace.js';
|
|
378
617
|
import { uartRingStateLines } from './lowering/uart.js';
|
|
379
618
|
import { spiInitLines } from './lowering/spi.js';
|
|
380
619
|
import { uartInitLines } from './lowering/uart.js';
|
|
@@ -412,7 +651,8 @@ import { randomInitLines } from './lowering/random.js';
|
|
|
412
651
|
import { generateStaticAsyncRuntime } from '@typecad/cuttlefish/api/shared';
|
|
413
652
|
import { resolveZephyrDisplayOp, newDisplayState } from './display/index.js';
|
|
414
653
|
import { buildDisplayRuntime } from './display/gfx.js';
|
|
415
|
-
import { ZEPHYR_DISPLAY_PROFILES, BUILT_IN_PROFILES } from './display/profiles.js';
|
|
654
|
+
import { ZEPHYR_DISPLAY_PROFILES, BUILT_IN_PROFILES, isDtCompatible, isMonoDisplay, isGrayDisplay, isEinkDisplay } from './display/profiles.js';
|
|
655
|
+
import { listBoundDisplayCompatibles } from './display/bindings.js';
|
|
416
656
|
import { zephyrDisplayAdapterGenerator } from './display/ui-adapter.js';
|
|
417
657
|
import { zephyrTouchAdapter } from './display/touch-adapter.js';
|
|
418
658
|
/** debugMode() memo — the boardgen facts lookup is not free and the method is
|
|
@@ -500,6 +740,28 @@ export class ZephyrStrategy {
|
|
|
500
740
|
inc.push('<zephyr/drivers/sensor.h>');
|
|
501
741
|
if (uses('usesSPI'))
|
|
502
742
|
inc.push('<zephyr/drivers/spi.h>');
|
|
743
|
+
if (uses('usesStrip'))
|
|
744
|
+
inc.push('<zephyr/drivers/led_strip.h>');
|
|
745
|
+
if (uses('usesHid')) {
|
|
746
|
+
inc.push('<zephyr/usb/class/hid.h>');
|
|
747
|
+
inc.push('<zephyr/usb/class/usbd_hid.h>');
|
|
748
|
+
inc.push('<zephyr/usb/usbd.h>');
|
|
749
|
+
inc.push('<zephyr/drivers/usb/usb_buf.h>');
|
|
750
|
+
}
|
|
751
|
+
if (uses('usesMatrix'))
|
|
752
|
+
inc.push('<zephyr/input/input.h>');
|
|
753
|
+
if (uses('usesPower'))
|
|
754
|
+
inc.push('<zephyr/sys/poweroff.h>');
|
|
755
|
+
// esp_sleep.h exists only on the espressif HAL — gate on the harvested
|
|
756
|
+
// RTC wake-timer fact (the includes' uses() reads op flags, not src).
|
|
757
|
+
if (uses('usesPower') && chip.powerWakeTimer)
|
|
758
|
+
inc.push('<esp_sleep.h>');
|
|
759
|
+
if (uses('usesClock'))
|
|
760
|
+
inc.push('<zephyr/drivers/rtc.h>');
|
|
761
|
+
if (uses('usesCan'))
|
|
762
|
+
inc.push('<zephyr/drivers/can.h>');
|
|
763
|
+
if (uses('usesI2s'))
|
|
764
|
+
inc.push('<zephyr/drivers/i2s.h>');
|
|
503
765
|
if (uses('usesUart'))
|
|
504
766
|
inc.push('<zephyr/drivers/uart.h>');
|
|
505
767
|
// USB CDC serial: the class instance is a UART device (uart.h); the
|
|
@@ -800,21 +1062,29 @@ export class ZephyrStrategy {
|
|
|
800
1062
|
'static inline char* __tc_fmt_num_buf(double v, char* out, size_t cap) {',
|
|
801
1063
|
' if (v != v) { snprintf(out, cap, "nan"); return out; }',
|
|
802
1064
|
' double a = v < 0 ? -v : v;',
|
|
803
|
-
' long long ip =
|
|
804
|
-
' long long fr =
|
|
1065
|
+
' long long ip = static_cast<long long>(a);',
|
|
1066
|
+
' long long fr = static_cast<long long>((a - static_cast<double>(ip)) * 1000000.0 + 0.5);',
|
|
805
1067
|
' if (fr >= 1000000LL) { ip += 1LL; fr = 0LL; }',
|
|
806
1068
|
' int used = 0;',
|
|
807
1069
|
' if (v < 0 && (ip != 0LL || fr != 0LL)) { out[used++] = \'-\'; out[used] = \'\\0\'; }',
|
|
808
|
-
' if (fr == 0LL) { snprintf(out + used, cap - (
|
|
1070
|
+
' if (fr == 0LL) { snprintf(out + used, cap - static_cast<size_t>(used), "%lld", ip); return out; }',
|
|
809
1071
|
' char fbuf[8];',
|
|
810
1072
|
' int len = snprintf(fbuf, sizeof(fbuf), "%06lld", fr);',
|
|
811
1073
|
' while (len > 0 && fbuf[len - 1] == \'0\') { fbuf[--len] = \'\\0\'; }',
|
|
812
|
-
' snprintf(out + used, cap - (
|
|
1074
|
+
' snprintf(out + used, cap - static_cast<size_t>(used), "%lld.%s", ip, fbuf);',
|
|
813
1075
|
' return out;',
|
|
814
1076
|
'}',
|
|
815
1077
|
'static void __tc_fmt_num(double v) { char __b[32]; printf("%s", __tc_fmt_num_buf(v, __b, sizeof(__b))); }',
|
|
816
1078
|
].join('\n'), 'inline void __tc_print(double v) { __tc_fmt_num(v); }', 'inline void __tc_println(const char* s) { printf("%s\\n", s); }', 'inline void __tc_println(double v) { __tc_fmt_num(v); printf("\\n"); }');
|
|
817
1079
|
}
|
|
1080
|
+
// Trace user-event helpers (Trace.mark / Trace.event → trace.mark /
|
|
1081
|
+
// trace.event ops): one [TR:EV:<uptime_ms>:<name>[:<value>] console line
|
|
1082
|
+
// per call, captured host-side as timeline events. Emitted
|
|
1083
|
+
// UNCONDITIONALLY like __tc_print — a Trace.mark() call site must never
|
|
1084
|
+
// fail to link because zephyr.trace was disabled; with no capture
|
|
1085
|
+
// listening the lines are ordinary console output. Value formatting
|
|
1086
|
+
// reuses __tc_fmt_num_buf (integer-only, the picolibc %g trap).
|
|
1087
|
+
guardBody.push('inline void __tc_trace_mark(const char* name) {', ' printf("[TR:EV:%u:%s\\n", static_cast<unsigned int>(k_uptime_get_32()), name);', '}', 'inline void __tc_trace_event(const char* name, double v) {', ' char __b[32];', ' printf("[TR:EV:%u:%s:%s\\n", static_cast<unsigned int>(k_uptime_get_32()), name, __tc_fmt_num_buf(v, __b, sizeof(__b)));', '}');
|
|
818
1088
|
// Serial-port write helper: writes a scalar to a UART/CDC device a byte at
|
|
819
1089
|
// a time. Overloaded on const char* (strings, snprintf buffers) and double
|
|
820
1090
|
// (numbers/booleans) so a single __tc_dev_put(dev, value) call site formats
|
|
@@ -830,12 +1100,29 @@ export class ZephyrStrategy {
|
|
|
830
1100
|
// declared controller's __tc_<bus>N_dev trips -Wunused-variable under
|
|
831
1101
|
// Zephyr's -Werror (collectUsedBusIndices; probes with no program emit all).
|
|
832
1102
|
const usedBuses = collectUsedBusIndices(program);
|
|
1103
|
+
// Verb-level usage for the can.*/i2s.*/clock.* init blocks (see
|
|
1104
|
+
// collectVerbUsage) — undefined when there is no program (probe flows
|
|
1105
|
+
// emit the full state set).
|
|
1106
|
+
const verbUsage = collectVerbUsage(program);
|
|
833
1107
|
if (uses('usesI2C') && chip.i2c) {
|
|
834
1108
|
for (let i = 0; i < chip.i2c.controllers.length; i++) {
|
|
835
1109
|
if (usedBuses && !usedBuses.i2c.has(i))
|
|
836
1110
|
continue;
|
|
837
1111
|
guardBody.push(...i2cInitLines(chip, i));
|
|
838
1112
|
}
|
|
1113
|
+
// I2C responders — one target-mode state block per constructed
|
|
1114
|
+
// responder (bus|address), against the controller handles above
|
|
1115
|
+
// (collectI2cResponders; the ops mark the bus used, so the handle
|
|
1116
|
+
// the registration references is always present).
|
|
1117
|
+
const responders = collectI2cResponders(program);
|
|
1118
|
+
if (responders) {
|
|
1119
|
+
for (const r of responders.values()) {
|
|
1120
|
+
const idx = parseControllerIndex(r.bus);
|
|
1121
|
+
if (idx >= chip.i2c.controllers.length)
|
|
1122
|
+
continue;
|
|
1123
|
+
guardBody.push(...i2cResponderStateLines(chip, idx, r.address, r.rx, r.tx));
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
839
1126
|
}
|
|
840
1127
|
if (uses('usesSPI') && chip.spi) {
|
|
841
1128
|
for (let i = 0; i < chip.spi.controllers.length; i++) {
|
|
@@ -844,6 +1131,79 @@ export class ZephyrStrategy {
|
|
|
844
1131
|
guardBody.push(...spiInitLines(chip, i));
|
|
845
1132
|
}
|
|
846
1133
|
}
|
|
1134
|
+
// LED strips — one buffer + device handle per driven SPI controller
|
|
1135
|
+
// (chain length from the construction facts).
|
|
1136
|
+
{
|
|
1137
|
+
const strips = collectStrips(program);
|
|
1138
|
+
if (uses('usesStrip') && strips) {
|
|
1139
|
+
for (const [idx, count] of strips) {
|
|
1140
|
+
guardBody.push(...stripInitLines(chip, idx, count));
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
// Key matrix — the input-subsystem trampoline (the DT node comes from
|
|
1145
|
+
// the overlay generator, driven by the toolchain's matrix scan).
|
|
1146
|
+
if (uses('usesMatrix')) {
|
|
1147
|
+
guardBody.push(...matrixInitLines());
|
|
1148
|
+
}
|
|
1149
|
+
// Wall-clock shim — the epoch<->civil helpers + the rtc alias handle
|
|
1150
|
+
// (the DT node comes from the overlay generator's shim synthesis).
|
|
1151
|
+
if (uses('usesClock')) {
|
|
1152
|
+
const clockUsage = verbUsage?.clock ?? { set: true, now: true };
|
|
1153
|
+
guardBody.push(...clockInitLines(clockUsage));
|
|
1154
|
+
}
|
|
1155
|
+
// CAN — per-controller device handle + the rx trampoline (the DT node
|
|
1156
|
+
// is the board's own can@ node, enabled by the overlay). Only the
|
|
1157
|
+
// controllers the program addresses, and only the state its verbs
|
|
1158
|
+
// reference (collectVerbUsage; probes with no program emit all). Usage
|
|
1159
|
+
// folds through the same clamp lowerCan applies to out-of-range
|
|
1160
|
+
// instances, so the state block for the clamped controller emits.
|
|
1161
|
+
if (uses('usesCan') && chip.can) {
|
|
1162
|
+
const nCtrl = chip.can.controllers.length;
|
|
1163
|
+
const canUsage = verbUsage?.can;
|
|
1164
|
+
const folded = Array.from({ length: nCtrl }, () => ({ begin: false, send: false, onReceive: false }));
|
|
1165
|
+
if (canUsage) {
|
|
1166
|
+
for (const [inst, flags] of canUsage) {
|
|
1167
|
+
const f = folded[Math.max(0, Math.min(inst, nCtrl - 1))];
|
|
1168
|
+
f.begin = f.begin || flags.begin;
|
|
1169
|
+
f.send = f.send || flags.send;
|
|
1170
|
+
f.onReceive = f.onReceive || flags.onReceive;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
for (let i = 0; i < nCtrl; i++) {
|
|
1174
|
+
const f = folded[i];
|
|
1175
|
+
if (canUsage && !f.begin && !f.send && !f.onReceive)
|
|
1176
|
+
continue;
|
|
1177
|
+
guardBody.push(...canInitLines(chip, i, canUsage ? f : { begin: true, send: true, onReceive: true }));
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
// I2S — per-controller slab + block buffers + lazy direction inits,
|
|
1181
|
+
// sized from the construction facts the ops carry. Same used-instance
|
|
1182
|
+
// and clamp-fold discipline as CAN.
|
|
1183
|
+
if (uses('usesI2s') && chip.i2s) {
|
|
1184
|
+
const i2sFacts = collectI2s(program);
|
|
1185
|
+
const nCtrl = chip.i2s.controllers.length;
|
|
1186
|
+
const i2sUsage = verbUsage?.i2s;
|
|
1187
|
+
const folded = Array.from({ length: nCtrl }, () => ({ write: false, read: false, readAt: false }));
|
|
1188
|
+
if (i2sUsage) {
|
|
1189
|
+
for (const [inst, flags] of i2sUsage) {
|
|
1190
|
+
const f = folded[Math.max(0, Math.min(inst, nCtrl - 1))];
|
|
1191
|
+
f.write = f.write || flags.write;
|
|
1192
|
+
f.read = f.read || flags.read;
|
|
1193
|
+
f.readAt = f.readAt || flags.readAt;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
for (let i = 0; i < nCtrl; i++) {
|
|
1197
|
+
const f = folded[i];
|
|
1198
|
+
if (i2sUsage && !f.write && !f.read && !f.readAt)
|
|
1199
|
+
continue;
|
|
1200
|
+
const facts = i2sFacts?.get(i);
|
|
1201
|
+
const channels = facts?.channels ?? 2;
|
|
1202
|
+
const bits = facts?.bits ?? 16;
|
|
1203
|
+
const blockFrames = facts?.blockFrames ?? 64;
|
|
1204
|
+
guardBody.push(...i2sInitLines(chip, i, blockFrames * channels * (bits / 8), i2sUsage ? f : { write: true, read: true, readAt: true }));
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
847
1207
|
if (uses('usesUart') && chip.uart) {
|
|
848
1208
|
for (let i = 0; i < chip.uart.controllers.length; i++) {
|
|
849
1209
|
if (usedBuses && !usedBuses.uart.has(i))
|
|
@@ -866,7 +1226,7 @@ export class ZephyrStrategy {
|
|
|
866
1226
|
const sensors = collectSensors(program);
|
|
867
1227
|
if (sensors) {
|
|
868
1228
|
for (const s of sensors.values()) {
|
|
869
|
-
guardBody.push(...sensorStateLines(s.part, s.bus, s.port, s.busKind, s.spiHz, s.spiMode, s.alertPin));
|
|
1229
|
+
guardBody.push(...sensorStateLines(s.part, s.bus, s.port, s.busKind, s.spiHz, s.spiMode, s.alertPin, s.resolution));
|
|
870
1230
|
}
|
|
871
1231
|
}
|
|
872
1232
|
}
|
|
@@ -892,10 +1252,52 @@ export class ZephyrStrategy {
|
|
|
892
1252
|
}
|
|
893
1253
|
}
|
|
894
1254
|
}
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1255
|
+
// Trace heartbeat — the runtime-stats sampler behind `typecad-hal trace
|
|
1256
|
+
// capture`. Opt-in via zephyr.trace.enabled in typecad-hal.config.ts (the
|
|
1257
|
+
// config loader threads the zephyr record through platformContext). The
|
|
1258
|
+
// block compiles under CUTTLEFISH_ENTRY_TU, so split-file TUs carry no
|
|
1259
|
+
// second copy (a duplicate SYS_INIT would double every heartbeat).
|
|
1260
|
+
// UI-mounted programs additionally get the frame-stats block (always
|
|
1261
|
+
// defined, active only under CUTTLEFISH_TRACE_UI) so the ui_tick call
|
|
1262
|
+
// site's instrumentation never depends on the trace config.
|
|
1263
|
+
{
|
|
1264
|
+
const traceCfg = ctx
|
|
1265
|
+
?.zephyr?.trace;
|
|
1266
|
+
const traceEnabled = traceCfg?.enabled === true;
|
|
1267
|
+
if (traceEnabled && entryHasUI()) {
|
|
1268
|
+
guardBody.push('#if defined(CUTTLEFISH_ENTRY_TU)', '#define CUTTLEFISH_TRACE_UI 1', '#endif');
|
|
1269
|
+
}
|
|
1270
|
+
if (entryHasUI()) {
|
|
1271
|
+
guardBody.push(...uiFrameTraceLines(traceCfg?.alarms?.frameMaxMs));
|
|
1272
|
+
}
|
|
1273
|
+
if (traceEnabled) {
|
|
1274
|
+
guardBody.push(...traceHeartbeatLines(clampTraceIntervalMs(traceCfg?.intervalMs), entryHasUI(), traceCfg?.alarms));
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
// The usbd context is shared by CDC and HID; the CDC per-instance
|
|
1278
|
+
// state only emits when the program actually uses usb.* (an HID-only
|
|
1279
|
+
// program would otherwise carry an unused __tc_usb0_dev).
|
|
1280
|
+
if ((uses('usesUsb') || uses('usesHid')) && chip.usb) {
|
|
1281
|
+
guardBody.push(...usbdDeviceLines(chip, { hid: uses('usesHid') }));
|
|
1282
|
+
if (uses('usesUsb')) {
|
|
1283
|
+
for (let i = 0; i < chip.usb.cdcInstances; i++)
|
|
1284
|
+
guardBody.push(...usbInitLines(chip, i));
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
// USB HID — one interface per program; the protocol comes from which
|
|
1288
|
+
// class's verbs the program used (keyboard vs mouse). Requires the USB
|
|
1289
|
+
// device context (the same one CDC rides — the register helper calls
|
|
1290
|
+
// __tc_usbd_start).
|
|
1291
|
+
if (uses('usesHid') && chip.usb) {
|
|
1292
|
+
const protocol = collectHidProtocol(program) ?? 'keyboard';
|
|
1293
|
+
if (protocol === 'mixed') {
|
|
1294
|
+
// One zephyr,hid-device interface per program (the v1 ceiling) —
|
|
1295
|
+
// name it at compile time instead of an undefined-symbol error.
|
|
1296
|
+
guardBody.push('#error "typecad-hal: one HID interface per program (v1) — Keyboard and Mouse cannot be mixed in one app"');
|
|
1297
|
+
}
|
|
1298
|
+
else {
|
|
1299
|
+
guardBody.push(...hidInitLines(protocol));
|
|
1300
|
+
}
|
|
899
1301
|
}
|
|
900
1302
|
// PWM init also fires (with alias vars for the override pins) when a
|
|
901
1303
|
// program drives ONLY inline-override channels on a chip with no pwm
|
|
@@ -1017,7 +1419,11 @@ export class ZephyrStrategy {
|
|
|
1017
1419
|
// precede the wiring-ambient shims and the PinGroup factory there; the
|
|
1018
1420
|
// __tc_gpio_read body below is what still needs emitting here.)
|
|
1019
1421
|
if (this.needsGpioReadShim(program, ctx)) {
|
|
1020
|
-
lines.push('inline int __tc_gpio_read(int pin) { return gpio_pin_get_raw(__tc_gpio_dev(static_cast<uint32_t>(pin)), __tc_gpio_pin(static_cast<uint32_t>(pin))); }'
|
|
1422
|
+
lines.push('inline int __tc_gpio_read(int pin) { return gpio_pin_get_raw(__tc_gpio_dev(static_cast<uint32_t>(pin)), __tc_gpio_pin(static_cast<uint32_t>(pin))); }',
|
|
1423
|
+
// Runtime input configuration for ui.watchPin / ui.press setup
|
|
1424
|
+
// (the strategy's setPinMode lowers here). Idempotent — setup calls
|
|
1425
|
+
// it once per watched pin before the poll loop reads it.
|
|
1426
|
+
'inline void __tc_gpio_configure_input(uint32_t pin) { gpio_pin_configure(__tc_gpio_dev(pin), __tc_gpio_pin(pin), GPIO_INPUT | GPIO_PULL_UP); }');
|
|
1021
1427
|
}
|
|
1022
1428
|
// __tc_gpio_write / __tc_delay_us are only referenced via @typecad/safety
|
|
1023
1429
|
// lowering, so they stay gated on it.
|
|
@@ -1771,6 +2177,17 @@ export class ZephyrStrategy {
|
|
|
1771
2177
|
postIteration: 'k_msleep(1);',
|
|
1772
2178
|
};
|
|
1773
2179
|
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Per-frame wall-time feed for the trace heartbeat's UI stats. The helper
|
|
2182
|
+
* is emitted unconditionally for UI programs (compiles to a no-op unless
|
|
2183
|
+
* zephyr.trace defined CUTTLEFISH_TRACE_UI), so this call is safe with
|
|
2184
|
+
* tracing on or off.
|
|
2185
|
+
*/
|
|
2186
|
+
uiFrameTimingLines(deltaMsExpr) {
|
|
2187
|
+
if (!entryHasUI())
|
|
2188
|
+
return null;
|
|
2189
|
+
return [`__tc_trace_ui_frame(static_cast<uint32_t>(${deltaMsExpr}));`];
|
|
2190
|
+
}
|
|
1774
2191
|
// ── Type aliases ────────────────────────────────────────────────────────
|
|
1775
2192
|
shouldSkipTypeAlias() {
|
|
1776
2193
|
return false;
|
|
@@ -2005,9 +2422,14 @@ struct __tc_StaticArray {
|
|
|
2005
2422
|
writeDigitalPin(pin, val) {
|
|
2006
2423
|
return `__tc_gpio_write(${pin}, ${val})`;
|
|
2007
2424
|
}
|
|
2008
|
-
setPinMode(
|
|
2009
|
-
//
|
|
2010
|
-
|
|
2425
|
+
setPinMode(pin, _mode) {
|
|
2426
|
+
// Runtime input configuration: Zephyr has no pinMode — the GPIO API
|
|
2427
|
+
// configures direction/pull explicitly. The mode argument is ignored:
|
|
2428
|
+
// every watchPin/press consumer wants an input with pull-up (buttons are
|
|
2429
|
+
// active-low), and __tc_gpio_configure_input hardcodes exactly that.
|
|
2430
|
+
// The helper's definition rides the GPIO read shim (same gate — UI builds
|
|
2431
|
+
// with pin watchers always carry the read surface too).
|
|
2432
|
+
return `__tc_gpio_configure_input(static_cast<uint32_t>(${pin}));`;
|
|
2011
2433
|
}
|
|
2012
2434
|
delayMs(ms) {
|
|
2013
2435
|
return `k_msleep(${ms})`;
|
|
@@ -2043,16 +2465,31 @@ struct __tc_StaticArray {
|
|
|
2043
2465
|
return resolveZephyrDisplayOp(op, this._displayState);
|
|
2044
2466
|
}
|
|
2045
2467
|
supportedDisplayDrivers() {
|
|
2046
|
-
|
|
2468
|
+
// Registry profiles plus every panel compatible with a display binding in
|
|
2469
|
+
// the user's Zephyr tree — the drop-in path (display.driver = compatible)
|
|
2470
|
+
// validates at mount like any curated profile. No tree discoverable →
|
|
2471
|
+
// registry only.
|
|
2472
|
+
const drivers = new Set(Object.keys(ZEPHYR_DISPLAY_PROFILES));
|
|
2473
|
+
try {
|
|
2474
|
+
for (const compatible of listBoundDisplayCompatibles())
|
|
2475
|
+
drivers.add(compatible);
|
|
2476
|
+
}
|
|
2477
|
+
catch {
|
|
2478
|
+
// Tree unreadable — the registry set stands.
|
|
2479
|
+
}
|
|
2480
|
+
return drivers;
|
|
2047
2481
|
}
|
|
2048
2482
|
// ── Strategy-owned display/touch adapter seam ────────────────────────────
|
|
2049
2483
|
// Zephyr owns its display + touch adapters: the UI display adapter bridges
|
|
2050
|
-
// the in-tree CuttlefishGFX class to the panel
|
|
2051
|
-
//
|
|
2052
|
-
//
|
|
2053
|
-
//
|
|
2054
|
-
//
|
|
2055
|
-
//
|
|
2484
|
+
// the in-tree CuttlefishGFX class to the panel via one of two transports
|
|
2485
|
+
// (per profile — 'direct-spi': per-controller init + wire format over
|
|
2486
|
+
// spi_write, see src/display/ui-adapter.ts; 'zephyr-display': Zephyr's
|
|
2487
|
+
// display API with in-tree panel drivers, see src/display/ui-adapter-native.ts),
|
|
2488
|
+
// and the touch adapters drive the FT6336U (I2C capacitive) and XPT2046
|
|
2489
|
+
// (SPI resistive) controllers via Zephyr's bus APIs (src/display/touch-adapter.ts).
|
|
2490
|
+
// Both live in this package so cuttlefish carries no Zephyr/Wiring-specific
|
|
2491
|
+
// display or touch knowledge. Mirrors ArduinoStrategy's provides*/resolve*
|
|
2492
|
+
// pattern.
|
|
2056
2493
|
providesDisplayAdapter() { return true; }
|
|
2057
2494
|
resolveDisplayAdapter(display) {
|
|
2058
2495
|
const code = zephyrDisplayAdapterGenerator(display);
|
|
@@ -2071,7 +2508,30 @@ struct __tc_StaticArray {
|
|
|
2071
2508
|
return new Map(Object.entries(BUILT_IN_PROFILES));
|
|
2072
2509
|
}
|
|
2073
2510
|
colorFormat() {
|
|
2074
|
-
|
|
2511
|
+
// The seeded display state is the truth after display.init (drop-in mono
|
|
2512
|
+
// panels synthesize 'mono'); the default profile keeps the pre-init
|
|
2513
|
+
// rgb565 answer byte-identical with history.
|
|
2514
|
+
return this._displayState.profile.colorFormat;
|
|
2515
|
+
}
|
|
2516
|
+
colorFormatForDriver(driver) {
|
|
2517
|
+
// Drop-in panel class from the compatible table (DATA): the 1bpp OLED
|
|
2518
|
+
// family lowers mono engine-side and the 16-gray family lowers gray8,
|
|
2519
|
+
// so colors flatten at build time instead of rgb565-lowering into an
|
|
2520
|
+
// adapter that cannot show them. Registry profiles carry their own
|
|
2521
|
+
// colorFormat; non-compatible driver ids keep the default.
|
|
2522
|
+
if (isDtCompatible(driver) && isMonoDisplay({ driver }))
|
|
2523
|
+
return 'mono';
|
|
2524
|
+
if (isDtCompatible(driver) && isEinkDisplay({ driver }))
|
|
2525
|
+
return 'mono';
|
|
2526
|
+
if (isDtCompatible(driver) && isGrayDisplay({ driver }))
|
|
2527
|
+
return 'gray8';
|
|
2528
|
+
return undefined;
|
|
2529
|
+
}
|
|
2530
|
+
displayClassForDriver(driver) {
|
|
2531
|
+
// The compatible table decides (DATA) — ssd16xx/uc81xx are e-ink.
|
|
2532
|
+
if (isDtCompatible(driver) && isEinkDisplay({ driver }))
|
|
2533
|
+
return 'eink';
|
|
2534
|
+
return undefined;
|
|
2075
2535
|
}
|
|
2076
2536
|
graphicsCapacity() {
|
|
2077
2537
|
return {
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { ToolchainOptions, CompileResult, UploadResult } from '@typecad/cuttlefish/api/shared';
|
|
2
2
|
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
3
|
+
export declare function scanMatrix(src: string): {
|
|
4
|
+
rows: number[];
|
|
5
|
+
cols: number[];
|
|
6
|
+
} | undefined;
|
|
7
|
+
export declare function scanHid(src: string): 'keyboard' | 'mouse' | undefined;
|
|
8
|
+
export declare function scanStrips(src: string): Array<{
|
|
9
|
+
index: number;
|
|
10
|
+
count: number;
|
|
11
|
+
}>;
|
|
3
12
|
/**
|
|
4
13
|
* Distinct DT-bound sensors the emitted sources reference — the lowering's
|
|
5
14
|
* state blocks name each one `__tc_sensor_<part>_i2c<N>_0x<addr>_dev`
|
|
@@ -11,10 +20,12 @@ export interface ScannedSensorPart {
|
|
|
11
20
|
part: string;
|
|
12
21
|
busIndex: number;
|
|
13
22
|
port: number;
|
|
14
|
-
busKind: 'i2c' | 'spi';
|
|
23
|
+
busKind: 'i2c' | 'spi' | 'w1';
|
|
15
24
|
spiHz: number;
|
|
16
25
|
spiMode: number;
|
|
17
26
|
alertPin: number;
|
|
27
|
+
/** 1-Wire parts: the converter resolution in bits. */
|
|
28
|
+
resolution: number;
|
|
18
29
|
}
|
|
19
30
|
export interface ScannedSpiTarget {
|
|
20
31
|
busIndex: number;
|