32 lines
1.3 KiB
Plaintext
32 lines
1.3 KiB
Plaintext
;
|
|
; bus_watch.pio — I2C 总线被动边沿捕获(RP2040 PIO)
|
|
; ==================================================
|
|
; 思路同 pico-examples 的 logic_analyser: 硬件只做最难的"确定性捕获"
|
|
; (电平变化即压入 FIFO), 协议解码(I2C 状态机)留给 CPU——与 PC 端
|
|
; i2cdec.py 共享同一套算法语义(源自 I2C-Inject 真机验证的
|
|
; i2c_sniff_decode.py)。
|
|
;
|
|
; 接线约定(沿用 I2C-Inject): GP8=SDA, GP9=SCL, 共地, 不加上拉,
|
|
; 纯输入不驱动(开漏总线零干扰)。
|
|
; 引脚映射: in_base = GP8 → ISR/X/Y 的 bit0=SDA bit1=SCL。
|
|
;
|
|
; 每个 FIFO 字 = 新电平值(0..3)。时间戳由 CPU 取(边沿间隔 ≥ 500ns,
|
|
; 核1 专职轮询, 抖动远小于 1us)。
|
|
; 环形轮询 5 条指令 @250MHz = 20ns/圈, 可分辨 ~40ns 毛刺;
|
|
; push noblock: FIFO 满则丢当前沿(Y 已更新, 后续沿仍连续可解,
|
|
; CPU 侧以"双位同变"启发式统计疑似丢沿)。
|
|
|
|
.program bus_watch
|
|
|
|
top:
|
|
mov isr, null ; ISR 清零(低 2 位待填)
|
|
in pins, 2 ; ISR[1:0] = SCL<<1 | SDA
|
|
mov x, isr
|
|
jmp x != y, changed ; 电平有变 -> 送出
|
|
jmp top ; 无变 -> 继续盯
|
|
|
|
changed:
|
|
mov y, x ; 先更新基线(即使 push 被丢也不失步)
|
|
push noblock ; 送出新电平(FIFO 满则丢弃)
|
|
jmp top
|