@typecad/framework-zephyr 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.
- package/README.md +22 -35
- package/dist/as-built.d.ts +33 -0
- package/dist/as-built.js +188 -0
- package/dist/async/timer-polyfill.js +1 -1
- package/dist/boardgen.d.ts +128 -0
- package/dist/boardgen.js +1366 -0
- package/dist/chips/board-overrides.d.ts +7 -0
- package/dist/chips/board-overrides.js +11 -0
- package/dist/chips/controllers.d.ts +28 -8
- package/dist/chips/controllers.js +49 -12
- package/dist/chips/esp32s3.js +49 -0
- package/dist/chips/index.d.ts +6 -12
- package/dist/chips/index.js +18 -34
- package/dist/chips/resolve.d.ts +16 -2
- package/dist/chips/resolve.js +298 -15
- package/dist/chips/soc/.d.ts +2 -0
- package/dist/chips/soc/.js +129 -0
- package/dist/chips/soc/esp32.d.ts +2 -0
- package/dist/chips/soc/esp32.js +120 -0
- package/dist/chips/soc/esp32c3.d.ts +2 -0
- package/dist/chips/soc/esp32c3.js +90 -0
- package/dist/chips/soc/esp32c6.d.ts +2 -0
- package/dist/chips/soc/esp32c6.js +109 -0
- package/dist/chips/soc/esp32s3.d.ts +2 -0
- package/dist/chips/soc/esp32s3.js +189 -0
- package/dist/chips/soc/index.d.ts +2 -0
- package/dist/chips/soc/index.js +23 -0
- package/dist/chips/soc/nrf52840.d.ts +2 -0
- package/dist/chips/soc/nrf52840.js +130 -0
- package/dist/chips/soc/rp2040.d.ts +2 -0
- package/dist/chips/soc/rp2040.js +141 -0
- package/dist/chips/soc/rp2350a.d.ts +2 -0
- package/dist/chips/soc/rp2350a.js +145 -0
- package/dist/chips/soc/samd21g18a.d.ts +2 -0
- package/dist/chips/soc/samd21g18a.js +143 -0
- package/dist/chips/soc/stm32f411xe.d.ts +2 -0
- package/dist/chips/soc/stm32f411xe.js +251 -0
- package/dist/chips/types.d.ts +382 -12
- package/dist/chips/xiao-ble.js +33 -0
- package/dist/display/profiles.js +1 -1
- package/dist/doctor.js +38 -4
- package/dist/dt-config/custom-board.d.ts +23 -0
- package/dist/dt-config/custom-board.js +227 -0
- package/dist/dt-config/kconfig.d.ts +83 -1
- package/dist/dt-config/kconfig.js +116 -27
- package/dist/dt-config/overlay.js +623 -18
- package/dist/framework.manifest.d.ts +20 -30
- package/dist/framework.manifest.js +124 -178
- package/dist/index.d.ts +4 -1
- package/dist/index.js +8 -2
- package/dist/lowering/adc.d.ts +26 -5
- package/dist/lowering/adc.js +137 -31
- package/dist/lowering/ble.js +31 -28
- package/dist/lowering/dac.js +9 -9
- package/dist/lowering/fs.js +18 -10
- package/dist/lowering/gpio.d.ts +2 -0
- package/dist/lowering/gpio.js +90 -10
- package/dist/lowering/http.js +39 -14
- package/dist/lowering/hwtimer.d.ts +4 -0
- package/dist/lowering/hwtimer.js +35 -10
- package/dist/lowering/i2c.js +46 -54
- package/dist/lowering/index.d.ts +5 -5
- package/dist/lowering/index.js +15 -16
- package/dist/lowering/interrupts.d.ts +22 -5
- package/dist/lowering/interrupts.js +104 -22
- package/dist/lowering/mqtt.js +12 -6
- package/dist/lowering/power.js +0 -4
- package/dist/lowering/preferences.js +49 -77
- package/dist/lowering/pulse.js +5 -36
- package/dist/lowering/pwm.d.ts +32 -3
- package/dist/lowering/pwm.js +105 -17
- package/dist/lowering/random.js +3 -3
- package/dist/lowering/sensor.d.ts +37 -0
- package/dist/lowering/sensor.js +119 -0
- package/dist/lowering/spi.d.ts +12 -0
- package/dist/lowering/spi.js +65 -40
- package/dist/lowering/thread.d.ts +14 -0
- package/dist/lowering/thread.js +55 -0
- package/dist/lowering/timing.js +20 -46
- package/dist/lowering/tone.js +18 -5
- package/dist/lowering/uart.d.ts +13 -0
- package/dist/lowering/uart.js +72 -51
- package/dist/lowering/usb.d.ts +34 -0
- package/dist/lowering/usb.js +206 -0
- package/dist/lowering/wdt.d.ts +1 -1
- package/dist/lowering/wdt.js +17 -7
- package/dist/lowering/wifi.d.ts +3 -2
- package/dist/lowering/wifi.js +120 -111
- package/dist/sdk/board-catalog-sync.d.ts +16 -0
- package/dist/sdk/board-catalog-sync.js +41 -0
- package/dist/sdk/board-data.generated.d.ts +2 -0
- package/dist/sdk/board-data.generated.js +4 -0
- package/dist/sdk/catalog-walker.d.ts +90 -0
- package/dist/sdk/catalog-walker.js +682 -0
- package/dist/sdk/dts-reader.d.ts +83 -0
- package/dist/sdk/dts-reader.js +596 -0
- package/dist/strategy.d.ts +136 -17
- package/dist/strategy.js +881 -212
- package/dist/toolchain/bossac-touch.d.ts +18 -0
- package/dist/toolchain/bossac-touch.js +88 -0
- package/dist/toolchain/compat.d.ts +2 -2
- package/dist/toolchain/compat.js +8 -3
- package/dist/toolchain/debug-config.d.ts +21 -26
- package/dist/toolchain/debug-config.js +212 -72
- package/dist/toolchain/env-check.d.ts +4 -4
- package/dist/toolchain/env-check.js +5 -5
- package/dist/toolchain/index.d.ts +66 -1
- package/dist/toolchain/index.js +713 -58
- package/dist/toolchain/scaffold.d.ts +9 -0
- package/dist/toolchain/scaffold.js +84 -7
- package/dist/toolchain/west-discover.d.ts +8 -1
- package/dist/toolchain/west-discover.js +19 -6
- package/dist/toolchain/west-spawn.js +17 -5
- package/installer/CHANGELOG.md +473 -0
- package/installer/README.md +328 -0
- package/installer/environment.yml +46 -0
- package/installer/etc/conda/activate.d/zephyr.bat +7 -0
- package/installer/etc/conda/activate.d/zephyr.ps1 +12 -0
- package/installer/etc/conda/activate.d/zephyr.sh +20 -0
- package/installer/etc/conda/deactivate.d/zephyr.bat +6 -0
- package/installer/etc/conda/deactivate.d/zephyr.ps1 +6 -0
- package/installer/etc/conda/deactivate.d/zephyr.sh +4 -0
- package/installer/install.mjs +580 -0
- package/installer/install.ps1 +619 -0
- package/installer/install.sh +310 -0
- package/installer/lib/detect-platform.sh +62 -0
- package/installer/lib/fetch-sdk.sh +304 -0
- package/installer/lib/init-workspace.sh +153 -0
- package/installer/lib/write-activation.sh +76 -0
- package/installer/patches/tfm-c-include-separators.patch +19 -0
- package/installer/patches/zephyr-tfm-nordic-zephyr-include.patch +24 -0
- package/installer/templates/project/.typecad/activate-zephyr.ps1 +31 -0
- package/installer/templates/project/.typecad/activate-zephyr.sh +31 -0
- package/installer/templates/project/.vscode/settings.json +30 -0
- package/installer/templates/project/README.md +58 -0
- package/installer/versions.env +110 -0
- package/package.json +16 -16
- package/src/as-built.ts +206 -0
- package/src/boardgen.ts +1428 -0
- package/src/chips/controllers.ts +61 -12
- package/src/chips/index.ts +35 -54
- package/src/chips/resolve.ts +316 -14
- package/src/chips/types.ts +388 -13
- package/src/display/profiles.ts +1 -1
- package/src/doctor.ts +110 -77
- package/src/dt-config/custom-board.ts +325 -0
- package/src/dt-config/kconfig.ts +177 -19
- package/src/dt-config/overlay.ts +1058 -450
- package/src/framework.manifest.ts +125 -178
- package/src/index.ts +57 -41
- package/src/lowering/adc.ts +222 -102
- package/src/lowering/ble.ts +32 -28
- package/src/lowering/dac.ts +82 -82
- package/src/lowering/fs.ts +18 -10
- package/src/lowering/gpio.ts +242 -152
- package/src/lowering/http.ts +512 -488
- package/src/lowering/hwtimer.ts +139 -101
- package/src/lowering/i2c.ts +116 -126
- package/src/lowering/index.ts +91 -93
- package/src/lowering/interrupts.ts +113 -21
- package/src/lowering/mqtt.ts +12 -6
- package/src/lowering/preferences.ts +327 -354
- package/src/lowering/pwm.ts +167 -74
- package/src/lowering/random.ts +3 -3
- package/src/lowering/sensor.ts +155 -0
- package/src/lowering/spi.ts +164 -124
- package/src/lowering/thread.ts +63 -0
- package/src/lowering/timing.ts +46 -72
- package/src/lowering/uart.ts +73 -51
- package/src/lowering/usb.ts +221 -0
- package/src/lowering/wdt.ts +95 -84
- package/src/lowering/wifi.ts +120 -111
- package/src/sdk/board-catalog-sync.ts +62 -0
- package/src/strategy.ts +888 -229
- package/src/toolchain/bossac-touch.ts +112 -0
- package/src/toolchain/compat.ts +8 -3
- package/src/toolchain/debug-config.ts +666 -522
- package/src/toolchain/env-check.ts +9 -9
- package/src/toolchain/index.ts +765 -44
- package/src/toolchain/scaffold.ts +81 -7
- package/src/toolchain/west-discover.ts +334 -316
- package/src/toolchain/west-spawn.ts +17 -5
- package/src/async/timer-polyfill.ts +0 -107
- package/src/chips/esp32.ts +0 -74
- package/src/chips/esp32s3.ts +0 -57
- package/src/chips/xiao-ble.ts +0 -70
- package/src/lowering/power.ts +0 -70
- package/src/lowering/pulse.ts +0 -93
- package/src/lowering/tone.ts +0 -60
- package/src/lowering/worker-backing.ts +0 -94
- package/src/lowering/worker.ts +0 -17
package/src/lowering/pwm.ts
CHANGED
|
@@ -1,74 +1,167 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// PWM lowering — pwm_dt_spec via pwm-led0 alias
|
|
3
|
-
//
|
|
4
|
-
// The XIAO nRF52840 exposes PWM via the `pwm-led0` devicetree alias (PWM_OUT0
|
|
5
|
-
// on P0.17, inverted). The lowering emits a `pwm_dt_spec` per channel and uses
|
|
6
|
-
// `pwm_set_pulse_dt` / `pwm_set_dt`. Duty is scaled from the Arduino-style
|
|
7
|
-
// 0–255 (or 0–1023) range to nanoseconds against the spec's period.
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
|
|
10
|
-
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
11
|
-
import type { ZephyrChipDescriptor, ZephyrPwmSpec } from '../chips/types.js';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function
|
|
20
|
-
return `
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// PWM lowering — pwm_dt_spec via pwm-led0 alias
|
|
3
|
+
//
|
|
4
|
+
// The XIAO nRF52840 exposes PWM via the `pwm-led0` devicetree alias (PWM_OUT0
|
|
5
|
+
// on P0.17, inverted). The lowering emits a `pwm_dt_spec` per channel and uses
|
|
6
|
+
// `pwm_set_pulse_dt` / `pwm_set_dt`. Duty is scaled from the Arduino-style
|
|
7
|
+
// 0–255 (or 0–1023) range to nanoseconds against the spec's period.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
|
|
10
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
11
|
+
import type { ZephyrChipDescriptor, ZephyrPwmSpec } from '../chips/types.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The DT alias a PWM spec is addressed by. Board-shipped specs carry their
|
|
15
|
+
* alias in `dtSpec`; synthesized specs (controller + channel) get a
|
|
16
|
+
* `tc-pwm<pin>` alias that the overlay generator creates in
|
|
17
|
+
* <board>.overlay — both sides derive the name from the pin so they agree.
|
|
18
|
+
*/
|
|
19
|
+
export function pwmDtAlias(spec: ZephyrPwmSpec): string {
|
|
20
|
+
return spec.dtSpec ?? `tc-pwm${spec.pin}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The C macro token for a spec's alias. Zephyr's devicetree macros replace
|
|
25
|
+
* dashes in alias names with underscores (`pwm-led0` in DTS is
|
|
26
|
+
* DT_ALIAS(pwm_led0) in C) — the dashed spelling is a subtraction
|
|
27
|
+
* expression and fails to compile (caught by the blackpill E2E west build).
|
|
28
|
+
*/
|
|
29
|
+
export function pwmDtAliasToken(spec: ZephyrPwmSpec): string {
|
|
30
|
+
return pwmDtAlias(spec).replace(/-/g, '_');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Look up a PWM spec by HAL pin number. Matrix pins (ESP32 LEDC) synthesize
|
|
35
|
+
* a spec on the fly: the channel is inert here — the emitted C++ addresses
|
|
36
|
+
* the pin only via its `tc-pwm<pin>` alias (the DT pwms cell carries the
|
|
37
|
+
* real channel, assigned by the overlay generator over the driven pins).
|
|
38
|
+
*/
|
|
39
|
+
export function findPwmSpec(chip: ZephyrChipDescriptor, pin: number): ZephyrPwmSpec | undefined {
|
|
40
|
+
const spec = chip.pwm?.specs.find((s) => s.pin === pin);
|
|
41
|
+
if (spec) return spec;
|
|
42
|
+
const m = chip.pwm?.matrix;
|
|
43
|
+
if (m && m.pins.includes(pin)) return { pin, controller: m.controller, channel: 0 };
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The C variable name emitted for a PWM channel's spec. */
|
|
48
|
+
function pwmVarName(spec: ZephyrPwmSpec): string {
|
|
49
|
+
return `__tc_pwm_${pwmDtAliasToken(spec)}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Emit the per-channel PWM spec declarations. One per spec in the chip
|
|
54
|
+
* descriptor that the PROGRAM ACTUALLY DRIVES (`usedPins`) — a spec for an
|
|
55
|
+
* untouched pin is unused code in the emitted TU (and would need a dead DT
|
|
56
|
+
* alias in the overlay). When `usedPins` is omitted (probe paths with no
|
|
57
|
+
* program), every spec is emitted. Called from shimLines when the program
|
|
58
|
+
* uses PWM.
|
|
59
|
+
*/
|
|
60
|
+
export function pwmInitLines(
|
|
61
|
+
chip: ZephyrChipDescriptor,
|
|
62
|
+
usedPins?: ReadonlySet<number>,
|
|
63
|
+
userSpecs?: readonly { pin: number; controller: string; channel: number }[],
|
|
64
|
+
): string[] {
|
|
65
|
+
const lines: string[] = ['// CUTTLEFISH_PWM_BEGIN'];
|
|
66
|
+
for (const spec of chip.pwm?.specs ?? []) {
|
|
67
|
+
if (usedPins && !usedPins.has(spec.pin)) continue;
|
|
68
|
+
lines.push(
|
|
69
|
+
`static const struct pwm_dt_spec ${pwmVarName(spec)} = PWM_DT_SPEC_GET(DT_ALIAS(${pwmDtAliasToken(spec)}));`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
// Inline-override pins (the escape hatch): the construction opts vouch for
|
|
73
|
+
// controller+channel on a pin the manifest does not map — the alias var
|
|
74
|
+
// the lowered calls reference (the DT node itself comes from the overlay
|
|
75
|
+
// regen's marker merge).
|
|
76
|
+
for (const spec of userSpecs ?? []) {
|
|
77
|
+
if (chip.pwm?.specs.some((s) => s.pin === spec.pin)) continue;
|
|
78
|
+
if (usedPins && !usedPins.has(spec.pin)) continue;
|
|
79
|
+
lines.push(
|
|
80
|
+
`static const struct pwm_dt_spec ${pwmVarName(spec)} = PWM_DT_SPEC_GET(DT_ALIAS(${pwmDtAliasToken(spec)}));`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
// Matrix pins (ESP32 LEDC): one alias per driven pin, ascending — the same
|
|
84
|
+
// order the overlay generator assigns channels in, though the C++ never
|
|
85
|
+
// needs the channel (the DT pwms cell carries it). An omitted usage set
|
|
86
|
+
// (probe paths) emits every matrix pin, mirroring the static behavior.
|
|
87
|
+
const m = chip.pwm?.matrix;
|
|
88
|
+
if (m) {
|
|
89
|
+
const pins = (usedPins ? [...usedPins].filter((p) => m.pins.includes(p)) : [...m.pins])
|
|
90
|
+
.sort((a, b) => a - b);
|
|
91
|
+
for (const pin of pins) {
|
|
92
|
+
const spec: ZephyrPwmSpec = { pin, controller: m.controller, channel: 0 };
|
|
93
|
+
lines.push(
|
|
94
|
+
`static const struct pwm_dt_spec ${pwmVarName(spec)} = PWM_DT_SPEC_GET(DT_ALIAS(${pwmDtAliasToken(spec)}));`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
lines.push('// CUTTLEFISH_PWM_END');
|
|
99
|
+
return lines;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Resolve a HAL pwm.* op to Zephyr C++.
|
|
104
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
105
|
+
*/
|
|
106
|
+
export function lowerPwm(
|
|
107
|
+
op: HALOpIR,
|
|
108
|
+
chip: ZephyrChipDescriptor,
|
|
109
|
+
): { code?: string; expression?: string } {
|
|
110
|
+
const o = op as any;
|
|
111
|
+
// Construction-time controller/channel overrides (hal/pwm-pin.ts opts):
|
|
112
|
+
// the user vouches for the routing. The spec synthesizes from the
|
|
113
|
+
// override (addressing rides the tc-pwm<pin> alias like a matrix pin) and
|
|
114
|
+
// a marker comment carries controller+channel to the overlay regen, which
|
|
115
|
+
// synthesizes the DT node — the transpiler cannot.
|
|
116
|
+
const hasOverride = (typeof o.controllerOverride === 'string' && o.controllerOverride !== '')
|
|
117
|
+
|| (typeof o.channelOverride === 'number' && o.channelOverride >= 0);
|
|
118
|
+
const spec = hasOverride
|
|
119
|
+
? {
|
|
120
|
+
pin: o.pin as number,
|
|
121
|
+
controller: (o.controllerOverride as string | undefined) ?? 'pwm0',
|
|
122
|
+
channel: (o.channelOverride as number | undefined) ?? 0,
|
|
123
|
+
}
|
|
124
|
+
: findPwmSpec(chip, o.pin);
|
|
125
|
+
if (!spec) {
|
|
126
|
+
// Probe / unlisted pin: return a comment so the resolver reports non-
|
|
127
|
+
// undefined (the manifest validator's probe sends pin:0 with no spec).
|
|
128
|
+
// A real program pins the descriptor's pwm.specs entry.
|
|
129
|
+
return { code: `/* pwm on pin ${o.pin}: no PWM spec in chip descriptor */` };
|
|
130
|
+
}
|
|
131
|
+
const v = pwmVarName(spec);
|
|
132
|
+
// The overlay regen (toolchain) parses this into a synthesized pwm-leds
|
|
133
|
+
// spec: pin → controller/channel. Comment placement inside the block
|
|
134
|
+
// braces is legal C.
|
|
135
|
+
const marker = hasOverride
|
|
136
|
+
? `/* cuttlefish-user-facts: pwm pin=${spec.pin} controller=${spec.controller} channel=${spec.channel} */ `
|
|
137
|
+
: '';
|
|
138
|
+
|
|
139
|
+
switch (op.operation) {
|
|
140
|
+
// ── Thin PWM (hal/pwm-pin.ts) — ns-true verbs ──────────────────────────
|
|
141
|
+
// Zephyr 4.4 has pwm_set_dt (period + pulse) and pwm_set_pulse_dt (pulse
|
|
142
|
+
// only) — no period-only setter. The construction period is established
|
|
143
|
+
// once via pwm_set_dt(period, pulse 0 = line idle), then every set is one
|
|
144
|
+
// pwm_set_pulse_dt. No 0–255 scaling anywhere.
|
|
145
|
+
case 'pwm.set_pulse': {
|
|
146
|
+
return {
|
|
147
|
+
code: `{ ${marker}static bool __tc_pwm_p${o.pin}_prd = false; if (!__tc_pwm_p${o.pin}_prd) { (void)pwm_set_dt(&${v}, ${o.periodNs}, 0); __tc_pwm_p${o.pin}_prd = true; } (void)pwm_set_pulse_dt(&${v}, ${o.pulseNs}); }`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
case 'pwm.set_duty': {
|
|
151
|
+
// duty is 0.0–1.0; pulse = duty × the construction period.
|
|
152
|
+
return {
|
|
153
|
+
code: `{ ${marker}static bool __tc_pwm_p${o.pin}_prd = false; if (!__tc_pwm_p${o.pin}_prd) { (void)pwm_set_dt(&${v}, ${o.periodNs}, 0); __tc_pwm_p${o.pin}_prd = true; } (void)pwm_set_pulse_dt(&${v}, static_cast<uint32_t>(static_cast<double>(${o.duty}) * static_cast<double>(${o.periodNs}))); }`,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
case 'pwm.set_period': {
|
|
157
|
+
// No period-only API: pwm_set_dt applies the new period and resets the
|
|
158
|
+
// pulse to idle — follow with setPulse/setDuty to drive the line.
|
|
159
|
+
return { code: `${marker}(void)pwm_set_dt(&${v}, ${o.periodNs}, 0);` };
|
|
160
|
+
}
|
|
161
|
+
default:
|
|
162
|
+
throw new Error(
|
|
163
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
164
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
package/src/lowering/random.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// the configured entropy source (the nRF52840 hardware RNG when
|
|
6
6
|
// CONFIG_HARDWARE_DEVICE_RANDOM_GENERATOR is selected, or the default test/
|
|
7
7
|
// xoroshiro generator otherwise). It is seeded automatically at boot from the
|
|
8
|
-
// entropy driver, so
|
|
8
|
+
// entropy driver, so there is no implicit seeding step.
|
|
9
9
|
//
|
|
10
10
|
// The HAL random surface is the Arduino-core model:
|
|
11
11
|
// random.int() → a non-negative 31-bit integer [0, 2^31 - 1]
|
|
@@ -73,7 +73,7 @@ export function randomInitLines(): string[] {
|
|
|
73
73
|
`}`,
|
|
74
74
|
``,
|
|
75
75
|
`// Re-seed the PRNG. After this call the sequence is deterministic from`,
|
|
76
|
-
`// \`seed\`, matching
|
|
76
|
+
`// \`seed\`, matching the platform's randomSeed. A literal zero seed is accepted and`,
|
|
77
77
|
`// remapped to the same odd constant (xorshift32 cannot start from 0).`,
|
|
78
78
|
`static inline void __tc_rand_seed(uint32_t seed) {`,
|
|
79
79
|
` __tc_rand_state = (seed == 0U) ? 0x9E3779B9U : seed;`,
|
|
@@ -87,7 +87,7 @@ export function randomInitLines(): string[] {
|
|
|
87
87
|
`}`,
|
|
88
88
|
``,
|
|
89
89
|
`// Half-open range [min, max-1]. Implements the HAL contract directly rather`,
|
|
90
|
-
`// than calling
|
|
90
|
+
`// than calling the platform random(min, max): the modulus rejection-free form`,
|
|
91
91
|
`// avoids the modulo bias a naive (rand % (max-min)) introduces. max > min`,
|
|
92
92
|
`// is assumed (the HAL validates this at the source level).`,
|
|
93
93
|
`static inline int32_t __tc_rand_range(int32_t min, int32_t max) {`,
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Sensor lowering — Zephyr's uniform sensor API over the generated catalog
|
|
3
|
+
//
|
|
4
|
+
// One code shape for every part in @typecad/hal's sensor catalog: the op's
|
|
5
|
+
// part token resolves to the DT compatible, the bus string to the controller
|
|
6
|
+
// index, and the address to the I2C reg. The names are derived identically
|
|
7
|
+
// here (device handles), in strategy.ts state blocks, and in the overlay
|
|
8
|
+
// scanner (dt-config/overlay.ts + toolchain/index.ts) — the tc-pwm<pin>
|
|
9
|
+
// discipline: both sides derive from the same facts, so they cannot drift.
|
|
10
|
+
//
|
|
11
|
+
// Kconfig: nothing per-part. The in-tree driver Kconfigs are `default y` on
|
|
12
|
+
// DT_HAS_<COMPAT>_ENABLED, so the overlay's child node IS the enable switch;
|
|
13
|
+
// CONFIG_SENSOR (the umbrella under `if SENSOR`) is usage-gated in
|
|
14
|
+
// dt-config/kconfig.ts off the lowered `sensor_` tokens.
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
|
|
17
|
+
import { SENSOR_PART_INFO } from '@typecad/hal';
|
|
18
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
19
|
+
import { parseControllerIndex } from './util.js';
|
|
20
|
+
|
|
21
|
+
/** Strip the 'SENSOR.' property-access prefix from a part token arg. */
|
|
22
|
+
export function sensorPartKey(part: string): string {
|
|
23
|
+
return part.replace(/^SENSOR\./, '');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Strip the 'CHAN.' property-access prefix from a channel arg. */
|
|
27
|
+
export function sensorChanName(chan: string): string {
|
|
28
|
+
return chan.replace(/^CHAN\./, '');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** All names a constructed sensor is known by, derived from the op facts. */
|
|
32
|
+
export interface SensorNames {
|
|
33
|
+
/** DT nodelabel of the child node the overlay emits
|
|
34
|
+
* (tc_<part>_i2c<N>_0x<addr> / tc_<part>_spi<N>_cs<pin>). */
|
|
35
|
+
dtLabel: string;
|
|
36
|
+
/** C device-handle variable (__tc_sensor_<stem>_dev). */
|
|
37
|
+
devVar: string;
|
|
38
|
+
/** C sensor_value scratch variable (__tc_sensor_<stem>_val). */
|
|
39
|
+
valVar: string;
|
|
40
|
+
/** The controller index the bus string carries. */
|
|
41
|
+
busIndex: number;
|
|
42
|
+
/** The bus port: I2C address or SPI CS pin. */
|
|
43
|
+
port: number;
|
|
44
|
+
/** 'i2c' | 'spi'. */
|
|
45
|
+
busKind: 'i2c' | 'spi';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Derive a sensor's DT/C++ names. The scanner regexes the emitted __tc_
|
|
49
|
+
* prefix form, so the part group must stay [a-z0-9_]+ and greedy. */
|
|
50
|
+
export function sensorNames(part: string, bus: string, port: number | string, busKind: string = 'i2c'): SensorNames {
|
|
51
|
+
const partKey = sensorPartKey(String(part));
|
|
52
|
+
const busIndex = parseControllerIndex(typeof bus === 'string' ? bus : String(bus));
|
|
53
|
+
const portNum = typeof port === 'number' ? port : parseInt(String(port));
|
|
54
|
+
const stem = busKind === 'spi'
|
|
55
|
+
? `${partKey}_spi${busIndex}_cs${portNum}`
|
|
56
|
+
: `${partKey}_i2c${busIndex}_0x${portNum.toString(16)}`;
|
|
57
|
+
return {
|
|
58
|
+
dtLabel: `tc_${stem}`,
|
|
59
|
+
devVar: `__tc_sensor_${stem}_dev`,
|
|
60
|
+
valVar: `__tc_sensor_${stem}_val`,
|
|
61
|
+
busIndex,
|
|
62
|
+
port: portNum,
|
|
63
|
+
busKind: busKind === 'spi' ? 'spi' : 'i2c',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Resolve the part token against the generated catalog, validating the bus
|
|
69
|
+
* kind and (when the driver scan knows them) the channel. Throws a build-time
|
|
70
|
+
* error with the Zephyr-facing name — the same words the user would meet in
|
|
71
|
+
* Zephyr docs, checked before west ever runs.
|
|
72
|
+
*/
|
|
73
|
+
/** @internal */
|
|
74
|
+
function requirePartInfo(partKey: string) {
|
|
75
|
+
const info = SENSOR_PART_INFO[partKey];
|
|
76
|
+
if (!info) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
`Sensor part '${partKey}' is not in the Zephyr sensor catalog (SENSOR in @typecad/hal). ` +
|
|
79
|
+
`Check the token against the catalog — it is the compatible with , and - replaced by _.`,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
return info;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Validate the op's bus kind against the part's bindings. */
|
|
86
|
+
function requireBusKind(partKey: string, info: ReturnType<typeof requirePartInfo>, busKind: string) {
|
|
87
|
+
if (!info.buses.includes(busKind)) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Sensor part '${partKey}' (${info.compatible}) does not bind on ${busKind.toUpperCase()} — ` +
|
|
90
|
+
`its bindings are ${info.buses.join('/').toUpperCase()}.`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Emit the per-sensor state block (device handle + sensor_value scratch).
|
|
97
|
+
* Called from shimLines for each distinct sensor the program's ops reference.
|
|
98
|
+
*/
|
|
99
|
+
export function sensorStateLines(part: string, bus: string, port: number | string, busKind: string = 'i2c', spiHz: number | string = 0, spiMode: number | string = 0, alertPin: number | string = -1): string[] {
|
|
100
|
+
const partKey = sensorPartKey(String(part));
|
|
101
|
+
requireBusKind(partKey, requirePartInfo(partKey), busKind);
|
|
102
|
+
const n = sensorNames(part, bus, port, busKind);
|
|
103
|
+
// The config comment carries construction facts (SPI clock, mode, alert
|
|
104
|
+
// GPIO) to the overlay scanner — they shape the DT node, not the C++.
|
|
105
|
+
const cfg = `// tc-sensor-cfg: ${n.dtLabel} hz=${Number(spiHz)} mode=${Number(spiMode)} alert=${Number(alertPin)}`;
|
|
106
|
+
return [
|
|
107
|
+
'// CUTTLEFISH_SENSOR_BEGIN',
|
|
108
|
+
`static const struct device* ${n.devVar} = DEVICE_DT_GET(DT_NODELABEL(${n.dtLabel}));`,
|
|
109
|
+
`static struct sensor_value ${n.valVar};`,
|
|
110
|
+
cfg,
|
|
111
|
+
'// CUTTLEFISH_SENSOR_END',
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Resolve a HAL sensor.* op to Zephyr C++.
|
|
117
|
+
* Returns `{ code }` for fetch (statement), `{ expression }` for get (value).
|
|
118
|
+
*/
|
|
119
|
+
export function lowerSensor(op: HALOpIR): { code?: string; expression?: string } {
|
|
120
|
+
const o = op as any;
|
|
121
|
+
const partKey = sensorPartKey(String(o.part));
|
|
122
|
+
const info = requirePartInfo(partKey);
|
|
123
|
+
requireBusKind(partKey, info, String(o.busKind ?? 'i2c'));
|
|
124
|
+
const n = sensorNames(o.part, o.bus, o.port ?? o.address, String(o.busKind ?? 'i2c'));
|
|
125
|
+
|
|
126
|
+
switch (op.operation) {
|
|
127
|
+
case 'sensor.fetch':
|
|
128
|
+
// sensor_sample_fetch. The leading (void) keeps the value scratch
|
|
129
|
+
// referenced under Zephyr's -Werror when the program fetches but never
|
|
130
|
+
// reads a channel (the state block is emitted per referenced sensor).
|
|
131
|
+
return {
|
|
132
|
+
code: `(void)${n.valVar}; sensor_sample_fetch(${n.devVar});`,
|
|
133
|
+
};
|
|
134
|
+
case 'sensor.get': {
|
|
135
|
+
const chan = sensorChanName(String(o.chan));
|
|
136
|
+
if (info.channels.length > 0 && !info.channels.includes(chan)) {
|
|
137
|
+
throw new Error(
|
|
138
|
+
`Sensor part '${partKey}' (${info.compatible}) does not serve channel '${chan}' — ` +
|
|
139
|
+
`its driver serves: ${info.channels.join(', ')}.`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
// sensor_value is val1 + val2 * 1e-6; evaluate once per read.
|
|
143
|
+
return {
|
|
144
|
+
expression:
|
|
145
|
+
`(sensor_channel_get(${n.devVar}, SENSOR_CHAN_${chan}, &${n.valVar}), ` +
|
|
146
|
+
`static_cast<double>(${n.valVar}.val1) + static_cast<double>(${n.valVar}.val2) / 1000000.0)`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
default:
|
|
150
|
+
throw new Error(
|
|
151
|
+
`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
152
|
+
`Open an issue or use rawCpp() to emit it manually.`,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
}
|