前回では結局CWとCCWを切り替えることが出来なかった。
色々やってみたのだが、1step単位で指定してCW/CCWを切り替えるコードはとりあえず不可能という結論に至った。
理由は次の2つ
-
スクラッチレジスタが不足する
上記機能を実現するためには残りstep数、CW/CCWのフラグ、現在のstep位置の3つのレジスタが必要であるが
スクラッチレジスタはx,yの2つしかなく、ビット演算ができないためx,yを分割して使うことも不可能であるためレジスタが不足する -
インストラクションメモリが不足する
スクラッチレジスタを使わずにjmpだけで無理やり実装することもインストラクションメモリが無限であれば不可能ではない
(前回のように各step毎にpull,outを使って現在のstep数とプログラムカウンタを結びつける)
しかし、実際実装するとインストラクションメモリが全く足りない(2~3倍程度あればいけそう)
諦めて何もしないというのも癪なので、4step単位での指示でやってみる。
from rp2 import PIO, StateMachine, asm_pio
import time
from machine import Pin
@asm_pio(set_init=(PIO.OUT_LOW, PIO.OUT_LOW, PIO.OUT_LOW, PIO.OUT_LOW), out_shiftdir=PIO.SHIFT_LEFT, autopull=False)
def cw_ccw():
wrap_target()
pull()
out(y, 1)
out(x, 31)
label("continue")
jmp(not_y, "cw")
jmp("ccw")
label("return")
jmp(x_dec, "continue")
wrap()
label("cw")
set(pins, 0b1001)[3]
set(pins, 0b0011)[3]
set(pins, 0b0110)[3]
set(pins, 0b1100)[3]
jmp("return")
label("ccw")
set(pins, 0b1100)[3]
set(pins, 0b0110)[3]
set(pins, 0b0011)[3]
set(pins, 0b1001)[3]
jmp("return")
cw_ccw = StateMachine(0, cw_ccw, freq=2000, set_base=Pin(2))
cw_ccw.active(1)
cw_ccw.put(0x100) # CW
time.sleep(5)
cw_ccw.put((0b1 << 31) + 0x100) # CCW
time.sleep(5)
cw_ccw.active(0)
最上位ビットをyに割り当ててCW/CCWフラグとしている。
これで下(ステートマシン)に指示を丸投げして自分(CPU)は寝ている、しかも部下の仕事が終わったことに起きるまで気づかないというダメ上司ムーブが完成した。
指示が適当(分解能1/4)なところや報告させずに進捗管理をしないというところもダメさを表していて憎らしいかわいいやつである。
次回はこのダメ上司をちょっとはマシにしてみようかと思う。