@typecad/framework-zephyr 1.0.0-alpha.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/async/timer-polyfill.d.ts +10 -0
- package/dist/async/timer-polyfill.js +95 -0
- package/dist/chips/controllers.d.ts +21 -0
- package/dist/chips/controllers.js +66 -0
- package/dist/chips/esp32.d.ts +2 -0
- package/dist/chips/esp32.js +59 -0
- package/dist/chips/esp32s3.d.ts +2 -0
- package/dist/chips/esp32s3.js +54 -0
- package/dist/chips/index.d.ts +15 -0
- package/dist/chips/index.js +45 -0
- package/dist/chips/resolve.d.ts +9 -0
- package/dist/chips/resolve.js +121 -0
- package/dist/chips/types.d.ts +154 -0
- package/dist/chips/types.js +14 -0
- package/dist/chips/xiao-ble.d.ts +2 -0
- package/dist/chips/xiao-ble.js +61 -0
- package/dist/debug-codegen.d.ts +33 -0
- package/dist/debug-codegen.js +162 -0
- package/dist/display/gfx.d.ts +17 -0
- package/dist/display/gfx.js +171 -0
- package/dist/display/index.d.ts +20 -0
- package/dist/display/index.js +53 -0
- package/dist/display/profiles.d.ts +25 -0
- package/dist/display/profiles.js +41 -0
- package/dist/display/touch-adapter.d.ts +9 -0
- package/dist/display/touch-adapter.js +95 -0
- package/dist/display/ui-adapter.d.ts +21 -0
- package/dist/display/ui-adapter.js +534 -0
- package/dist/dt-config/kconfig.d.ts +27 -0
- package/dist/dt-config/kconfig.js +283 -0
- package/dist/dt-config/overlay.d.ts +35 -0
- package/dist/dt-config/overlay.js +246 -0
- package/dist/framework.manifest.d.ts +98 -0
- package/dist/framework.manifest.js +525 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +12 -0
- package/dist/lowering/adc.d.ts +19 -0
- package/dist/lowering/adc.js +76 -0
- package/dist/lowering/ble.d.ts +20 -0
- package/dist/lowering/ble.js +419 -0
- package/dist/lowering/board.d.ts +9 -0
- package/dist/lowering/board.js +33 -0
- package/dist/lowering/gpio.d.ts +12 -0
- package/dist/lowering/gpio.js +123 -0
- package/dist/lowering/http.d.ts +23 -0
- package/dist/lowering/http.js +482 -0
- package/dist/lowering/i2c.d.ts +15 -0
- package/dist/lowering/i2c.js +114 -0
- package/dist/lowering/index.d.ts +29 -0
- package/dist/lowering/index.js +93 -0
- package/dist/lowering/interrupts.d.ts +21 -0
- package/dist/lowering/interrupts.js +91 -0
- package/dist/lowering/mqtt.d.ts +19 -0
- package/dist/lowering/mqtt.js +366 -0
- package/dist/lowering/power.d.ts +9 -0
- package/dist/lowering/power.js +64 -0
- package/dist/lowering/preferences.d.ts +23 -0
- package/dist/lowering/preferences.js +345 -0
- package/dist/lowering/pulse.d.ts +7 -0
- package/dist/lowering/pulse.js +82 -0
- package/dist/lowering/pwm.d.ts +15 -0
- package/dist/lowering/pwm.js +59 -0
- package/dist/lowering/random.d.ts +18 -0
- package/dist/lowering/random.js +129 -0
- package/dist/lowering/spi.d.ts +17 -0
- package/dist/lowering/spi.js +113 -0
- package/dist/lowering/timing.d.ts +9 -0
- package/dist/lowering/timing.js +63 -0
- package/dist/lowering/tone.d.ts +10 -0
- package/dist/lowering/tone.js +50 -0
- package/dist/lowering/uart.d.ts +15 -0
- package/dist/lowering/uart.js +102 -0
- package/dist/lowering/util.d.ts +4 -0
- package/dist/lowering/util.js +12 -0
- package/dist/lowering/wdt.d.ts +15 -0
- package/dist/lowering/wdt.js +80 -0
- package/dist/lowering/wifi.d.ts +21 -0
- package/dist/lowering/wifi.js +447 -0
- package/dist/lowering/worker-backing.d.ts +14 -0
- package/dist/lowering/worker-backing.js +79 -0
- package/dist/lowering/worker.d.ts +6 -0
- package/dist/lowering/worker.js +14 -0
- package/dist/strategy.d.ts +168 -0
- package/dist/strategy.js +1094 -0
- package/dist/toolchain/debug-config.d.ts +82 -0
- package/dist/toolchain/debug-config.js +359 -0
- package/dist/toolchain/index.d.ts +73 -0
- package/dist/toolchain/index.js +427 -0
- package/dist/toolchain/scaffold.d.ts +15 -0
- package/dist/toolchain/scaffold.js +196 -0
- package/dist/toolchain/west-discover.d.ts +40 -0
- package/dist/toolchain/west-discover.js +203 -0
- package/dist/toolchain/west-spawn.d.ts +39 -0
- package/dist/toolchain/west-spawn.js +117 -0
- package/package.json +82 -0
- package/src/async/timer-polyfill.ts +107 -0
- package/src/chips/controllers.ts +74 -0
- package/src/chips/esp32.ts +62 -0
- package/src/chips/esp32s3.ts +57 -0
- package/src/chips/index.ts +54 -0
- package/src/chips/resolve.ts +146 -0
- package/src/chips/types.ts +163 -0
- package/src/chips/xiao-ble.ts +64 -0
- package/src/debug-codegen.ts +207 -0
- package/src/display/gfx.ts +190 -0
- package/src/display/index.ts +70 -0
- package/src/display/profiles.ts +63 -0
- package/src/display/touch-adapter.ts +100 -0
- package/src/display/ui-adapter.ts +558 -0
- package/src/dt-config/kconfig.ts +308 -0
- package/src/dt-config/overlay.ts +293 -0
- package/src/framework.manifest.ts +545 -0
- package/src/index.ts +23 -0
- package/src/lowering/adc.ts +102 -0
- package/src/lowering/ble.ts +426 -0
- package/src/lowering/board.ts +38 -0
- package/src/lowering/gpio.ts +148 -0
- package/src/lowering/http.ts +488 -0
- package/src/lowering/i2c.ts +126 -0
- package/src/lowering/index.ts +86 -0
- package/src/lowering/interrupts.ts +114 -0
- package/src/lowering/mqtt.ts +371 -0
- package/src/lowering/power.ts +70 -0
- package/src/lowering/preferences.ts +354 -0
- package/src/lowering/pulse.ts +93 -0
- package/src/lowering/pwm.ts +74 -0
- package/src/lowering/random.ts +135 -0
- package/src/lowering/spi.ts +124 -0
- package/src/lowering/timing.ts +72 -0
- package/src/lowering/tone.ts +60 -0
- package/src/lowering/uart.ts +111 -0
- package/src/lowering/util.ts +12 -0
- package/src/lowering/wdt.ts +84 -0
- package/src/lowering/wifi.ts +452 -0
- package/src/lowering/worker-backing.ts +94 -0
- package/src/lowering/worker.ts +17 -0
- package/src/strategy.ts +1265 -0
- package/src/toolchain/debug-config.ts +399 -0
- package/src/toolchain/index.ts +459 -0
- package/src/toolchain/scaffold.ts +196 -0
- package/src/toolchain/west-discover.ts +233 -0
- package/src/toolchain/west-spawn.ts +141 -0
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Zephyr framework manifest
|
|
3
|
+
//
|
|
4
|
+
// Coverage reflects actual resolveHALOperation / lowerHalOp + resolveDisplayOp
|
|
5
|
+
// behavior. GPIO, PWM, ADC, I2C, SPI, UART, interrupts, tone, power, pulse,
|
|
6
|
+
// shift, WDT, BLE, timing, WiFi, HTTP/S, MQTT, board constants, and random
|
|
7
|
+
// are lowered; display is lowered via the generic <zephyr/drivers/display.h>
|
|
8
|
+
// GFX runtime. WiFi/HTTP/MQTT require an ESP32 target (nRF52840 has no radio).
|
|
9
|
+
// The manifest validator probes every declared op against the resolver: a
|
|
10
|
+
// 'supported' op must lower, an 'unsupported' op must return undefined.
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
import { defineFrameworkManifest, HAL_OPERATION_KINDS } from '@typecad/cuttlefish/api/shared';
|
|
13
|
+
/**
|
|
14
|
+
* Build an `{ opKind: 'unsupported' }` record for every op kind under a given
|
|
15
|
+
* category prefix. Keeps unsupported categories honest without hand-listing
|
|
16
|
+
* every op (the validator requires every op kind be declared, even as
|
|
17
|
+
* unsupported). Mirrors the discipline esp32 applies by hand-listing.
|
|
18
|
+
*/
|
|
19
|
+
function unsupportedOps(prefix) {
|
|
20
|
+
const out = {};
|
|
21
|
+
for (const kind of HAL_OPERATION_KINDS) {
|
|
22
|
+
if (kind.startsWith(prefix))
|
|
23
|
+
out[kind] = 'unsupported';
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
export default defineFrameworkManifest({
|
|
28
|
+
schemaVersion: 1,
|
|
29
|
+
frameworkId: 'zephyr',
|
|
30
|
+
packageName: '@typecad/framework-zephyr',
|
|
31
|
+
canonical: false,
|
|
32
|
+
displayName: 'Zephyr RTOS',
|
|
33
|
+
description: 'Native Zephyr framework targeting the Zephyr RTOS via west/CMake. ' +
|
|
34
|
+
'GPIO is lowered through devicetree specs (gpio_pin_*_dt).',
|
|
35
|
+
implementationMode: 'from-scratch',
|
|
36
|
+
entrypoint: {
|
|
37
|
+
entrypointFunctionName: 'setup',
|
|
38
|
+
requiresLoopFunction: true,
|
|
39
|
+
sourceExtension: 'cpp',
|
|
40
|
+
overrideBaseName: 'main',
|
|
41
|
+
outputSubdirectory: 'src',
|
|
42
|
+
generateHeaderFile: true,
|
|
43
|
+
customBridgeShim: 'main',
|
|
44
|
+
},
|
|
45
|
+
profile: {
|
|
46
|
+
// Informational list of supported board targets. The manifest validator
|
|
47
|
+
// never iterates this; chipForTarget (src/chips/index.ts) is the real
|
|
48
|
+
// resolver. ESP32-S3 + plain ESP32 added alongside the nRF52840 MVP target.
|
|
49
|
+
targets: ['xiao_ble', 'esp32s3_devkitc', 'esp32_devkitc'],
|
|
50
|
+
forcedIncludes: ['<zephyr/kernel.h>', '<zephyr/drivers/gpio.h>', '<cstdint>'],
|
|
51
|
+
symbolAliases: {},
|
|
52
|
+
},
|
|
53
|
+
hal: {
|
|
54
|
+
// ── Supported: GPIO (devicetree-spec bridge) ──────────────────────────
|
|
55
|
+
gpio: {
|
|
56
|
+
supported: true,
|
|
57
|
+
partialCoverage: false,
|
|
58
|
+
ops: {
|
|
59
|
+
'gpio.write': 'supported',
|
|
60
|
+
'gpio.read': 'supported',
|
|
61
|
+
'gpio.toggle': 'supported',
|
|
62
|
+
'gpio.set_mode': 'supported',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
// ── Supported: Timing (delay/millis/delay_us/micros/free_heap; timers via polyfill) ─
|
|
66
|
+
timing: {
|
|
67
|
+
supported: true,
|
|
68
|
+
partialCoverage: false,
|
|
69
|
+
ops: {
|
|
70
|
+
'timing.delay': 'supported', // → k_msleep(ms)
|
|
71
|
+
'timing.delay_microseconds': 'supported', // → k_busy_wait(us)
|
|
72
|
+
'timing.millis': 'supported', // → k_uptime_get_32()
|
|
73
|
+
'timing.micros': 'supported', // → k_cycle_get_32 + cycles/sec
|
|
74
|
+
'timing.free_heap': 'supported', // → 0 (no portable query; see lowering)
|
|
75
|
+
// Timer ops are POLYFILL_BACKED_OPS → timer_methods. The validator skips
|
|
76
|
+
// the resolver probe (these legitimately return polyfill-helper calls,
|
|
77
|
+
// not direct lowering) and requires the polyfill be in polyfills.emitted.
|
|
78
|
+
'timing.set_interval': 'polyfill',
|
|
79
|
+
'timing.set_timeout': 'polyfill',
|
|
80
|
+
'timing.clear_interval': 'polyfill',
|
|
81
|
+
'timing.clear_timeout': 'polyfill',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
// ── Supported: PWM (pwm_dt_spec via pwm-led0) ──────────────────────────
|
|
85
|
+
pwm: {
|
|
86
|
+
supported: true,
|
|
87
|
+
partialCoverage: false,
|
|
88
|
+
ops: {
|
|
89
|
+
'pwm.write': 'supported',
|
|
90
|
+
'pwm.get_frequency': 'supported',
|
|
91
|
+
'pwm.get_resolution': 'supported',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
// ── Supported: ADC (SAADC via adc_read + channel setup) ────────────────
|
|
95
|
+
adc: {
|
|
96
|
+
supported: true,
|
|
97
|
+
partialCoverage: false,
|
|
98
|
+
ops: {
|
|
99
|
+
'adc.read': 'supported',
|
|
100
|
+
'adc.get_resolution': 'supported',
|
|
101
|
+
'adc.set_reference': 'supported',
|
|
102
|
+
'adc.get_reference': 'supported',
|
|
103
|
+
'adc.read_voltage': 'supported',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
dac: {
|
|
107
|
+
supported: false,
|
|
108
|
+
unsupportedReason: 'No DAC lowering implemented in the framework (not applicable on nRF52840; ESP32 variants with DAC not yet wired).',
|
|
109
|
+
ops: { 'dac.write': 'unsupported' },
|
|
110
|
+
},
|
|
111
|
+
interrupts: {
|
|
112
|
+
supported: true,
|
|
113
|
+
partialCoverage: true,
|
|
114
|
+
unsupportedReason: undefined,
|
|
115
|
+
ops: {
|
|
116
|
+
'interrupt.attach': 'supported',
|
|
117
|
+
'interrupt.detach': 'supported',
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
tone: {
|
|
121
|
+
supported: true,
|
|
122
|
+
partialCoverage: true,
|
|
123
|
+
ops: {
|
|
124
|
+
'tone.play': 'supported', // PWM-based square wave (blocking for duration)
|
|
125
|
+
'tone.stop': 'supported',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
power: {
|
|
129
|
+
supported: true,
|
|
130
|
+
partialCoverage: true,
|
|
131
|
+
ops: {
|
|
132
|
+
'power.deep_sleep': 'supported', // k_sleep (deepest allowed state)
|
|
133
|
+
'power.light_sleep': 'supported', // pm_state_force SUSPEND_TO_IDLE
|
|
134
|
+
'power.set_cpu_frequency': 'supported', // comment (nRF clock API deferred)
|
|
135
|
+
'power.deep_sleep_pin': 'supported', // GPIO-interrupt wake + k_sleep
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
i2c: {
|
|
139
|
+
supported: true,
|
|
140
|
+
partialCoverage: false,
|
|
141
|
+
ops: {
|
|
142
|
+
'i2c.begin': 'supported', 'i2c.end': 'supported', 'i2c.set_clock': 'supported',
|
|
143
|
+
'i2c.begin_transmission': 'supported', 'i2c.write': 'supported',
|
|
144
|
+
'i2c.write_bytes': 'supported', 'i2c.write_buffer': 'supported',
|
|
145
|
+
'i2c.read_buffer': 'supported', 'i2c.end_transmission': 'supported',
|
|
146
|
+
'i2c.request_from': 'supported', 'i2c.available': 'supported', 'i2c.read': 'supported',
|
|
147
|
+
'i2c.recover': 'supported',
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
spi: {
|
|
151
|
+
supported: true,
|
|
152
|
+
partialCoverage: false,
|
|
153
|
+
ops: {
|
|
154
|
+
'spi.begin': 'supported', 'spi.end': 'supported', 'spi.transfer': 'supported',
|
|
155
|
+
'spi.begin_transaction': 'supported', 'spi.end_transaction': 'supported',
|
|
156
|
+
'spi.set_mode': 'supported', 'spi.set_bit_order': 'supported',
|
|
157
|
+
'spi.cs_low': 'supported', 'spi.cs_high': 'supported', 'spi.read_buffer': 'supported',
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
uart: {
|
|
161
|
+
supported: true,
|
|
162
|
+
partialCoverage: true,
|
|
163
|
+
ops: {
|
|
164
|
+
'uart.begin': 'supported', 'uart.end': 'supported', 'uart.print': 'supported',
|
|
165
|
+
'uart.println': 'supported', 'uart.printf': 'supported', 'uart.write': 'supported',
|
|
166
|
+
'uart.read': 'supported', 'uart.peek': 'supported', 'uart.available': 'supported',
|
|
167
|
+
'uart.flush': 'supported',
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
pulse: {
|
|
171
|
+
supported: true,
|
|
172
|
+
partialCoverage: true,
|
|
173
|
+
ops: { 'pulse.in': 'supported', 'pulse.in_long': 'supported' },
|
|
174
|
+
},
|
|
175
|
+
shift: {
|
|
176
|
+
supported: true,
|
|
177
|
+
partialCoverage: false,
|
|
178
|
+
ops: { 'shift.out': 'supported', 'shift.in': 'supported' },
|
|
179
|
+
},
|
|
180
|
+
board: {
|
|
181
|
+
// Board constant resolution. Board.definition.<path> /
|
|
182
|
+
// Pins.definition.<path> property accesses are folded by
|
|
183
|
+
// ZephyrStrategy.renderBoardDefinitionAccess against the loaded
|
|
184
|
+
// board/MCU constants — the same mechanism framework-arduino uses. The
|
|
185
|
+
// lone HAL op (board.resolve) is constant-folded at IR-build time
|
|
186
|
+
// (expression-to-ir.ts / hal-emitter.ts), so it only reaches the
|
|
187
|
+
// resolver as a dead-letter; 'probe-inconclusive' reflects that the
|
|
188
|
+
// minimal validator probe carries no path/board constants to resolve.
|
|
189
|
+
supported: true,
|
|
190
|
+
partialCoverage: false,
|
|
191
|
+
ops: { 'board.resolve': 'probe-inconclusive' },
|
|
192
|
+
},
|
|
193
|
+
wdt: {
|
|
194
|
+
supported: true,
|
|
195
|
+
partialCoverage: false,
|
|
196
|
+
ops: {
|
|
197
|
+
'wdt.enable': 'supported',
|
|
198
|
+
'wdt.reset': 'supported',
|
|
199
|
+
'wdt.disable': 'supported',
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
// ── Partial: WiFi (STA connect + scan + config via conn_mgr/net_mgmt) ────
|
|
203
|
+
// ESP32-S3 only — profileDiagnostics flags wifi usage on radioless chips.
|
|
204
|
+
// AP mode, credential persistence, static IP, and event callbacks deferred.
|
|
205
|
+
wifi: {
|
|
206
|
+
supported: true,
|
|
207
|
+
partialCoverage: true,
|
|
208
|
+
// Unsupported surface: AP client enumeration/IP/per-station-config have no
|
|
209
|
+
// driver hook; credentials need a custom settings-subsystem layer; static IP
|
|
210
|
+
// / auto-reconnect / tx-power aren't wifi-shaped or aren't exposed by the
|
|
211
|
+
// esp32 Zephyr driver. See per-op reasons.
|
|
212
|
+
unsupportedReason: 'AP client enumeration/IP/per-station config, credential persistence, static IP, auto-reconnect, and tx-power have no Zephyr lowering (no driver/Kconfig hook).',
|
|
213
|
+
ops: {
|
|
214
|
+
// Connection (8) — net_mgmt connect/disconnect + L4 connectivity state.
|
|
215
|
+
'wifi.connect': 'supported', 'wifi.connect_start': 'supported',
|
|
216
|
+
'wifi.disconnect': 'supported', 'wifi.status': 'supported',
|
|
217
|
+
'wifi.is_connected': 'supported', 'wifi.local_ip': 'supported',
|
|
218
|
+
'wifi.rssi': 'supported', 'wifi.mac': 'supported',
|
|
219
|
+
// Waits (2) — block on the L4 connected flag (k_msleep poll).
|
|
220
|
+
'wifi.wait_connected': 'supported', 'wifi.wait_disconnected': 'supported',
|
|
221
|
+
// Scan (8) — net_mgmt NET_REQUEST_WIFI_SCAN + result pool.
|
|
222
|
+
'wifi.scan': 'supported', 'wifi.scan_start': 'supported',
|
|
223
|
+
'wifi.scan_done': 'supported', 'wifi.scan_count': 'supported',
|
|
224
|
+
'wifi.scan_ssid': 'supported', 'wifi.scan_rssi': 'supported',
|
|
225
|
+
'wifi.scan_encryption': 'supported', 'wifi.scan_channel': 'supported',
|
|
226
|
+
// AP mode (2 of 7) — esp32 driver wires ap_enable/ap_disable. Only
|
|
227
|
+
// ssid/password/channel are honored; the rest of the AP surface has no
|
|
228
|
+
// driver hook (config_params isn't wired, max_clients hardcodes 5).
|
|
229
|
+
'wifi.ap_start': 'supported', 'wifi.ap_stop': 'supported',
|
|
230
|
+
// Config (2) — hostname (best-effort no-op) + power save (real net_mgmt).
|
|
231
|
+
'wifi.set_hostname': 'supported', 'wifi.set_power_save': 'supported',
|
|
232
|
+
// on_event: 'disconnect' (NET_EVENT_L4_DISCONNECTED) + 'connect'
|
|
233
|
+
// (NET_EVENT_IPV4_ADDR_ADD) are lowered.
|
|
234
|
+
'wifi.on_event': 'supported',
|
|
235
|
+
// ── Genuinely unsupported (no Zephyr/driver hook) ───────────────────
|
|
236
|
+
// ap_client_count: no API to enumerate connected AP stations.
|
|
237
|
+
// ap_ip: set via net_if, not wifi net_mgmt.
|
|
238
|
+
// ap_set_channel: channel set at ap_start; driver doesn't wire ap_config_params.
|
|
239
|
+
// ap_set_hidden: esp32 ap_enable config has no ssid_hidden field.
|
|
240
|
+
// ap_set_max_clients: driver hardcodes max_connection to 5; config_params unwired.
|
|
241
|
+
// save_credentials/connect_saved/clear_credentials: no wifi-credentials API in
|
|
242
|
+
// Zephyr (would need a custom settings-subsystem layer).
|
|
243
|
+
// set_static_ip: a net_if operation, not a wifi net_mgmt request.
|
|
244
|
+
// set_auto_reconnect: esp32 driver doesn't expose esp_wifi_set_auto_connect.
|
|
245
|
+
// set_tx_power: driver owns the radio; the PHY ceiling isn't a Zephyr Kconfig (zephyr#45580).
|
|
246
|
+
'wifi.ap_client_count': 'unsupported',
|
|
247
|
+
'wifi.ap_ip': 'unsupported',
|
|
248
|
+
'wifi.ap_set_channel': 'unsupported',
|
|
249
|
+
'wifi.ap_set_hidden': 'unsupported',
|
|
250
|
+
'wifi.ap_set_max_clients': 'unsupported',
|
|
251
|
+
'wifi.save_credentials': 'unsupported', 'wifi.connect_saved': 'unsupported',
|
|
252
|
+
'wifi.clear_credentials': 'unsupported',
|
|
253
|
+
'wifi.set_static_ip': 'unsupported',
|
|
254
|
+
'wifi.set_auto_reconnect': 'unsupported',
|
|
255
|
+
'wifi.set_tx_power': 'unsupported',
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
http: {
|
|
259
|
+
supported: true,
|
|
260
|
+
partialCoverage: false,
|
|
261
|
+
// HTTP/S client over Zephyr BSD sockets + http_client_req (TLS via
|
|
262
|
+
// mbedTLS / NET_SOCKETS_SOCKOPT_TLS). The __tc_http shim owns url parse,
|
|
263
|
+
// DNS (getaddrinfo), socket/TLS connect, and body accumulation. Requires
|
|
264
|
+
// a networked target (ESP32 WiFi); profileDiagnostics flags usage on a
|
|
265
|
+
// radioless chip as 'zephyr-http-unavailable-on-target'.
|
|
266
|
+
ops: {
|
|
267
|
+
'http.begin': 'supported', 'http.reset': 'supported',
|
|
268
|
+
'http.set_header': 'supported', 'http.set_timeout': 'supported',
|
|
269
|
+
'http.set_max_body': 'supported', 'http.set_body': 'supported',
|
|
270
|
+
'http.set_insecure': 'supported', 'http.set_ca_cert': 'supported',
|
|
271
|
+
'http.send': 'supported', 'http.send_start': 'supported',
|
|
272
|
+
'http.done': 'supported', 'http.status': 'supported',
|
|
273
|
+
'http.ok': 'supported', 'http.body': 'supported',
|
|
274
|
+
'http.content_length': 'supported', 'http.response_header': 'supported',
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
display: {
|
|
278
|
+
supported: true,
|
|
279
|
+
partialCoverage: false,
|
|
280
|
+
unsupportedReason: undefined,
|
|
281
|
+
drivers: ['ili9341-zephyr', 'st7796-zephyr'],
|
|
282
|
+
colorFormat: 'rgb565',
|
|
283
|
+
ops: {
|
|
284
|
+
'display.init': 'supported',
|
|
285
|
+
'display.fill_rect': 'supported',
|
|
286
|
+
'display.draw_text': 'supported',
|
|
287
|
+
'display.draw_rect': 'supported',
|
|
288
|
+
'display.flush': 'supported',
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
// ── Supported: BLE (NimBLE GATT peripheral via runtime service register) ──
|
|
292
|
+
ble: {
|
|
293
|
+
supported: true,
|
|
294
|
+
partialCoverage: true,
|
|
295
|
+
ops: Object.fromEntries(HAL_OPERATION_KINDS.filter((k) => k.startsWith('ble.')).map((k) => [k, 'supported'])),
|
|
296
|
+
},
|
|
297
|
+
// ── Supported: Worker offload (k_work system workqueue + k_sem) ──────────
|
|
298
|
+
// worker.* is lowered via lowerWorkerOp against the shared __tc_worker
|
|
299
|
+
// contract; the Zephyr backing (worker-backing.ts) supplies k_work + k_sem.
|
|
300
|
+
worker: {
|
|
301
|
+
supported: true,
|
|
302
|
+
partialCoverage: false,
|
|
303
|
+
ops: { 'worker.submit': 'supported', 'worker.done': 'supported' },
|
|
304
|
+
},
|
|
305
|
+
// ── Honestly unsupported extended categories ─────────────────────────────
|
|
306
|
+
// These have op-kinds in HAL_OPERATION_KINDS but no Zephyr lowering. Each
|
|
307
|
+
// is declared unsupported (with a reason) so the coverage matrix is uniform
|
|
308
|
+
// and the resolver's `return undefined` for these prefixes is honest. The
|
|
309
|
+
// catchall schema (HalCoverageSchema) validates any declared extended
|
|
310
|
+
// category; declaring them keeps the manifest a complete coverage record.
|
|
311
|
+
rmt: {
|
|
312
|
+
supported: false,
|
|
313
|
+
unsupportedReason: 'RMT (ESP32 infrared/transaction peripheral) has no Zephyr lowering.',
|
|
314
|
+
partialCoverage: false,
|
|
315
|
+
ops: unsupportedOps('rmt.'),
|
|
316
|
+
},
|
|
317
|
+
snprintf: {
|
|
318
|
+
supported: false,
|
|
319
|
+
unsupportedReason: 'snprintf.emit is a raw escape hatch; the Zephyr resolver returns undefined (use rawCpp()).',
|
|
320
|
+
partialCoverage: false,
|
|
321
|
+
ops: { 'snprintf.emit': 'unsupported' },
|
|
322
|
+
},
|
|
323
|
+
preferences: {
|
|
324
|
+
// ZMS-backed Zephyr settings. The HAL ESP32-NVS session model (begin/end
|
|
325
|
+
// + typed put/get) is modeled on top of Zephyr's flat settings key-space:
|
|
326
|
+
// begin(ns) records a "tc/<ns>/" prefix; put/get operate on an in-RAM
|
|
327
|
+
// cache populated once at boot by settings_load()'s h_set callback;
|
|
328
|
+
// writes mirror to flash via settings_save_one/settings_delete. The ZMS
|
|
329
|
+
// backend auto-locates the storage_partition fixed-partition (or the
|
|
330
|
+
// /chosen zephyr,settings-partition node — see dt-config/overlay.ts).
|
|
331
|
+
// begin/end are no-ops beyond prefix bookkeeping: Zephyr settings has no
|
|
332
|
+
// session/namespace, but keeping the ops preserves portability with the
|
|
333
|
+
// ESP32 NVS model and leaves a hook for a future session-needing backend.
|
|
334
|
+
supported: true,
|
|
335
|
+
partialCoverage: false,
|
|
336
|
+
ops: {
|
|
337
|
+
'preferences.begin': 'supported', 'preferences.end': 'supported',
|
|
338
|
+
'preferences.clear': 'supported', 'preferences.remove': 'supported',
|
|
339
|
+
'preferences.put_int': 'supported', 'preferences.get_int': 'supported',
|
|
340
|
+
'preferences.put_uint': 'supported', 'preferences.get_uint': 'supported',
|
|
341
|
+
'preferences.put_bool': 'supported', 'preferences.get_bool': 'supported',
|
|
342
|
+
'preferences.put_float': 'supported', 'preferences.get_float': 'supported',
|
|
343
|
+
'preferences.put_string': 'supported', 'preferences.get_string': 'supported',
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
random: {
|
|
347
|
+
// <zephyr/random/random.h> sys_rand_get seeds a userspace xorshift32
|
|
348
|
+
// PRNG (__tc_rand_*); random.seed re-seeds it deterministically (matching
|
|
349
|
+
// Arduino randomSeed). random.int → [0, 2^31-1], random.range → [min,max-1].
|
|
350
|
+
supported: true,
|
|
351
|
+
partialCoverage: false,
|
|
352
|
+
ops: {
|
|
353
|
+
'random.int': 'supported',
|
|
354
|
+
'random.range': 'supported',
|
|
355
|
+
'random.seed': 'supported',
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
fs: {
|
|
359
|
+
supported: false,
|
|
360
|
+
unsupportedReason: 'No filesystem lowering on Zephyr (Zephyr has its own FS API; not wired).',
|
|
361
|
+
partialCoverage: false,
|
|
362
|
+
ops: unsupportedOps('fs.'),
|
|
363
|
+
},
|
|
364
|
+
mdns: {
|
|
365
|
+
supported: false,
|
|
366
|
+
unsupportedReason: 'No mDNS lowering on Zephyr (requires networking stack).',
|
|
367
|
+
partialCoverage: false,
|
|
368
|
+
ops: unsupportedOps('mdns.'),
|
|
369
|
+
},
|
|
370
|
+
mqtt: {
|
|
371
|
+
supported: true,
|
|
372
|
+
partialCoverage: false,
|
|
373
|
+
// MQTT 3.1.1 client over Zephyr <zephyr/net/mqtt.h> (mqtts:// TLS via
|
|
374
|
+
// MQTT_TRANSPORT_SECURE + the shared mbedTLS matrix, encryption only — the
|
|
375
|
+
// HAL surface has no CA-pinning op, so peer verify is NONE). The __tc_mqtt
|
|
376
|
+
// shim resolves the broker, runs the mqtt_input/mqtt_live poll loop on a
|
|
377
|
+
// background k_thread, and dispatches incoming PUBLISHes to the user's
|
|
378
|
+
// onMessage callback. Requires a networked target (ESP32 WiFi);
|
|
379
|
+
// profileDiagnostics flags usage on a radioless chip.
|
|
380
|
+
ops: {
|
|
381
|
+
'mqtt.connect': 'supported', 'mqtt.on_message': 'supported',
|
|
382
|
+
'mqtt.subscribe': 'supported', 'mqtt.publish': 'supported',
|
|
383
|
+
'mqtt.connected': 'supported', 'mqtt.disconnect': 'supported',
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
ota: {
|
|
387
|
+
supported: false,
|
|
388
|
+
unsupportedReason: 'No OTA lowering on Zephyr (Zephyr has MCUmgr; not wired).',
|
|
389
|
+
partialCoverage: false,
|
|
390
|
+
ops: unsupportedOps('ota.'),
|
|
391
|
+
},
|
|
392
|
+
temp: {
|
|
393
|
+
supported: false,
|
|
394
|
+
unsupportedReason: 'No on-chip temperature lowering on Zephyr (nRF52840 TEMP peripheral; not wired).',
|
|
395
|
+
partialCoverage: false,
|
|
396
|
+
ops: { 'temp.read': 'unsupported' },
|
|
397
|
+
},
|
|
398
|
+
hwtimer: {
|
|
399
|
+
supported: false,
|
|
400
|
+
unsupportedReason: 'No hardware-timer lowering on Zephyr (timers are handled via the k_timer polyfill, not hwtimer.*).',
|
|
401
|
+
partialCoverage: false,
|
|
402
|
+
ops: unsupportedOps('hwtimer.'),
|
|
403
|
+
},
|
|
404
|
+
capacitive: {
|
|
405
|
+
// FT6336U capacitive touch is handled via the strategy-owned touch adapter
|
|
406
|
+
// (src/display/touch-adapter.ts → touch_init/touch_isTouched/touch_readRaw),
|
|
407
|
+
// NOT via a HAL op lowering. The manifest marks it unsupported here (no
|
|
408
|
+
// resolveHALOperation path for capacitive.read); the touch adapter provides
|
|
409
|
+
// the integration. partialCoverage reflects that it works on targets with
|
|
410
|
+
// the FT6336U DT node (ESP32), not on the bare nRF52840.
|
|
411
|
+
supported: false,
|
|
412
|
+
unsupportedReason: 'Capacitive touch is handled via the strategy touch adapter (FT6336U I2C), not a HAL op. Requires the ft6336u DT node.',
|
|
413
|
+
partialCoverage: true,
|
|
414
|
+
ops: { 'capacitive.read': 'unsupported' },
|
|
415
|
+
},
|
|
416
|
+
i2s: {
|
|
417
|
+
supported: false,
|
|
418
|
+
unsupportedReason: 'No I2S / digital audio lowering on Zephyr.',
|
|
419
|
+
partialCoverage: false,
|
|
420
|
+
ops: unsupportedOps('i2s.'),
|
|
421
|
+
},
|
|
422
|
+
twai: {
|
|
423
|
+
supported: false,
|
|
424
|
+
unsupportedReason: 'No CAN / TWAI lowering on Zephyr (Zephyr CAN driver not wired).',
|
|
425
|
+
partialCoverage: false,
|
|
426
|
+
ops: unsupportedOps('twai.'),
|
|
427
|
+
},
|
|
428
|
+
usb: {
|
|
429
|
+
supported: false,
|
|
430
|
+
unsupportedReason: 'No USB OTG / USB-Serial lowering on Zephyr (Zephyr USB device stack not wired).',
|
|
431
|
+
partialCoverage: false,
|
|
432
|
+
ops: unsupportedOps('usb.'),
|
|
433
|
+
},
|
|
434
|
+
eth: {
|
|
435
|
+
supported: false,
|
|
436
|
+
unsupportedReason: 'No Ethernet MAC lowering on Zephyr.',
|
|
437
|
+
partialCoverage: false,
|
|
438
|
+
ops: unsupportedOps('eth.'),
|
|
439
|
+
},
|
|
440
|
+
espnow: {
|
|
441
|
+
supported: false,
|
|
442
|
+
unsupportedReason: 'ESP-NOW is an ESP-exclusive wireless protocol; no Zephyr lowering.',
|
|
443
|
+
partialCoverage: false,
|
|
444
|
+
ops: unsupportedOps('espnow.'),
|
|
445
|
+
},
|
|
446
|
+
crypto: {
|
|
447
|
+
supported: false,
|
|
448
|
+
unsupportedReason: 'No hardware crypto (AES/SHA/HMAC) lowering on Zephyr.',
|
|
449
|
+
partialCoverage: false,
|
|
450
|
+
ops: unsupportedOps('crypto.'),
|
|
451
|
+
},
|
|
452
|
+
pcnt: {
|
|
453
|
+
supported: false,
|
|
454
|
+
unsupportedReason: 'No pulse-counter (PCNT) lowering on Zephyr.',
|
|
455
|
+
partialCoverage: false,
|
|
456
|
+
ops: unsupportedOps('pcnt.'),
|
|
457
|
+
},
|
|
458
|
+
mcpwm: {
|
|
459
|
+
supported: false,
|
|
460
|
+
unsupportedReason: 'No motor-control PWM (MCPWM) lowering on Zephyr.',
|
|
461
|
+
partialCoverage: false,
|
|
462
|
+
ops: unsupportedOps('mcpwm.'),
|
|
463
|
+
},
|
|
464
|
+
raw: { supported: true },
|
|
465
|
+
},
|
|
466
|
+
polyfills: {
|
|
467
|
+
emitted: [
|
|
468
|
+
{ id: 'cuttlefish_halt', domain: 'standard', notes: 'Mapped to a k_msleep halt loop (exceptions disabled)' },
|
|
469
|
+
{ id: 'timer_methods', domain: 'embedded', notes: 'k_timer + k_work pool (system workqueue); callbacks run in thread context' },
|
|
470
|
+
{ id: 'async_runtime', domain: 'embedded', notes: 'Heap-free static Promise/microtask runtime (generateStaticAsyncRuntime), pumped in loop()' },
|
|
471
|
+
],
|
|
472
|
+
suppressed: [],
|
|
473
|
+
},
|
|
474
|
+
toolchain: {
|
|
475
|
+
backend: 'west',
|
|
476
|
+
operations: { prepare: true, compile: true, upload: true, monitor: true },
|
|
477
|
+
},
|
|
478
|
+
libraryResolution: {
|
|
479
|
+
isFrameworkLibraryImport: false,
|
|
480
|
+
getFrameworkLibraryHeaderName: false,
|
|
481
|
+
buildClassNameMap: false,
|
|
482
|
+
tryGenerateLibDecl: false,
|
|
483
|
+
},
|
|
484
|
+
typeEmission: {
|
|
485
|
+
normalizeCppType: true,
|
|
486
|
+
mathHeader: '<math.h>',
|
|
487
|
+
needsStdString: false,
|
|
488
|
+
needsStdVector: false,
|
|
489
|
+
needsIostream: false,
|
|
490
|
+
needsStdFunction: false,
|
|
491
|
+
stdlibSupport: {
|
|
492
|
+
hasVector: false,
|
|
493
|
+
hasString: false,
|
|
494
|
+
hasIostream: false,
|
|
495
|
+
hasExceptions: false,
|
|
496
|
+
hasRTTI: false,
|
|
497
|
+
recommendedArrayImpl: 'static_array',
|
|
498
|
+
recommendedStringImpl: 'static_string',
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
ambientTypes: ['Preferences'],
|
|
502
|
+
conformance: {
|
|
503
|
+
// Hardware-test groups — each entry is backed by a tests/<group>.test.ts
|
|
504
|
+
// file in this package (validated by the manifest validator). Mirrors the
|
|
505
|
+
// framework-avr/framework-esp32 convention. These run on metal via
|
|
506
|
+
// `npm run test:hw` (cuttlefish-test transpiles → west build → flash).
|
|
507
|
+
hardwareTestGroups: [
|
|
508
|
+
'01-basics',
|
|
509
|
+
'30-timing',
|
|
510
|
+
'40-gpio',
|
|
511
|
+
'41-analog',
|
|
512
|
+
'42-timers',
|
|
513
|
+
],
|
|
514
|
+
// Per-op HAL-resolution suite — one tests/packages/framework-zephyr/
|
|
515
|
+
// hal-resolution/<cat>.test.ts per category, snapshotting the exact C++
|
|
516
|
+
// each op lowers to. Mirrors the framework-esp32 convention. These are
|
|
517
|
+
// pure string-snapshot tests (no hardware); they are the safety net that
|
|
518
|
+
// catches regressions like silent pull-resistor / interrupt no-ops.
|
|
519
|
+
halResolutionTests: [
|
|
520
|
+
'adc', 'ble', 'board', 'dac', 'gpio', 'http', 'i2c', 'interrupts', 'mqtt',
|
|
521
|
+
'power', 'preferences', 'pulse', 'pwm', 'random', 'spi', 'timing', 'tone',
|
|
522
|
+
'uart', 'wdt', 'worker',
|
|
523
|
+
],
|
|
524
|
+
},
|
|
525
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
2
|
+
export { ZephyrStrategy } from './strategy.js';
|
|
3
|
+
export { Toolchain } from './toolchain/index.js';
|
|
4
|
+
export { chipForTarget, setActiveChip, getActiveChip, XIAO_BLE, } from './chips/index.js';
|
|
5
|
+
export type { ZephyrChipDescriptor, ZephyrGpioDtSpec, } from './chips/types.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// @typecad/framework-zephyr — public exports
|
|
3
|
+
//
|
|
4
|
+
// The cuttlefish loader (framework-package.ts) requires a `FrameworkStrategy`
|
|
5
|
+
// export (the PlatformStrategy class it instantiates) and an optional
|
|
6
|
+
// `Toolchain`. This package aliases ZephyrStrategy → FrameworkStrategy.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
export { ZephyrStrategy as FrameworkStrategy } from './strategy.js';
|
|
9
|
+
export { ZephyrStrategy } from './strategy.js';
|
|
10
|
+
export { Toolchain } from './toolchain/index.js';
|
|
11
|
+
// Chip descriptor registry (for downstream tooling / additional boards).
|
|
12
|
+
export { chipForTarget, setActiveChip, getActiveChip, XIAO_BLE, } from './chips/index.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
2
|
+
import type { ZephyrChipDescriptor } from '../chips/types.js';
|
|
3
|
+
/** Resolve the SAADC channel index for a HAL pin number; -1 if unmapped. */
|
|
4
|
+
export declare function adcChannelForPin(chip: ZephyrChipDescriptor, pin: number): number;
|
|
5
|
+
/**
|
|
6
|
+
* Emit the per-channel ADC setup state. One block per channel in the chip
|
|
7
|
+
* descriptor, each guarded by a `static bool __tc_adc<N>_ready` so the first
|
|
8
|
+
* read configures it and subsequent reads skip. Called from shimLines when
|
|
9
|
+
* the program uses ADC.
|
|
10
|
+
*/
|
|
11
|
+
export declare function adcInitLines(chip: ZephyrChipDescriptor): string[];
|
|
12
|
+
/**
|
|
13
|
+
* Resolve a HAL adc.* op to Zephyr C++.
|
|
14
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
15
|
+
*/
|
|
16
|
+
export declare function lowerAdc(op: HALOpIR, chip: ZephyrChipDescriptor): {
|
|
17
|
+
code?: string;
|
|
18
|
+
expression?: string;
|
|
19
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// ADC lowering — nRF SAADC via raw adc_read
|
|
3
|
+
//
|
|
4
|
+
// The XIAO nRF52840 has no pre-declared ADC channel nodes in devicetree, so we
|
|
5
|
+
// cannot use the `adc_dt_spec` convenience. Instead the lowering configures the
|
|
6
|
+
// channel up-front against DEVICE_DT_GET(DT_NODELABEL(adc)) and reads it with
|
|
7
|
+
// `adc_read`. The channel index comes from the chip descriptor's pin→channel
|
|
8
|
+
// map (XIAO D0–D3 = AIN0–AIN3).
|
|
9
|
+
//
|
|
10
|
+
// Channel setup is emitted in adcInitLines() (one per channel used); the ops
|
|
11
|
+
// then just read. A static `adc_channel_cfg` + a per-channel "configured" flag
|
|
12
|
+
// guards the setup, so repeated reads don't reconfigure.
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
/** Resolve the SAADC channel index for a HAL pin number; -1 if unmapped. */
|
|
15
|
+
export function adcChannelForPin(chip, pin) {
|
|
16
|
+
const ch = chip.adc?.channels.find((c) => c.pin === pin);
|
|
17
|
+
return ch ? ch.channel : -1;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Emit the per-channel ADC setup state. One block per channel in the chip
|
|
21
|
+
* descriptor, each guarded by a `static bool __tc_adc<N>_ready` so the first
|
|
22
|
+
* read configures it and subsequent reads skip. Called from shimLines when
|
|
23
|
+
* the program uses ADC.
|
|
24
|
+
*/
|
|
25
|
+
export function adcInitLines(chip) {
|
|
26
|
+
const dev = `DEVICE_DT_GET(DT_NODELABEL(${chip.adc?.nodeLabel ?? 'adc'}))`;
|
|
27
|
+
const res = chip.adc?.resolution ?? 12;
|
|
28
|
+
const vref = chip.adc?.vrefMv ?? 3000;
|
|
29
|
+
const lines = ['// CUTTLEFISH_ADC_BEGIN'];
|
|
30
|
+
lines.push(`static const struct device* __tc_adc_dev = ${dev};`);
|
|
31
|
+
for (const c of chip.adc?.channels ?? []) {
|
|
32
|
+
const n = c.channel;
|
|
33
|
+
lines.push(`static bool __tc_adc${n}_ready = false;`, `static void __tc_adc${n}_setup(void) {`, ` if (__tc_adc${n}_ready) return;`, ` const struct adc_channel_cfg cfg = {`, ` .gain = ADC_GAIN_1_4,`, ` .reference = ADC_REF_INTERNAL,`, ` .acquisition_time = ADC_ACQ_TIME_DEFAULT,`, ` .channel_id = ${n},`, ` .differential = 0,`, ` };`, ` adc_channel_setup(__tc_adc_dev, &cfg);`, ` __tc_adc${n}_ready = true;`, `}`);
|
|
34
|
+
}
|
|
35
|
+
lines.push(`#define __TC_ADC_VREF_MV ${vref}`);
|
|
36
|
+
lines.push(`#define __TC_ADC_RESOLUTION ${res}`);
|
|
37
|
+
lines.push('// CUTTLEFISH_ADC_END');
|
|
38
|
+
return lines;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve a HAL adc.* op to Zephyr C++.
|
|
42
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
43
|
+
*/
|
|
44
|
+
export function lowerAdc(op, chip) {
|
|
45
|
+
const o = op;
|
|
46
|
+
const res = chip.adc?.resolution ?? 12;
|
|
47
|
+
const vref = chip.adc?.vrefMv ?? 3000;
|
|
48
|
+
switch (op.operation) {
|
|
49
|
+
case 'adc.read': {
|
|
50
|
+
const ch = adcChannelForPin(chip, o.pin);
|
|
51
|
+
// GCC statement-expression: configures-on-first-call, reads, returns raw.
|
|
52
|
+
return {
|
|
53
|
+
expression: `({ __tc_adc${ch}_setup(); int16_t __b = 0; struct adc_sequence __s = { .channels = BIT(${ch}), .buffer = &__b, .buffer_size = sizeof(__b), .resolution = ${res} }; adc_read(__tc_adc_dev, &__s); __b; })`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
case 'adc.read_voltage': {
|
|
57
|
+
const ch = adcChannelForPin(chip, o.pin);
|
|
58
|
+
// Read raw, convert to millivolts via adc_raw_to_millivolts (gain 1/4,
|
|
59
|
+
// internal ref). Returns mV as int.
|
|
60
|
+
return {
|
|
61
|
+
expression: `({ __tc_adc${ch}_setup(); int16_t __b = 0; struct adc_sequence __s = { .channels = BIT(${ch}), .buffer = &__b, .buffer_size = sizeof(__b), .resolution = ${res} }; adc_read(__tc_adc_dev, &__s); int32_t __v = __b; adc_raw_to_millivolts(${vref}, ADC_GAIN_1_4, ${res}, &__v); __v; })`,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
case 'adc.get_resolution':
|
|
65
|
+
return { expression: String(res) };
|
|
66
|
+
case 'adc.set_reference':
|
|
67
|
+
// Zephyr configures the reference at channel-setup time; runtime switching
|
|
68
|
+
// would require re-setup. Record the intent as a no-op statement.
|
|
69
|
+
return { code: `/* adc.set_reference(${o.reference}): configured at channel setup (ADC_REF_INTERNAL) */` };
|
|
70
|
+
case 'adc.get_reference':
|
|
71
|
+
return { expression: `0 /* DEFAULT (ADC_REF_INTERNAL) */` };
|
|
72
|
+
default:
|
|
73
|
+
throw new Error(`framework-zephyr does not yet support HAL op \`${op.operation}\`. ` +
|
|
74
|
+
`Open an issue or use rawCpp() to emit it manually.`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HALOpIR } from '@typecad/cuttlefish/api/shared';
|
|
2
|
+
/**
|
|
3
|
+
* The BLE runtime shim. All helpers are `static` (file-scope) so unused ones
|
|
4
|
+
* don't trip -Wunused-function in the single generated TU.
|
|
5
|
+
*
|
|
6
|
+
* State mirrors the HAL BleStatus enum:
|
|
7
|
+
* 0 Idle, 1 Initializing, 2 Advertising, 3 Connected, 4 Error.
|
|
8
|
+
*/
|
|
9
|
+
export declare function bleInitLines(): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a HAL ble.* op to Zephyr NimBLE C++ via the __tc_ble_* shim.
|
|
12
|
+
* Returns `{ code }` for statement ops, `{ expression }` for value-returning ops.
|
|
13
|
+
*
|
|
14
|
+
* The current_char-keyed callback assignment pattern (on_read/on_write set into
|
|
15
|
+
* the table by the index add_char last established) ports verbatim from ESP32.
|
|
16
|
+
*/
|
|
17
|
+
export declare function lowerBle(op: HALOpIR): {
|
|
18
|
+
code?: string;
|
|
19
|
+
expression?: string;
|
|
20
|
+
};
|