- parser: FSM 解析器与仓颉版逐语义对齐,修 S01/S02/S04/Q05 - robot/hardvars: 六类硬件变量工厂,修 r.cj:911 重名 FIXME、Q07 倒序释放 - plugin: Python 插件替代 Lua 桥接,修 S07 三级路径查找 - hd: i2c(每fd锁 Q03/S06)/spi/servo/kalman/mpu6050(S05/Q06)/speaker(S03 实声) - modules: PCA9685 与 Lua 版逐字节对齐;ADS1115 重写(experimental);ADS1256 空桩 - tests: 42 项 pytest 全绿(Mock 总线 journal 断言) - CLI: --dry-run / --test roundtrip / --verbose;运行时零第三方依赖
43 lines
1.2 KiB
Python
43 lines
1.2 KiB
Python
"""SPI 总线插件 —— 与 bot4cj/modules/SPI.lua 逐语义对齐
|
||
|
||
@SPI 块元数据:name / path / spi_mode / bits / speed / delay
|
||
build 打开并配置 spidev;call 返回 {"fd": fd}(供其他块引用展开);
|
||
destroy 关闭。模块级全局 _fd 即设备私有状态
|
||
(pybot 每设备加载独立模块实例,与 Lua 每设备独立状态机等价)。
|
||
"""
|
||
|
||
import logging
|
||
|
||
from pybot.hd import spi
|
||
|
||
log = logging.getLogger("pybot.modules.SPI")
|
||
|
||
_fd = -1 # 全局文件句柄(对应 SPI.lua 的 fd)
|
||
|
||
|
||
def build(ctx):
|
||
global _fd
|
||
for key in ("path", "spi_mode", "bits", "speed", "delay"):
|
||
if key not in ctx:
|
||
return {"result": "ERR", "message": f"Invalid Arguments: {key}"}
|
||
log.info("SPI build parameters: %s", ctx)
|
||
_fd = spi.open_dev(ctx["path"])
|
||
if _fd <= 0:
|
||
return {"result": "ERR", "message": "Failed to open SPI file"}
|
||
spi.setup(_fd, int(str(ctx["spi_mode"]), 0),
|
||
int(ctx["bits"]), int(ctx["speed"]))
|
||
return {"result": "OK", "fd": _fd}
|
||
|
||
|
||
def call(ctx):
|
||
return {"fd": _fd}
|
||
|
||
|
||
def destroy(ctx):
|
||
global _fd
|
||
log.info("SPI destroy, fd=%d", _fd)
|
||
if _fd > 0:
|
||
spi.close_dev(_fd)
|
||
_fd = -1
|
||
return {"result": "OK"}
|