MicroPython で RP2040 の PIO を使うサンプル 補足編

# `out()`に時間がかかる説

- P25に1を書けば1が読めて，0を書けば0を読めるだろうと実行させてみると，

```main.py
import machine, rp2

@rp2.asm_pio(
    out_init=rp2.PIO.OUT_LOW,
    out_shiftdir=rp2.PIO.SHIFT_RIGHT,
    in_shiftdir=rp2.PIO.SHIFT_LEFT
    )
def prog():
    pull()
    out(pins, 25)
    in_(pins, 25)
    push()

state_machine = rp2.StateMachine(
    0, prog,
    freq=10_000_000,
    out_base=machine.Pin(25),
    in_base=machine.Pin(25)
    )

state_machine.active(1)

state_machine.put(1)
print("put 1 get",state_machine.get())

state_machine.put(0)
print("put 0 get",state_machine.get())
```

期待通り動きます。デバッグや，XIAOのように引き出されていないピンを記憶用として活用できますね。

```
>>> %Run -c $EDITOR_CONTENT
put 1 get 1
put 0 get 0
>>> 
```

上記では `freq=10_000_000,` で動作させてますが，100MHzだとダメです...

```
>>> %Run -c $EDITOR_CONTENT
put 1 get 0
put 0 get 1
>>> 
```

どうやら `out()` に時間がかかるようで，100MHz動作の場合は，

```main（抜粋）.py
    out(pins, 25).delay(2)
```

と明示的に待ちを入れたら想定通り動くようになりました。

データシート等では `out()` など1クロックで動くことになっているのですが，実際に OSR を ピンに書き込んでいくのに時間がかかるようです。

# `out()` は30ポートまでかけるらしい

- 確認しました

```main.py
import machine, rp2

@rp2.asm_pio(
    out_init=(
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH,
        rp2.PIO.OUT_HIGH, rp2.PIO.OUT_HIGH
        ),
    out_shiftdir=rp2.PIO.SHIFT_RIGHT
    )
def prog():
    pull()                 # TX FIFO -> OSR
    out(pins, 30).delay(3) # OSR -> pins * bit
    in_(pins, 30)          # pins * bit -> ISR
    push()                 # ISR -> RX FIFO

state_machine = rp2.StateMachine(
    0, prog,
    out_base=machine.Pin(0),
    in_base=machine.Pin(0)
    )

state_machine.active(1)

for a in range(30):
    p=(2**32) - 1 - (1<<a)
    state_machine.put(p)
    print(f'put  {p:032b}')
    print(f'get  {(state_machine.get()):032b}')
    print()
```

実行例
```
>>> %Run -c $EDITOR_CONTENT
put  11111111111111111111111111111110
get  00111111111111111111111111111110

put  11111111111111111111111111111101
get  00111111111111111111111111111101

put  11111111111111111111111111111011
get  00111111111111111111111111111011

put  11111111111111111111111111110111
get  00111111111111111111111111110111

put  11111111111111111111111111101111
get  00111111111111111111111111101111

put  11111111111111111111111111011111
get  00111111111111111111111111011111

put  11111111111111111111111110111111
get  00111111111111111111111110111111

put  11111111111111111111111101111111
get  00111111111111111111111101111111

put  11111111111111111111111011111111
get  00111111111111111111111011111111

put  11111111111111111111110111111111
get  00111111111111111111110111111111

put  11111111111111111111101111111111
get  00111111111111111111101111111111

put  11111111111111111111011111111111
get  00111111111111111111011111111111

put  11111111111111111110111111111111
get  00111111111111111110111111111111

put  11111111111111111101111111111111
get  00111111111111111101111111111111

put  11111111111111111011111111111111
get  00111111111111111011111111111111

put  11111111111111110111111111111111
get  00111111111111110111111111111111

put  11111111111111101111111111111111
get  00111111111111101111111111111111

put  11111111111111011111111111111111
get  00111111111111011111111111111111

put  11111111111110111111111111111111
get  00111111111110111111111111111111

put  11111111111101111111111111111111
get  00111111111101111111111111111111

put  11111111111011111111111111111111
get  00111111111011111111111111111111

put  11111111110111111111111111111111
get  00111111110111111111111111111111

put  11111111101111111111111111111111
get  00111111101111111111111111111111

put  11111111011111111111111111111111
get  00111111011111111111111111111111

put  11111110111111111111111111111111
get  00111110111111111111111111111111

put  11111101111111111111111111111111
get  00111101111111111111111111111111

put  11111011111111111111111111111111
get  00111011111111111111111111111111

put  11110111111111111111111111111111
get  00110111111111111111111111111111

put  11101111111111111111111111111111
get  00101111111111111111111111111111

put  11011111111111111111111111111111
get  00011111111111111111111111111111

>>> 
```

この場合は `out(pins, 30).delay(3)` で正しく動きました。`delay` がない場合，あと1ビット転送が終わっていないようなデータとなりました。

# `sideset`は４ビットまで?

- データシートでは最大5ビットなんだけどな...

```main.py
import machine, rp2

@rp2.asm_pio(
    sideset_init=(
        rp2.PIO.OUT_LOW,
        rp2.PIO.OUT_LOW,
        rp2.PIO.OUT_LOW,
        rp2.PIO.OUT_LOW,
        rp2.PIO.OUT_LOW
        )
    )
def prog():
    nop().side(0b10000)
    in_(pins,5)
    push()
    nop().side(0b01000)
    in_(pins,5)
    push()
    nop().side(0b00100)
    in_(pins,5)
    push()
    nop().side(0b00010)
    in_(pins,5)
    push()
    nop().side(0b00001)
    in_(pins,5)
    push()

state_machine = rp2.StateMachine(
    0, prog,
    freq=100_000,
    sideset_base=machine.Pin(0),
    in_base=machine.Pin(0)
    )

state_machine.active(1)

for i in range(5):
    print(f'{(state_machine.get()):05b}')
```

実行例

```
>>> %Run -c $EDITOR_CONTENT
10000
01000
00100
00010
00000
>>> 
```

# たぶん本当のおしまい

やっぱりデータシートはすごく理解に役に立ちました。

https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf

MicroPythonとうまく融合されていて，とても面白いですね！