firmwareloop 0.1.1__tar.gz → 0.1.3__tar.gz
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.
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/PKG-INFO +3 -3
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/README.md +2 -2
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/firmwareloop.egg-info/PKG-INFO +3 -3
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/pyproject.toml +1 -1
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/__init__.py +1 -1
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/fw_mcp_server.py +114 -8
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/logic_decode.ps1 +1 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/ndtdbg_bridge.ps1 +6 -4
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/setup-agent-mcp.ps1 +2 -2
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/LICENSE +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/firmwareloop.egg-info/SOURCES.txt +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/firmwareloop.egg-info/dependency_links.txt +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/firmwareloop.egg-info/entry_points.txt +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/firmwareloop.egg-info/requires.txt +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/firmwareloop.egg-info/top_level.txt +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/setup.cfg +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/acceptance-scenario.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/build.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/can.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/check-qoder-mcp.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/common/build-backends.psm1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/common/fw.psm1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/common/uart_probe.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/doctor.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/flash.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/instrument_cli.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/lib/__init__.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/lib/instruments.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/lib/ndtdbg.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/logic_capture.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/ndtdbg_cli.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/reset.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/sigrok_csv_to_fwloop.py +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/test-backends.ps1 +0 -0
- {firmwareloop-0.1.1 → firmwareloop-0.1.3}/tools/test.ps1 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firmwareloop
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
|
|
5
5
|
Author-email: WeilinZhang <19523330249@163.com>
|
|
6
6
|
License: MIT
|
|
@@ -338,7 +338,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
338
338
|
├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
|
|
339
339
|
├── demo-make/ 示例固件(Make;构建测试载体)
|
|
340
340
|
├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
|
|
341
|
-
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.
|
|
341
|
+
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.3)
|
|
342
342
|
├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
|
|
343
343
|
├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
|
|
344
344
|
├── CLAUDE.md Claude Code CLI 指南
|
|
@@ -348,7 +348,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
348
348
|
|
|
349
349
|
---
|
|
350
350
|
|
|
351
|
-
## 能力验证状态(v0.1.
|
|
351
|
+
## 能力验证状态(v0.1.3)
|
|
352
352
|
|
|
353
353
|
> 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
|
|
354
354
|
> `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
|
|
@@ -310,7 +310,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
310
310
|
├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
|
|
311
311
|
├── demo-make/ 示例固件(Make;构建测试载体)
|
|
312
312
|
├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
|
|
313
|
-
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.
|
|
313
|
+
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.3)
|
|
314
314
|
├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
|
|
315
315
|
├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
|
|
316
316
|
├── CLAUDE.md Claude Code CLI 指南
|
|
@@ -320,7 +320,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
320
320
|
|
|
321
321
|
---
|
|
322
322
|
|
|
323
|
-
## 能力验证状态(v0.1.
|
|
323
|
+
## 能力验证状态(v0.1.3)
|
|
324
324
|
|
|
325
325
|
> 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
|
|
326
326
|
> `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firmwareloop
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
|
|
5
5
|
Author-email: WeilinZhang <19523330249@163.com>
|
|
6
6
|
License: MIT
|
|
@@ -338,7 +338,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
338
338
|
├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
|
|
339
339
|
├── demo-make/ 示例固件(Make;构建测试载体)
|
|
340
340
|
├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
|
|
341
|
-
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.
|
|
341
|
+
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.1.3)
|
|
342
342
|
├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
|
|
343
343
|
├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
|
|
344
344
|
├── CLAUDE.md Claude Code CLI 指南
|
|
@@ -348,7 +348,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
348
348
|
|
|
349
349
|
---
|
|
350
350
|
|
|
351
|
-
## 能力验证状态(v0.1.
|
|
351
|
+
## 能力验证状态(v0.1.3)
|
|
352
352
|
|
|
353
353
|
> 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
|
|
354
354
|
> `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.1.
|
|
3
|
+
fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.1.3).
|
|
4
4
|
|
|
5
5
|
Exposes high-level firmware engineering and hardware management tools to AI Coding
|
|
6
6
|
Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, Cursor) via the Model Context
|
|
@@ -18,6 +18,7 @@ Tools provided:
|
|
|
18
18
|
- fw_ndtdbg_measure: NdtBox pressure-sensor data stream polling over IIC (ndtdbg_cli.py)
|
|
19
19
|
- fw_ndtdbg_read_reg: NdtBox IIC register read (ndtdbg_cli.py)
|
|
20
20
|
- fw_ndtdbg_write_reg: NdtBox IIC register write, double-gated (ndtdbg_cli.py)
|
|
21
|
+
- fw_ndtdbg_capture_seq: NdtBox register sequence + concurrent I2C capture for waveform evidence (ndtdbg_cli.py)
|
|
21
22
|
- fw_logic_capture: Logic analyzer protocol capture (logic_capture.ps1)
|
|
22
23
|
- fw_logic_decode: Logic analyzer protocol decoding & assertion (logic_decode.ps1)
|
|
23
24
|
- fw_get_evidence: Read structured audit run evidence (artifacts/runs/)
|
|
@@ -305,6 +306,71 @@ def handle_fw_ndtdbg_write_reg(args: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
305
306
|
return res
|
|
306
307
|
|
|
307
308
|
|
|
309
|
+
def handle_fw_ndtdbg_capture_seq(args: Dict[str, Any]) -> Dict[str, Any]:
|
|
310
|
+
"""单次调用内并发: 逻辑分析仪抓取与 NdtBox 寄存器序列同时进行。
|
|
311
|
+
|
|
312
|
+
MCP 工具调用不可并行, 串行调用无法让抓取窗口覆盖物理事务; 此工具在
|
|
313
|
+
handler 内以线程并发二者, 返回 capture 路径供 fw_logic_decode 消费。
|
|
314
|
+
"""
|
|
315
|
+
import threading
|
|
316
|
+
|
|
317
|
+
cli_script = os.path.join(REPO_ROOT, "tools", "ndtdbg_cli.py")
|
|
318
|
+
cap_script = os.path.join(REPO_ROOT, "tools", "logic_capture.ps1")
|
|
319
|
+
duration_ms = int(args.get("duration_ms", 8000))
|
|
320
|
+
writes = args.get("writes", [{"reg": "0xBE", "data": "01"}, {"reg": "0x01", "data": "BE 42"}])
|
|
321
|
+
poll_reg = args.get("poll_reg", "0x01")
|
|
322
|
+
poll_attempts = int(args.get("poll_attempts", 5))
|
|
323
|
+
readback_reg = args.get("readback_reg", "0xBE")
|
|
324
|
+
|
|
325
|
+
cap_out: Dict[str, Any] = {}
|
|
326
|
+
|
|
327
|
+
def do_capture() -> None:
|
|
328
|
+
cap_cmd = [PWSH_EXE, "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass",
|
|
329
|
+
"-File", cap_script, "-Protocol", "i2c", "-Backend", "sigrok",
|
|
330
|
+
"-DurationSec", str(duration_ms / 1000.0), "-Json"]
|
|
331
|
+
cap_out.update(run_process(cap_cmd, timeout=duration_ms / 1000.0 + 120))
|
|
332
|
+
|
|
333
|
+
th = threading.Thread(target=do_capture)
|
|
334
|
+
th.start()
|
|
335
|
+
|
|
336
|
+
seq: Dict[str, Any] = {"writes": []}
|
|
337
|
+
try:
|
|
338
|
+
for w in writes:
|
|
339
|
+
write_cmd = [PYTHON_EXE, cli_script, "write-reg", "--addr", str(w.get("reg")),
|
|
340
|
+
"--data", str(w.get("data")), "--confirm"]
|
|
341
|
+
_ndtdbg_reg_args(args, write_cmd)
|
|
342
|
+
res = run_process(write_cmd, timeout=60)
|
|
343
|
+
seq["writes"].append({"reg": w.get("reg"), "data": w.get("data"),
|
|
344
|
+
"ok": bool(res.get("success")), "result": res if not res.get("success") else res.get("data")})
|
|
345
|
+
if poll_reg:
|
|
346
|
+
for attempt in range(poll_attempts + 1):
|
|
347
|
+
read_cmd = [PYTHON_EXE, cli_script, "read-reg", "--addr", str(poll_reg), "--len", "2"]
|
|
348
|
+
_ndtdbg_reg_args(args, read_cmd)
|
|
349
|
+
res = run_process(read_cmd, timeout=60)
|
|
350
|
+
val = (res.get("data") or {}).get("data", {}).get("hex", "")
|
|
351
|
+
seq["poll"] = {"reg": poll_reg, "attempts": attempt + 1, "hex": val,
|
|
352
|
+
"cleared": val == "00 00"}
|
|
353
|
+
if val == "00 00" or attempt >= poll_attempts:
|
|
354
|
+
break
|
|
355
|
+
import time
|
|
356
|
+
time.sleep(0.1)
|
|
357
|
+
if readback_reg:
|
|
358
|
+
read_cmd = [PYTHON_EXE, cli_script, "read-reg", "--addr", str(readback_reg), "--len", "1"]
|
|
359
|
+
_ndtdbg_reg_args(args, read_cmd)
|
|
360
|
+
res = run_process(read_cmd, timeout=60)
|
|
361
|
+
seq["readback"] = {"reg": readback_reg,
|
|
362
|
+
"hex": (res.get("data") or {}).get("data", {}).get("hex", "")}
|
|
363
|
+
finally:
|
|
364
|
+
th.join(timeout=duration_ms / 1000.0 + 180)
|
|
365
|
+
|
|
366
|
+
cap = cap_out.get("data") or cap_out
|
|
367
|
+
capture_path = None
|
|
368
|
+
if cap and isinstance(cap, dict):
|
|
369
|
+
capture_path = cap.get("capture")
|
|
370
|
+
return {"ok": bool(capture_path), "action": "capture-seq",
|
|
371
|
+
"sequence": seq, "capture": cap, "capture_path": capture_path}
|
|
372
|
+
|
|
373
|
+
|
|
308
374
|
def handle_fw_logic_capture(args: Dict[str, Any]) -> Dict[str, Any]:
|
|
309
375
|
script = os.path.join(REPO_ROOT, "tools", "logic_capture.ps1")
|
|
310
376
|
cmd = [PWSH_EXE, "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-File", script, "-Json"]
|
|
@@ -1199,6 +1265,37 @@ TOOLS_REGISTRY = {
|
|
|
1199
1265
|
},
|
|
1200
1266
|
"handler": handle_fw_ndtdbg_write_reg,
|
|
1201
1267
|
},
|
|
1268
|
+
"fw_ndtdbg_capture_seq": {
|
|
1269
|
+
"description": "One-call protocol evidence: concurrently runs a NdtBox register write sequence (default 0xBE=01, 0x01=BE 42, poll 0x01, readback 0xBE) and a 3s Saleae/sigrok I2C capture, returning the capture path for fw_logic_decode.",
|
|
1270
|
+
"inputSchema": {
|
|
1271
|
+
"type": "object",
|
|
1272
|
+
"properties": {
|
|
1273
|
+
"duration_ms": {
|
|
1274
|
+
"type": "integer",
|
|
1275
|
+
"description": "Logic capture duration in milliseconds",
|
|
1276
|
+
"default": 3000,
|
|
1277
|
+
},
|
|
1278
|
+
"writes": {
|
|
1279
|
+
"type": "array",
|
|
1280
|
+
"items": {
|
|
1281
|
+
"type": "object",
|
|
1282
|
+
"properties": {
|
|
1283
|
+
"reg": {"type": "string"},
|
|
1284
|
+
"data": {"type": "string"},
|
|
1285
|
+
},
|
|
1286
|
+
},
|
|
1287
|
+
"description": "Register write sequence (default 0xBE=01, 0x01=BE 42)",
|
|
1288
|
+
},
|
|
1289
|
+
"poll_reg": {"type": "string", "description": "Poll register until 00 00 (default 0x01)"},
|
|
1290
|
+
"poll_attempts": {"type": "integer", "description": "Max poll attempts", "default": 5},
|
|
1291
|
+
"readback_reg": {"type": "string", "description": "Read-back verification register (default 0xBE)"},
|
|
1292
|
+
"dll_dir": {"type": "string", "description": "NdtDebugTool lib directory; default from lab.yaml"},
|
|
1293
|
+
"slave_addr": {"type": "string", "description": "IIC slave address (e.g. 0xA0)"},
|
|
1294
|
+
},
|
|
1295
|
+
"additionalProperties": False,
|
|
1296
|
+
},
|
|
1297
|
+
"handler": handle_fw_ndtdbg_capture_seq,
|
|
1298
|
+
},
|
|
1202
1299
|
"fw_logic_capture": {
|
|
1203
1300
|
"description": "Capture digital protocol waveforms (I2C, SPI, UART) via Saleae / sigrok or deterministic simulator.",
|
|
1204
1301
|
"inputSchema": {
|
|
@@ -1336,7 +1433,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
1336
1433
|
},
|
|
1337
1434
|
"serverInfo": {
|
|
1338
1435
|
"name": "firmwareloop",
|
|
1339
|
-
"version": "0.1.
|
|
1436
|
+
"version": "0.1.3"
|
|
1340
1437
|
}
|
|
1341
1438
|
}
|
|
1342
1439
|
}
|
|
@@ -1428,7 +1525,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
1428
1525
|
def handle_cli_update() -> int:
|
|
1429
1526
|
"""Handle `firmwareloop update` command."""
|
|
1430
1527
|
print("============================================================")
|
|
1431
|
-
print(" FirmwareLoop Auto-Updater (v0.1.
|
|
1528
|
+
print(" FirmwareLoop Auto-Updater (v0.1.3)")
|
|
1432
1529
|
print("============================================================")
|
|
1433
1530
|
|
|
1434
1531
|
is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
|
|
@@ -1526,7 +1623,16 @@ def upsert_qoder_mcp_json(mcp_path: str, servers: Optional[Dict[str, Any]] = Non
|
|
|
1526
1623
|
mcp_servers = data.get("mcpServers")
|
|
1527
1624
|
if not isinstance(mcp_servers, dict):
|
|
1528
1625
|
mcp_servers = {}
|
|
1529
|
-
|
|
1626
|
+
# Merge per-entry (not whole-key replace): keep existing per-server extras
|
|
1627
|
+
# like "env" (e.g. FW_LAB_CONFIG) that this payload does not define.
|
|
1628
|
+
for name, entry in payload.items():
|
|
1629
|
+
old = mcp_servers.get(name)
|
|
1630
|
+
if isinstance(old, dict) and isinstance(entry, dict):
|
|
1631
|
+
merged = dict(old)
|
|
1632
|
+
merged.update(entry)
|
|
1633
|
+
mcp_servers[name] = merged
|
|
1634
|
+
else:
|
|
1635
|
+
mcp_servers[name] = entry
|
|
1530
1636
|
data["mcpServers"] = mcp_servers
|
|
1531
1637
|
parent = os.path.dirname(mcp_path)
|
|
1532
1638
|
if parent:
|
|
@@ -1571,7 +1677,7 @@ def configure_qoder_user_mcp(user_home: str) -> List[Dict[str, Any]]:
|
|
|
1571
1677
|
def handle_cli_setup() -> int:
|
|
1572
1678
|
"""Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, and Qoder IDE."""
|
|
1573
1679
|
print("============================================================")
|
|
1574
|
-
print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.1.
|
|
1680
|
+
print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.1.3)")
|
|
1575
1681
|
print("============================================================")
|
|
1576
1682
|
print("")
|
|
1577
1683
|
|
|
@@ -1676,7 +1782,7 @@ def handle_cli_setup() -> int:
|
|
|
1676
1782
|
def handle_cli_init() -> int:
|
|
1677
1783
|
"""Handle `firmwareloop init` command."""
|
|
1678
1784
|
print("============================================================")
|
|
1679
|
-
print(" FirmwareLoop Multi-Agent Project Initializer (v0.1.
|
|
1785
|
+
print(" FirmwareLoop Multi-Agent Project Initializer (v0.1.3)")
|
|
1680
1786
|
print("============================================================")
|
|
1681
1787
|
cwd = os.getcwd()
|
|
1682
1788
|
print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
|
|
@@ -1697,7 +1803,7 @@ def handle_cli_init() -> int:
|
|
|
1697
1803
|
|
|
1698
1804
|
|
|
1699
1805
|
def print_cli_help() -> None:
|
|
1700
|
-
print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.1.
|
|
1806
|
+
print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.1.3)
|
|
1701
1807
|
|
|
1702
1808
|
Usage:
|
|
1703
1809
|
fwloop [command] (or: firmwareloop [command])
|
|
@@ -1728,7 +1834,7 @@ def main() -> None:
|
|
|
1728
1834
|
elif cmd in ["setup", "register"]:
|
|
1729
1835
|
sys.exit(handle_cli_setup())
|
|
1730
1836
|
elif cmd in ["version", "-v", "--version"]:
|
|
1731
|
-
print("FirmwareLoop v0.1.
|
|
1837
|
+
print("FirmwareLoop v0.1.3")
|
|
1732
1838
|
sys.exit(0)
|
|
1733
1839
|
elif cmd in ["help", "-h", "--help"]:
|
|
1734
1840
|
print_cli_help()
|
|
@@ -22,6 +22,7 @@ param(
|
|
|
22
22
|
[string]$CaptureFile, # direct path to the raw CSV
|
|
23
23
|
[ValidateSet('spi', 'uart', 'i2c')]
|
|
24
24
|
[string]$Protocol, # override protocol (else read from metadata)
|
|
25
|
+
[int]$FrequencyHz = 0, # clock frequency hint (Hz); reserved for future decode validation
|
|
25
26
|
[string]$Expect, # expected decoded value (hex string or text)
|
|
26
27
|
[ValidateSet('hex', 'text')]
|
|
27
28
|
[string]$ExpectKind = 'hex',
|
|
@@ -68,7 +68,7 @@ function Parse-Hex([string]$s) {
|
|
|
68
68
|
try { $bytes[[int]($i / 2)] = [Convert]::ToByte($clean.Substring($i, 2), 16) }
|
|
69
69
|
catch { Fail "CONFIG_ERROR" "Data 含非法十六进制字符" $clean.Substring($i, 2) }
|
|
70
70
|
}
|
|
71
|
-
return
|
|
71
|
+
return ,$bytes # PS 函数返回会展开单元素数组, 一元数组符保护类型
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function Open-Device([int]$iIndex) {
|
|
@@ -103,10 +103,12 @@ function Read-Reg([uint32]$h, [int]$addr, [int]$reg, [int]$len) {
|
|
|
103
103
|
return $rb
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
-
function Write-Reg([uint32]$h, [int]$addr, [int]$reg,
|
|
107
|
-
|
|
106
|
+
function Write-Reg([uint32]$h, [int]$addr, [int]$reg, $data) {
|
|
107
|
+
# 无类型约束 + 函数内强转: 兼容标量/单元素数组/byte[] 各种传参形态 (PS5.1 会展开单元素数组)
|
|
108
|
+
$bytes = [byte[]]@($data)
|
|
109
|
+
$wb = New-Object byte[] (2 + $bytes.Length)
|
|
108
110
|
for ($i = 0; $i -lt $wb.Length; $i++) {
|
|
109
|
-
if ($i -eq 0) { $wb[0] = $addr } elseif ($i -eq 1) { $wb[1] = $reg } else { $wb[$i] = $
|
|
111
|
+
if ($i -eq 0) { $wb[0] = $addr } elseif ($i -eq 1) { $wb[1] = $reg } else { $wb[$i] = $bytes[$i - 2] }
|
|
110
112
|
}
|
|
111
113
|
if (-not (Invoke-WriteRead $h $wb (New-Object byte[] 0))) { Fail "TARGET_MISMATCH" ("IIC 写无应答 addr=0x{0:X2} reg=0x{1:X2}" -f $addr, $reg) ("{0:X2}/{1:X2}" -f $addr, $reg) }
|
|
112
114
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<#
|
|
2
2
|
.SYNOPSIS
|
|
3
|
-
Dual-Tier MCP setup and registration helper (v0.1.
|
|
3
|
+
Dual-Tier MCP setup and registration helper (v0.1.3).
|
|
4
4
|
Inspects installed AI coding agents (Qoder, Claude Code, Antigravity, Cursor)
|
|
5
5
|
and configures global MCP / skills or prints exact registration commands.
|
|
6
6
|
|
|
@@ -242,7 +242,7 @@ if ($Json) {
|
|
|
242
242
|
Write-FwJson ([pscustomobject]$report)
|
|
243
243
|
} else {
|
|
244
244
|
Write-Host "============================================================" -ForegroundColor Cyan
|
|
245
|
-
Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.1.
|
|
245
|
+
Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.1.3)" -ForegroundColor Green
|
|
246
246
|
Write-Host "============================================================" -ForegroundColor Cyan
|
|
247
247
|
Write-Host ""
|
|
248
248
|
Write-Host "[1] Google Antigravity / Gemini CLI:" -ForegroundColor Yellow
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|