driverge-mcp 0.1.0-beta.2 → 0.1.0-beta.3

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 CHANGED
@@ -4,7 +4,7 @@
4
4
  <p align="center"><em>Datasheet PDF → embedded C/C++ driver, from any MCP client.</em></p>
5
5
 
6
6
  <p align="center">
7
- <a href="https://www.npmjs.com/package/driverge-mcp"><img alt="npm" src="https://img.shields.io/npm/v/driverge-mcp"></a>
7
+ <a href="https://www.npmjs.com/package/driverge-mcp"><img alt="npm (beta)" src="https://img.shields.io/npm/v/driverge-mcp/beta"></a>
8
8
  <a href="https://github.com/MehmetTopuz/driverge-mcp/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/MehmetTopuz/driverge-mcp/actions/workflows/ci.yml/badge.svg"></a>
9
9
  <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-blue"></a>
10
10
  <img alt="status" src="https://img.shields.io/badge/status-closed%20beta-orange">
@@ -108,14 +108,16 @@ changes.
108
108
 
109
109
  | Target | Bus binding | Buses | Language | Maturity |
110
110
  |---|---|---|---|---|
111
- | **Portable (thin-HAL)** | user-implemented `hal_*` seam | I²C, SPI, UART, CAN | C / C++ | **Beta** — host-tested, gcc-compiled in CI; not yet on hardware |
111
+ | **Portable (thin-HAL)** | user-implemented `<part>_hal_*` seam | I²C, SPI, UART, CAN | C / C++ | **Beta** — host-tested, gcc-compiled in CI; not yet on hardware |
112
112
  | **ESP32** | ESP-IDF (`i2c_master_*`, `spi_master`, `uart`, TWAI) | I²C, SPI, UART, CAN | C / C++ | **Experimental** — one informal I²C bring-up; SPI/UART/CAN never on hardware |
113
- | **STM32** | CubeHAL (`HAL_I2C_*`, `HAL_SPI_*` + GPIO CS, `HAL_UART_*`) | I²C, SPI, UART | C / C++ | **Experimental** — never on hardware |
113
+ | **STM32** | CubeHAL (`HAL_I2C_*`, `HAL_SPI_*` + GPIO CS, `HAL_UART_*`) | I²C, SPI, UART | C / C++ | **Experimental** — 3 hardware field tests (NUCLEO-G474RE, hand-completed); no automated compile gate yet |
114
114
  | **Arduino** | `Wire` / `SPI` | — | C++ | not implemented |
115
115
 
116
- STM32 CAN is planned (the bxCAN/FDCAN family split needs its own pass); asking a
117
- target for a bus it doesn't support fails fast with a clear
118
- `UnsupportedBusError` rather than emitting a wrong seam. Pass
116
+ STM32 CAN is planned (the bxCAN/FDCAN family split needs its own pass), and a
117
+ next wave of native targets RP2040/RP2350, TI MSPM0, NXP MCX/i.MX RT,
118
+ Nuvoton NuMicro, Microchip PIC, and eventually Zephyr — is on the
119
+ [Roadmap](#roadmap). Asking a target for a bus it doesn't support fails fast
120
+ with a clear `UnsupportedBusError` rather than emitting a wrong seam. Pass
119
121
  `language: "cpp"` to `generate_driver` for a class-based C++ driver
120
122
  (`.hpp`/`.cpp`) instead of the default C output — same registers, same seam,
121
123
  same validation. What "Beta" and "Experimental" mean exactly is spelled out in
@@ -136,8 +138,8 @@ The extraction pipeline is regression-tested against real datasheets from
136
138
  | LSM6DSRX | STMicroelectronics | register map | 31 regs, 91 bit-fields |
137
139
  | MAX30102 | Maxim Integrated | register map | 20 regs, 33 bit-fields |
138
140
 
139
- Other tested parts (ADXL345, MLX90614, AEAT-8811, PCA9685, VL53L3CX, TLE5014)
140
- extract **partially** or **defer** to the host AI — the pipeline says so
141
+ Other tested parts (ADXL345, MLX90614, AEAT-8811, PCA9685, VL53L3CX, TLE5014,
142
+ TCA6408A) extract **partially** or **defer** to the host AI — the pipeline says so
141
143
  explicitly instead of guessing. The full, always-current matrix lives in the
142
144
  [coverage scorecard](tests/scorecard/scorecard.snap.md).
143
145
 
@@ -146,17 +148,20 @@ explicitly instead of guessing. The full, always-current matrix lives in the
146
148
  Driverge is in **closed beta** (`0.1.0-beta.x`, npm `beta` dist-tag).
147
149
 
148
150
  **Proven today (host-level):**
149
- - The full deterministic test suite is green (440-plus tests) on a clean
151
+ - The full deterministic test suite is green (540-plus tests) on a clean
150
152
  TypeScript build, and the **portable** driver is compiled by a real `gcc`
151
- gate in CI.
152
- - The extraction pipeline is regression-tested against **13 real datasheets**
153
- and reports its own coverage honestly — 7 fully extracted, 3 partial, 3
153
+ gate in CI (including a multi-driver link gate).
154
+ - The extraction pipeline is regression-tested against **14 real datasheets**
155
+ and reports its own coverage honestly — 7 fully extracted, 4 partial, 3
154
156
  deferred (see the [coverage scorecard](tests/scorecard/scorecard.snap.md)).
155
157
 
156
158
  **Not yet proven — this is the beta → v0.1.0 gate:**
157
- - **On-hardware behavior is not gated.** Only one informal ESP32 bring-up has
158
- run (MPU-9250, hand-completed); there is no clean, repeatable hardware pass
159
- yet, and STM32 has never run on silicon.
159
+ - **On-hardware behavior is not gated by CI.** STM32 has now run on real
160
+ hardware three NUCLEO-G474RE field tests (onsemi FXL6408 I²C, TI TUSS4470
161
+ SPI, Microchip CAP1206 I²C), each hand-completed and folded back into the
162
+ generator — and ESP32 has one informal I²C bring-up (MPU-9250). There is still
163
+ no clean, repeatable automated hardware pass, so every generated driver needs
164
+ review before you flash it.
160
165
  - The native ESP32/STM32 seams are not yet built by an automated compile gate
161
166
  (ESP-IDF / CubeIDE) — only the portable target is.
162
167
  - Only one MCP client has been exercised end-to-end.
@@ -206,23 +211,27 @@ re-parse, and the full JSON stays readable at `driverge://datasheet/<ref>`.
206
211
  ### The thin-HAL seam
207
212
 
208
213
  Generated drivers touch hardware through a tiny per-bus seam — and nothing
209
- else:
214
+ else. Seam symbols are **prefixed with the part's slug** (e.g.
215
+ `bme280_hal_i2c_read`) so two Driverge drivers can link into one firmware
216
+ image without symbol collisions:
210
217
 
211
- | Bus | Seam functions (plus `hal_delay_ms`) |
218
+ | Bus | Seam functions (plus `<part>_hal_delay_ms`) |
212
219
  |---|---|
213
- | I²C | `hal_i2c_read`, `hal_i2c_write` |
214
- | SPI | `hal_spi_transfer` (one call = one CS-framed transaction) |
215
- | UART | `hal_uart_write`, `hal_uart_read` |
216
- | CAN | `hal_can_transfer` (one call = one frame exchange) |
220
+ | I²C | `<part>_hal_i2c_read`, `<part>_hal_i2c_write` |
221
+ | SPI | `<part>_hal_spi_transfer(tx, rx, len)` (one call = one CS-framed **full-duplex** transaction; `rx` may be `NULL` for write-only, and write-then-read devices are served by padding `tx` with dummy bytes) |
222
+ | UART | `<part>_hal_uart_write`, `<part>_hal_uart_read` |
223
+ | CAN | `<part>_hal_can_transfer` (one call = one frame exchange) |
217
224
 
218
225
  The transfer seams return `int` — **`0` on success, non-zero on a bus error**
219
226
  (NACK, timeout) — and the generated register accessors propagate that status
220
227
  instead of swallowing it; native seams (ESP32, STM32) return their vendor
221
- status, which is already `0` on success. `validate_driver` enforces seam
222
- purity: a driver that calls a vendor peripheral API outside the seam fails the
223
- lint. Buses with no universal register-access primitive (UART, CAN) get their
224
- device-specific framing as a marked `TODO(driverge)` gap, completed by the host
225
- AI and then linted.
228
+ status, which is already `0` on success. Native targets also emit a seam
229
+ companion header (`<part>_hal_stm32.h` / `<part>_hal_esp32.h`) declaring the
230
+ one-time `bind` call that points the seam at your peripheral handle.
231
+ `validate_driver` enforces seam purity: a driver that calls a vendor
232
+ peripheral API outside the seam fails the lint. Buses with no universal
233
+ register-access primitive (UART, CAN) get their device-specific framing as a
234
+ marked `TODO(driverge)` gap, completed by the host AI and then linted.
226
235
 
227
236
  ### The fill-in loop
228
237
 
@@ -277,6 +286,7 @@ development.
277
286
  | Env var | Default | Purpose |
278
287
  |---|---|---|
279
288
  | `DRIVERGE_OUT_ROOT` | server's working directory | Root that `generate_driver`'s `out_dir` writes are confined to. Any `out_dir` that resolves outside this root is rejected (`out_dir "…" escapes the allowed root`). Set it to the directory you want drivers written into. |
289
+ | `DRIVERGE_MAX_PDF_BYTES` | `67108864` (64 MiB) | Maximum PDF size `analyze_datasheet` will read. A larger file is rejected with a clear "PDF too large" error before any parsing — bounds memory use on a hostile or accidentally huge input. |
280
290
 
281
291
  Set it in the MCP config's `env` block, e.g.:
282
292
 
@@ -431,6 +441,13 @@ datasheet prose, and `validate_driver` checks the result.
431
441
  (I²C, SPI, UART, CAN) ✅; C or C++ output ✅. *(current)*
432
442
  - **v1.0** — broader vendor/part coverage, STM32 CAN (bxCAN/FDCAN), and a
433
443
  stable, versioned JSON schema.
444
+ - **v1.x** — new native MCU targets (same portable thin-HAL core, one seam
445
+ file per platform; prioritized by beta-tester demand): **RP2040/RP2350**
446
+ (pico-sdk), **TI MSPM0** (DriverLib), **NXP MCX / i.MX RT** (MCUXpresso
447
+ `fsl_lpi2c`/`fsl_lpspi`), **Nuvoton NuMicro** (BSP Standard Driver), and
448
+ **Microchip PIC** (MCC Melody for 8/16-bit; Harmony v3 for PIC32).
449
+ - **Later** — a **Zephyr** meta-target (devicetree-based `i2c`/`spi` API):
450
+ one seam covering Nordic nRF and every other Zephyr-supported vendor.
434
451
 
435
452
  Day-to-day progress is tracked in the [CHANGELOG](CHANGELOG.md).
436
453
 
@@ -1,11 +1,14 @@
1
1
  import type { DatasheetJson } from "../schema/types.js";
2
2
  import type { CodegenLanguage, DriverArtifact } from "./types.js";
3
3
  /**
4
- * Portable core + an ESP-IDF seam implementation for the same part. With
5
- * language "c" (default) the seam is `<slug>_hal_esp32.c`, unchanged from
6
- * before. With language "cpp" the seam becomes `<slug>_hal_esp32.cpp` and its
7
- * core include is `#include "<slug>.hpp"` (see coreInclude/seamPath above) —
8
- * everything else in the seam content is identical either way.
4
+ * Portable core + an ESP-IDF seam implementation + a seam companion header for
5
+ * the same part. With language "c" (default) the seam is `<slug>_hal_esp32.c`;
6
+ * with language "cpp" it is `<slug>_hal_esp32.cpp` and its core include is
7
+ * `#include "<slug>.hpp"` (see coreInclude/seamPath above) — everything else
8
+ * in the seam content is identical either way. The companion header
9
+ * (`<slug>_hal_esp32.h`) is always a plain `.h` file, in BOTH language runs.
10
+ * File order in the artifact: [core header, core source, companion header,
11
+ * seam source] — see tests/codegen/esp32.test.ts.
9
12
  */
10
13
  export declare function generateEsp32Driver(json: DatasheetJson, opts?: {
11
14
  language?: CodegenLanguage;
@@ -1,18 +1,28 @@
1
1
  // ESP32 (ESP-IDF) target. Per platform-code-generation-targets, a native target
2
2
  // does NOT replace the thin HAL — it *pre-fills* the seam. So the ESP32 driver is
3
3
  // the exact portable core (unchanged, still platform-agnostic) PLUS a
4
- // <part>_hal_esp32.c that implements the bus's thin-HAL seam + hal_delay_ms with
5
- // ESP-IDF v5 drivers. The user drops all three files into an ESP-IDF component;
6
- // only the board's bus/pin bring-up stays a TODO(driverge).
4
+ // <slug>_hal_esp32.c that implements the bus's thin-HAL seam + <slug>_hal_delay_ms
5
+ // with ESP-IDF v5 drivers, PLUS a <slug>_hal_esp32.h companion header declaring
6
+ // the <slug>_esp32_bind(...) prototype the seam .c defines. The user drops all
7
+ // four files into an ESP-IDF component; only the board's bus/pin bring-up
8
+ // stays a TODO(driverge).
9
+ //
10
+ // Session E (2026-07-11 field-test findings — see raw/stm32-test-results/*.md
11
+ // and the approved plan, whose findings generalize to every native target):
12
+ // every seam symbol is PER-DRIVER PREFIXED (`<slug>_hal_*` — see busSeam in
13
+ // portable.ts), so two Driverge drivers in one project never collide at link.
14
+ // The SPI seam is also now a single full-duplex <slug>_hal_spi_transfer(tx,
15
+ // rx, len) — one spi_transaction_t (length = len*8, tx_buffer/rx_buffer, no
16
+ // SPI_DEVICE_HALFDUPLEX flag) — matching the portable core's contract exactly.
7
17
  //
8
18
  // I2C/SPI/UART/CAN only: the I2C seam references `${PREFIX}_I2C_ADDR`, a macro
9
19
  // the portable core only defines for I2C parts; the SPI seam needs the portable
10
- // core's hal_spi_transfer declaration; the UART seam (Session B) wraps ESP-IDF's
11
- // uart driver around hal_uart_write/hal_uart_read; the CAN seam (Session C)
12
- // wraps ESP-IDF's TWAI (Two-Wire Automotive Interface, ESP-IDF's CAN 2.0
13
- // controller) driver around hal_can_transfer — any other bus (unknown) has no
14
- // ESP-IDF seam here, so this target refuses (UnsupportedBusError) rather than
15
- // emit an uncompilable seam.
20
+ // core's <slug>_hal_spi_transfer declaration; the UART seam (Session B) wraps
21
+ // ESP-IDF's uart driver around <slug>_hal_uart_write/<slug>_hal_uart_read; the
22
+ // CAN seam (Session C) wraps ESP-IDF's TWAI (Two-Wire Automotive Interface,
23
+ // ESP-IDF's CAN 2.0 controller) driver around <slug>_hal_can_transfer — any
24
+ // other bus (unknown) has no ESP-IDF seam here, so this target refuses
25
+ // (UnsupportedBusError) rather than emit an uncompilable seam.
16
26
  import { prefixOf, slug } from "./ident.js";
17
27
  import { generatePortableCppDriver } from "./portable-cpp.js";
18
28
  import { generatePortableDriver } from "./portable.js";
@@ -26,24 +36,73 @@ import { UnsupportedBusError } from "./types.js";
26
36
  // nothing: the .hpp declares the hal_* seam inside `extern "C"`, so compiling
27
37
  // this seam as C++ still emits plain C-linkage definitions the class methods
28
38
  // can call, and both ESP-IDF and a C++-enabled CubeMX project compile .cpp
29
- // sources natively.
39
+ // sources natively. The seam companion header (Session E) stays a plain `.h`
40
+ // file in BOTH language runs — its own `extern "C"` guard makes it valid from
41
+ // either a C or a C++ translation unit, so there is nothing to switch on
42
+ // `language` for (see companionHeaderEsp32 below).
30
43
  function coreInclude(name, language) {
31
44
  return `#include "${name}.${language === "cpp" ? "hpp" : "h"}"`;
32
45
  }
33
46
  function seamPath(name, language) {
34
47
  return `${name}_hal_esp32.${language === "cpp" ? "cpp" : "c"}`;
35
48
  }
49
+ function companionHeaderName(name) {
50
+ return `${name}_hal_esp32.h`;
51
+ }
52
+ /**
53
+ * Session E: the seam companion header. Declares the `<slug>_esp32_bind(...)`
54
+ * prototype the seam .c/.cpp defines — the CAP1206/FXL6408 field sessions both
55
+ * had to hand-write this prototype into their own application code
56
+ * (raw/stm32-test-results/*.md §6) because Driverge never emitted it.
57
+ * `includeLine` is the ESP-IDF driver header the bind signature's vendor
58
+ * type(s) need (driver/i2c_master.h, driver/spi_master.h, driver/uart.h,
59
+ * driver/twai.h); `bindProtoLine` is the exact signature (identical to the
60
+ * `<ret> <slug>_esp32_bind(...) {` line the seam defines, just with a
61
+ * trailing `;` instead of a body) — passed in by each halImplX below so the
62
+ * header and the definition can never drift.
63
+ */
64
+ function companionHeaderEsp32(name, prefix, includeLine, bindProtoLine) {
65
+ const guard = `${prefix}_HAL_ESP32_H`;
66
+ const content = [
67
+ "/*",
68
+ ` * ${prefix} — ESP-IDF HAL seam companion header (generated by Driverge).`,
69
+ " *",
70
+ ` * Declares ${name}_esp32_bind(), which ${name}_hal_esp32.c/.cpp defines.`,
71
+ " * Include this header from your application code to call it after bus/",
72
+ " * peripheral bring-up.",
73
+ " */",
74
+ `#ifndef ${guard}`,
75
+ `#define ${guard}`,
76
+ "",
77
+ "#ifdef __cplusplus",
78
+ 'extern "C" {',
79
+ "#endif",
80
+ "",
81
+ includeLine,
82
+ "",
83
+ bindProtoLine,
84
+ "",
85
+ "#ifdef __cplusplus",
86
+ "}",
87
+ "#endif",
88
+ `#endif /* ${guard} */`,
89
+ "",
90
+ ].join("\n");
91
+ return { path: companionHeaderName(name), content };
92
+ }
36
93
  function halImplI2c(name, prefix, language) {
37
94
  const content = [
38
95
  "/*",
39
96
  ` * ${prefix} — ESP-IDF (i2c_master) HAL seam implementation (generated by Driverge).`,
40
97
  " *",
41
98
  " * Drop this beside the portable core; it fills the thin-HAL seam with the",
42
- " * ESP-IDF v5 i2c_master driver. In your app: create an I2C master bus with",
43
- ` * i2c_new_master_bus() for your SDA/SCL pins, then call ${name}_esp32_bind()`,
44
- " * once before using the driver. The driver core stays byte-for-byte portable.",
99
+ " * ESP-IDF v5 i2c_master driver. See the companion header",
100
+ ` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
101
+ " * call it once (after i2c_new_master_bus()) before using the driver. The",
102
+ " * driver core stays byte-for-byte portable.",
45
103
  " */",
46
104
  coreInclude(name, language),
105
+ `#include "${companionHeaderName(name)}"`,
47
106
  "#include <string.h>",
48
107
  '#include "driver/i2c_master.h"',
49
108
  '#include "freertos/FreeRTOS.h"',
@@ -66,7 +125,7 @@ function halImplI2c(name, prefix, language) {
66
125
  ` return i2c_master_bus_add_device(bus, &cfg, &s_${name}_dev);`,
67
126
  "}",
68
127
  "",
69
- "int hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {",
128
+ `int ${name}_hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {`,
70
129
  " uint8_t buf[33];",
71
130
  " (void)addr; /* the device handle already encodes the bus address */",
72
131
  " if ((size_t)len + 1u > sizeof buf) {",
@@ -77,17 +136,18 @@ function halImplI2c(name, prefix, language) {
77
136
  ` return i2c_master_transmit(s_${name}_dev, buf, (size_t)len + 1u, ${prefix}_I2C_TIMEOUT_MS);`,
78
137
  "}",
79
138
  "",
80
- "int hal_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {",
139
+ `int ${name}_hal_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {`,
81
140
  " (void)addr;",
82
141
  ` return i2c_master_transmit_receive(s_${name}_dev, &reg, 1, data, len, ${prefix}_I2C_TIMEOUT_MS);`,
83
142
  "}",
84
143
  "",
85
- "void hal_delay_ms(uint32_t ms) {",
144
+ `void ${name}_hal_delay_ms(uint32_t ms) {`,
86
145
  " vTaskDelay(pdMS_TO_TICKS(ms));",
87
146
  "}",
88
147
  "",
89
148
  ].join("\n");
90
- return { path: seamPath(name, language), content };
149
+ const header = companionHeaderEsp32(name, prefix, '#include "driver/i2c_master.h"', `esp_err_t ${name}_esp32_bind(i2c_master_bus_handle_t bus, uint32_t scl_speed_hz);`);
150
+ return [header, { path: seamPath(name, language), content }];
91
151
  }
92
152
  function halImplSpi(name, prefix, language) {
93
153
  const content = [
@@ -95,13 +155,14 @@ function halImplSpi(name, prefix, language) {
95
155
  ` * ${prefix} — ESP-IDF (spi_master) HAL seam implementation (generated by Driverge).`,
96
156
  " *",
97
157
  " * Drop this beside the portable core; it fills the thin-HAL seam with the",
98
- " * ESP-IDF v5 spi_master driver: one half-duplex, polling transaction per",
99
- ` * hal_spi_transfer() call. In your app: bring up the SPI bus with`,
100
- " * spi_bus_initialize() for your MOSI/MISO/SCLK pins, then call",
101
- ` * ${name}_esp32_bind() once before using the driver. The driver core stays`,
102
- " * byte-for-byte portable.",
158
+ " * ESP-IDF v5 spi_master driver: one full-duplex, polling transaction per",
159
+ ` * ${name}_hal_spi_transfer() call. See the companion header`,
160
+ ` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
161
+ " * call it once (after spi_bus_initialize()) before using the driver. The",
162
+ " * driver core stays byte-for-byte portable.",
103
163
  " */",
104
164
  coreInclude(name, language),
165
+ `#include "${companionHeaderName(name)}"`,
105
166
  "#include <string.h>",
106
167
  '#include "driver/spi_master.h"',
107
168
  '#include "freertos/FreeRTOS.h"',
@@ -114,7 +175,6 @@ function halImplSpi(name, prefix, language) {
114
175
  " * see fill_in_brief.hal_setup_todo for the SPI mode this part expects. */",
115
176
  `esp_err_t ${name}_esp32_bind(spi_host_device_t host, int cs_gpio, int clock_hz) {`,
116
177
  " spi_device_interface_config_t cfg = {",
117
- " .flags = SPI_DEVICE_HALFDUPLEX,",
118
178
  " .spics_io_num = cs_gpio,",
119
179
  " .clock_speed_hz = clock_hz,",
120
180
  " .mode = 0, /* see fill_in_brief.hal_setup_todo for this part's SPI mode */",
@@ -123,22 +183,24 @@ function halImplSpi(name, prefix, language) {
123
183
  ` return spi_bus_add_device(host, &cfg, &s_${name}_dev);`,
124
184
  "}",
125
185
  "",
126
- "int hal_spi_transfer(const uint8_t *tx, uint16_t tx_len, uint8_t *rx, uint16_t rx_len) {",
186
+ "/* Full-duplex: ONE spi_transaction_t clocks tx out and rx in together — no",
187
+ " * half-duplex device flag needed; hardware CS works fine in full-duplex too. */",
188
+ `int ${name}_hal_spi_transfer(const uint8_t *tx, uint8_t *rx, uint16_t len) {`,
127
189
  " spi_transaction_t t;",
128
190
  " memset(&t, 0, sizeof t);",
129
- " t.length = 8 * tx_len;",
130
- " t.rxlength = 8 * rx_len;",
191
+ " t.length = 8 * len;",
131
192
  " t.tx_buffer = tx;",
132
193
  " t.rx_buffer = rx;",
133
194
  ` return spi_device_polling_transmit(s_${name}_dev, &t);`,
134
195
  "}",
135
196
  "",
136
- "void hal_delay_ms(uint32_t ms) {",
197
+ `void ${name}_hal_delay_ms(uint32_t ms) {`,
137
198
  " vTaskDelay(pdMS_TO_TICKS(ms));",
138
199
  "}",
139
200
  "",
140
201
  ].join("\n");
141
- return { path: seamPath(name, language), content };
202
+ const header = companionHeaderEsp32(name, prefix, '#include "driver/spi_master.h"', `esp_err_t ${name}_esp32_bind(spi_host_device_t host, int cs_gpio, int clock_hz);`);
203
+ return [header, { path: seamPath(name, language), content }];
142
204
  }
143
205
  function halImplUart(name, prefix, language) {
144
206
  const content = [
@@ -146,13 +208,14 @@ function halImplUart(name, prefix, language) {
146
208
  ` * ${prefix} — ESP-IDF (uart) HAL seam implementation (generated by Driverge).`,
147
209
  " *",
148
210
  " * Drop this beside the portable core; it fills the thin-HAL seam with the",
149
- " * ESP-IDF v5 UART driver. In your app: configure and install the UART driver",
150
- " * (uart_param_config + uart_driver_install) for your TX/RX pins, port, and",
151
- ` * this part's baud rate, then call ${name}_esp32_bind() once before using the`,
152
- " * driver. The driver core stays byte-for-byte portable. See",
211
+ " * ESP-IDF v5 UART driver. See the companion header",
212
+ ` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
213
+ " * call it once (after uart_param_config + uart_driver_install) before",
214
+ " * using the driver. The driver core stays byte-for-byte portable. See",
153
215
  " * fill_in_brief.hal_setup_todo for the baud rate/config to use.",
154
216
  " */",
155
217
  coreInclude(name, language),
218
+ `#include "${companionHeaderName(name)}"`,
156
219
  '#include "driver/uart.h"',
157
220
  '#include "freertos/FreeRTOS.h"',
158
221
  '#include "freertos/task.h"',
@@ -165,11 +228,11 @@ function halImplUart(name, prefix, language) {
165
228
  ` s_${name}_port = port;`,
166
229
  "}",
167
230
  "",
168
- "void hal_uart_write(const uint8_t *data, uint16_t len) {",
231
+ `void ${name}_hal_uart_write(const uint8_t *data, uint16_t len) {`,
169
232
  ` uart_write_bytes(s_${name}_port, (const char *)data, len);`,
170
233
  "}",
171
234
  "",
172
- "uint16_t hal_uart_read(uint8_t *data, uint16_t len, uint32_t timeout_ms) {",
235
+ `uint16_t ${name}_hal_uart_read(uint8_t *data, uint16_t len, uint32_t timeout_ms) {`,
173
236
  ` int n = uart_read_bytes(s_${name}_port, data, len, pdMS_TO_TICKS(timeout_ms));`,
174
237
  " if (n < 0) {",
175
238
  " return 0;",
@@ -177,12 +240,13 @@ function halImplUart(name, prefix, language) {
177
240
  " return (uint16_t)n;",
178
241
  "}",
179
242
  "",
180
- "void hal_delay_ms(uint32_t ms) {",
243
+ `void ${name}_hal_delay_ms(uint32_t ms) {`,
181
244
  " vTaskDelay(pdMS_TO_TICKS(ms));",
182
245
  "}",
183
246
  "",
184
247
  ].join("\n");
185
- return { path: seamPath(name, language), content };
248
+ const header = companionHeaderEsp32(name, prefix, '#include "driver/uart.h"', `void ${name}_esp32_bind(uart_port_t port);`);
249
+ return [header, { path: seamPath(name, language), content }];
186
250
  }
187
251
  function halImplCan(name, prefix, language) {
188
252
  const content = [
@@ -191,10 +255,10 @@ function halImplCan(name, prefix, language) {
191
255
  " *",
192
256
  " * Drop this beside the portable core; it fills the thin-HAL seam with the",
193
257
  " * ESP-IDF v5 TWAI (Two-Wire Automotive Interface — ESP-IDF's CAN 2.0",
194
- " * controller) driver. In your app: install and start the TWAI driver",
195
- " * (twai_driver_install + twai_start) for your TX/RX GPIOs and this part's",
196
- ` * bitrate, then call ${name}_esp32_bind() once before using the driver.`,
197
- " * The driver core stays byte-for-byte portable. See",
258
+ " * controller) driver. See the companion header",
259
+ ` * (${companionHeaderName(name)}) for the ${name}_esp32_bind() prototype —`,
260
+ " * call it once (after twai_driver_install()/twai_start()) before using the",
261
+ " * driver. The driver core stays byte-for-byte portable. See",
198
262
  " * fill_in_brief.hal_setup_todo for the bitrate/acceptance-filter config.",
199
263
  " *",
200
264
  ` * ${name}_esp32_bind() deliberately takes NO arguments: unlike I2C/SPI/UART`,
@@ -204,6 +268,7 @@ function halImplCan(name, prefix, language) {
204
268
  " * signature parity with the other targets' bind().",
205
269
  " */",
206
270
  coreInclude(name, language),
271
+ `#include "${companionHeaderName(name)}"`,
207
272
  "#include <string.h>",
208
273
  '#include "driver/twai.h"',
209
274
  '#include "freertos/FreeRTOS.h"',
@@ -214,7 +279,7 @@ function halImplCan(name, prefix, language) {
214
279
  `void ${name}_esp32_bind(void) {`,
215
280
  "}",
216
281
  "",
217
- "int hal_can_transfer(uint32_t id, const uint8_t *tx, uint8_t tx_len, uint8_t *rx, uint8_t *rx_len, uint32_t timeout_ms) {",
282
+ `int ${name}_hal_can_transfer(uint32_t id, const uint8_t *tx, uint8_t tx_len, uint8_t *rx, uint8_t *rx_len, uint32_t timeout_ms) {`,
218
283
  " twai_message_t tx_msg;",
219
284
  " memset(&tx_msg, 0, sizeof tx_msg);",
220
285
  " tx_msg.identifier = id;",
@@ -241,19 +306,23 @@ function halImplCan(name, prefix, language) {
241
306
  " return 0;",
242
307
  "}",
243
308
  "",
244
- "void hal_delay_ms(uint32_t ms) {",
309
+ `void ${name}_hal_delay_ms(uint32_t ms) {`,
245
310
  " vTaskDelay(pdMS_TO_TICKS(ms));",
246
311
  "}",
247
312
  "",
248
313
  ].join("\n");
249
- return { path: seamPath(name, language), content };
314
+ const header = companionHeaderEsp32(name, prefix, '#include "driver/twai.h"', `void ${name}_esp32_bind(void);`);
315
+ return [header, { path: seamPath(name, language), content }];
250
316
  }
251
317
  /**
252
- * Portable core + an ESP-IDF seam implementation for the same part. With
253
- * language "c" (default) the seam is `<slug>_hal_esp32.c`, unchanged from
254
- * before. With language "cpp" the seam becomes `<slug>_hal_esp32.cpp` and its
255
- * core include is `#include "<slug>.hpp"` (see coreInclude/seamPath above) —
256
- * everything else in the seam content is identical either way.
318
+ * Portable core + an ESP-IDF seam implementation + a seam companion header for
319
+ * the same part. With language "c" (default) the seam is `<slug>_hal_esp32.c`;
320
+ * with language "cpp" it is `<slug>_hal_esp32.cpp` and its core include is
321
+ * `#include "<slug>.hpp"` (see coreInclude/seamPath above) — everything else
322
+ * in the seam content is identical either way. The companion header
323
+ * (`<slug>_hal_esp32.h`) is always a plain `.h` file, in BOTH language runs.
324
+ * File order in the artifact: [core header, core source, companion header,
325
+ * seam source] — see tests/codegen/esp32.test.ts.
257
326
  */
258
327
  export function generateEsp32Driver(json, opts = {}) {
259
328
  const bus = json.protocol.bus;
@@ -264,22 +333,23 @@ export function generateEsp32Driver(json, opts = {}) {
264
333
  const prefix = prefixOf(json.metadata.part);
265
334
  const language = opts.language ?? "c";
266
335
  const base = language === "cpp" ? generatePortableCppDriver(json) : generatePortableDriver(json);
267
- const hal = bus === "SPI"
336
+ const [companionHeader, hal] = bus === "SPI"
268
337
  ? halImplSpi(name, prefix, language)
269
338
  : bus === "UART"
270
339
  ? halImplUart(name, prefix, language)
271
340
  : bus === "CAN"
272
341
  ? halImplCan(name, prefix, language)
273
342
  : halImplI2c(name, prefix, language);
343
+ const headerName = companionHeaderName(name);
274
344
  const hal_setup_todo = bus === "SPI"
275
- ? `Bring up the ESP-IDF SPI bus (spi_bus_initialize with your MOSI/MISO/SCLK pins and host), then call ${name}_esp32_bind(host, cs_gpio, clock_hz) before the first driver call. Confirm this part's SPI mode (0-3) and maximum clock speed from the datasheet's SPI timing section.`
345
+ ? `Bring up the ESP-IDF SPI bus (spi_bus_initialize with your MOSI/MISO/SCLK pins and host), then call ${name}_esp32_bind(host, cs_gpio, clock_hz) before the first driver call (prototype in ${headerName}). Confirm this part's SPI mode (0-3) and maximum clock speed from the datasheet's SPI timing section.`
276
346
  : bus === "UART"
277
- ? `Install the ESP-IDF UART driver (uart_param_config + uart_driver_install) on your chosen port with this part's baud rate/parity/stop-bits (see the datasheet's serial interface section), then call ${name}_esp32_bind(port) before the first driver call.`
347
+ ? `Install the ESP-IDF UART driver (uart_param_config + uart_driver_install) on your chosen port with this part's baud rate/parity/stop-bits (see the datasheet's serial interface section), then call ${name}_esp32_bind(port) before the first driver call (prototype in ${headerName}).`
278
348
  : bus === "CAN"
279
- ? `Install and start the ESP-IDF TWAI driver (twai_driver_install + twai_start) on your chosen TX/RX GPIOs with this part's bitrate and an acceptance filter covering its message IDs (see the datasheet's CAN bus timing/message-ID section), then call ${name}_esp32_bind() before the first driver call.`
280
- : `Bring up the ESP-IDF I2C master bus (i2c_new_master_bus with your SDA/SCL GPIOs and port), then call ${name}_esp32_bind(bus, 400000) before the first driver call. Tune ${prefix}_I2C_TIMEOUT_MS if needed.`;
349
+ ? `Install and start the ESP-IDF TWAI driver (twai_driver_install + twai_start) on your chosen TX/RX GPIOs with this part's bitrate and an acceptance filter covering its message IDs (see the datasheet's CAN bus timing/message-ID section), then call ${name}_esp32_bind() before the first driver call (prototype in ${headerName}).`
350
+ : `Bring up the ESP-IDF I2C master bus (i2c_new_master_bus with your SDA/SCL GPIOs and port), then call ${name}_esp32_bind(bus, 400000) before the first driver call (prototype in ${headerName}). Tune ${prefix}_I2C_TIMEOUT_MS if needed.`;
281
351
  return {
282
- files: [...base.files, hal],
352
+ files: [...base.files, companionHeader, hal],
283
353
  fill_in_brief: {
284
354
  ...base.fill_in_brief,
285
355
  hal_setup_todo,
@@ -1 +1 @@
1
- {"version":3,"file":"esp32.js","sourceRoot":"","sources":["../../src/codegen/esp32.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"esp32.js","sourceRoot":"","sources":["../../src/codegen/esp32.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,kFAAkF;AAClF,sEAAsE;AACtE,mFAAmF;AACnF,gFAAgF;AAChF,+EAA+E;AAC/E,0EAA0E;AAC1E,0BAA0B;AAC1B,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAC9E,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,4EAA4E;AAC5E,4EAA4E;AAC5E,uEAAuE;AACvE,+DAA+D;AAG/D,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAGjD,yEAAyE;AACzE,gEAAgE;AAChE,oEAAoE;AACpE,wEAAwE;AACxE,mEAAmE;AACnE,sEAAsE;AACtE,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,8EAA8E;AAC9E,yEAAyE;AACzE,mDAAmD;AACnD,SAAS,WAAW,CAAC,IAAY,EAAE,QAAyB;IAC1D,OAAO,aAAa,IAAI,IAAI,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,QAAyB;IACvD,OAAO,GAAG,IAAI,cAAc,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;AACjE,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,GAAG,IAAI,cAAc,CAAC;AAC/B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,oBAAoB,CAC3B,IAAY,EACZ,MAAc,EACd,WAAmB,EACnB,aAAqB;IAErB,MAAM,KAAK,GAAG,GAAG,MAAM,cAAc,CAAC;IACtC,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,+DAA+D;QAC3E,IAAI;QACJ,eAAe,IAAI,wBAAwB,IAAI,4BAA4B;QAC3E,yEAAyE;QACzE,yBAAyB;QACzB,KAAK;QACL,WAAW,KAAK,EAAE;QAClB,WAAW,KAAK,EAAE;QAClB,EAAE;QACF,oBAAoB;QACpB,cAAc;QACd,QAAQ;QACR,EAAE;QACF,WAAW;QACX,EAAE;QACF,aAAa;QACb,EAAE;QACF,oBAAoB;QACpB,GAAG;QACH,QAAQ;QACR,aAAa,KAAK,KAAK;QACvB,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,EAAE,IAAI,EAAE,mBAAmB,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;AACtD,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,0EAA0E;QACtF,IAAI;QACJ,4EAA4E;QAC5E,2DAA2D;QAC3D,OAAO,mBAAmB,CAAC,IAAI,CAAC,aAAa,IAAI,2BAA2B;QAC5E,2EAA2E;QAC3E,8CAA8C;QAC9C,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,aAAa,mBAAmB,CAAC,IAAI,CAAC,GAAG;QACzC,qBAAqB;QACrB,gCAAgC;QAChC,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,WAAW,MAAM,iBAAiB;QAClC,WAAW,MAAM,sBAAsB;QACvC,QAAQ;QACR,EAAE;QACF,oCAAoC,IAAI,OAAO;QAC/C,EAAE;QACF,yBAAyB,MAAM,mDAAmD;QAClF,6EAA6E;QAC7E,aAAa,IAAI,mEAAmE;QACpF,iCAAiC;QACjC,gDAAgD;QAChD,6BAA6B,MAAM,YAAY;QAC/C,uCAAuC;QACvC,QAAQ;QACR,sDAAsD,IAAI,QAAQ;QAClE,GAAG;QACH,EAAE;QACF,OAAO,IAAI,0EAA0E;QACrF,sBAAsB;QACtB,yEAAyE;QACzE,0CAA0C;QAC1C,sCAAsC;QACtC,OAAO;QACP,mBAAmB;QACnB,iCAAiC;QACjC,oCAAoC,IAAI,gCAAgC,MAAM,mBAAmB;QACjG,GAAG;QACH,EAAE;QACF,OAAO,IAAI,yEAAyE;QACpF,iBAAiB;QACjB,4CAA4C,IAAI,6BAA6B,MAAM,mBAAmB;QACtG,GAAG;QACH,EAAE;QACF,QAAQ,IAAI,8BAA8B;QAC1C,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,oBAAoB,CACjC,IAAI,EACJ,MAAM,EACN,gCAAgC,EAChC,aAAa,IAAI,kEAAkE,CACpF,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,0EAA0E;QACtF,IAAI;QACJ,4EAA4E;QAC5E,2EAA2E;QAC3E,MAAM,IAAI,oDAAoD;QAC9D,OAAO,mBAAmB,CAAC,IAAI,CAAC,aAAa,IAAI,2BAA2B;QAC5E,2EAA2E;QAC3E,8CAA8C;QAC9C,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,aAAa,mBAAmB,CAAC,IAAI,CAAC,GAAG;QACzC,qBAAqB;QACrB,gCAAgC;QAChC,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,gCAAgC,IAAI,OAAO;QAC3C,EAAE;QACF,2EAA2E;QAC3E,2EAA2E;QAC3E,4EAA4E;QAC5E,aAAa,IAAI,kEAAkE;QACnF,2CAA2C;QAC3C,kCAAkC;QAClC,qCAAqC;QACrC,oFAAoF;QACpF,0BAA0B;QAC1B,QAAQ;QACR,gDAAgD,IAAI,QAAQ;QAC5D,GAAG;QACH,EAAE;QACF,6EAA6E;QAC7E,kFAAkF;QAClF,OAAO,IAAI,mEAAmE;QAC9E,0BAA0B;QAC1B,8BAA8B;QAC9B,yBAAyB;QACzB,uBAAuB;QACvB,uBAAuB;QACvB,4CAA4C,IAAI,YAAY;QAC5D,GAAG;QACH,EAAE;QACF,QAAQ,IAAI,8BAA8B;QAC1C,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,oBAAoB,CACjC,IAAI,EACJ,MAAM,EACN,gCAAgC,EAChC,aAAa,IAAI,iEAAiE,CACnF,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IAC1E,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,oEAAoE;QAChF,IAAI;QACJ,4EAA4E;QAC5E,qDAAqD;QACrD,OAAO,mBAAmB,CAAC,IAAI,CAAC,aAAa,IAAI,2BAA2B;QAC5E,wEAAwE;QACxE,wEAAwE;QACxE,kEAAkE;QAClE,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,aAAa,mBAAmB,CAAC,IAAI,CAAC,GAAG;QACzC,0BAA0B;QAC1B,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,wBAAwB,IAAI,QAAQ;QACpC,EAAE;QACF,8EAA8E;QAC9E,gEAAgE;QAChE,QAAQ,IAAI,iCAAiC;QAC7C,SAAS,IAAI,eAAe;QAC5B,GAAG;QACH,EAAE;QACF,QAAQ,IAAI,sDAAsD;QAClE,0BAA0B,IAAI,kCAAkC;QAChE,GAAG;QACH,EAAE;QACF,YAAY,IAAI,oEAAoE;QACpF,iCAAiC,IAAI,+CAA+C;QACpF,kBAAkB;QAClB,mBAAmB;QACnB,OAAO;QACP,yBAAyB;QACzB,GAAG;QACH,EAAE;QACF,QAAQ,IAAI,8BAA8B;QAC1C,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,oBAAoB,CACjC,IAAI,EACJ,MAAM,EACN,0BAA0B,EAC1B,QAAQ,IAAI,gCAAgC,CAC7C,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc,EAAE,QAAyB;IACzE,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,oEAAoE;QAChF,IAAI;QACJ,4EAA4E;QAC5E,uEAAuE;QACvE,iDAAiD;QACjD,OAAO,mBAAmB,CAAC,IAAI,CAAC,aAAa,IAAI,2BAA2B;QAC5E,6EAA6E;QAC7E,8DAA8D;QAC9D,2EAA2E;QAC3E,IAAI;QACJ,MAAM,IAAI,oEAAoE;QAC9E,yEAAyE;QACzE,4EAA4E;QAC5E,0EAA0E;QAC1E,qDAAqD;QACrD,KAAK;QACL,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC;QAC3B,aAAa,mBAAmB,CAAC,IAAI,CAAC,GAAG;QACzC,qBAAqB;QACrB,0BAA0B;QAC1B,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,qEAAqE;QACrE,2CAA2C;QAC3C,QAAQ,IAAI,qBAAqB;QACjC,GAAG;QACH,EAAE;QACF,OAAO,IAAI,wHAAwH;QACnI,4BAA4B;QAC5B,wCAAwC;QACxC,6BAA6B;QAC7B,uCAAuC;QACvC,qCAAqC;QACrC,0CAA0C;QAC1C,OAAO;QACP,wEAAwE;QACxE,oBAAoB;QACpB,OAAO;QACP,yDAAyD;QACzD,mBAAmB;QACnB,OAAO;QACP,4BAA4B;QAC5B,uEAAuE;QACvE,oBAAoB;QACpB,OAAO;QACP,0CAA0C;QAC1C,wBAAwB;QACxB,sBAAsB;QACtB,OAAO;QACP,iCAAiC;QACjC,kBAAkB;QAClB,eAAe;QACf,GAAG;QACH,EAAE;QACF,QAAQ,IAAI,8BAA8B;QAC1C,oCAAoC;QACpC,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,oBAAoB,CACjC,IAAI,EACJ,MAAM,EACN,0BAA0B,EAC1B,QAAQ,IAAI,oBAAoB,CACjC,CAAC;IACF,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAmB,EACnB,OAAuC,EAAE;IAEzC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;IAC9B,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QACtE,MAAM,IAAI,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC;IACtC,MAAM,IAAI,GAAG,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAEjG,MAAM,CAAC,eAAe,EAAE,GAAG,CAAC,GAC1B,GAAG,KAAK,KAAK;QACX,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;QACpC,CAAC,CAAC,GAAG,KAAK,MAAM;YACd,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;YACrC,CAAC,CAAC,GAAG,KAAK,KAAK;gBACb,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;gBACpC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,cAAc,GAClB,GAAG,KAAK,KAAK;QACX,CAAC,CAAC,uGAAuG,IAAI,mFAAmF,UAAU,wGAAwG;QAClT,CAAC,CAAC,GAAG,KAAK,MAAM;YACd,CAAC,CAAC,uMAAuM,IAAI,gEAAgE,UAAU,IAAI;YAC3R,CAAC,CAAC,GAAG,KAAK,KAAK;gBACb,CAAC,CAAC,yPAAyP,IAAI,4DAA4D,UAAU,IAAI;gBACzU,CAAC,CAAC,wGAAwG,IAAI,uEAAuE,UAAU,WAAW,MAAM,4BAA4B,CAAC;IAErP,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC;QAC5C,aAAa,EAAE;YACb,GAAG,IAAI,CAAC,aAAa;YACrB,cAAc;SACf;KACF,CAAC;AACJ,CAAC"}