2008/05/24

PICの小技: ブロックif

PICのアセンブラで条件分岐の処理を書くのって大変ですね。
条件を何重にも「否定」で考えないといけないし、
いちいちユニークなラベルを作るのもめんどくさいし、
elseがあったり多重になってくると、もうワケ分かりません。
Cみたいに if ... { ... } って書けると便利なんだけどなぁ...

実は、MPASMのマクロだけで、それっぽいことができるんです。
; マクロで使う変数の初期化
variable _BLK_count = 0
variable _BLK_depth = 0

; ifの素。条件スキップ命令と組み合わせて使う
if_n_ macro
_BLK_count++
_BLK_depth++
_BLK_stack#v(_BLK_depth) = _BLK_count
goto _BLK_label#v(_BLK_count)
endm

; elseブロック。あってもなくても良い
_else_ macro
goto _BLK_label#v(_BLK_stack#v(_BLK_depth)+1000)
_BLK_label#v(_BLK_stack#v(_BLK_depth)):
_BLK_stack#v(_BLK_depth) = _BLK_stack#v(_BLK_depth)+1000
endm

; ブロックの終わり
_endif macro
_BLK_label#v(_BLK_stack#v(_BLK_depth)):
_BLK_stack#v(_BLK_depth) = 0
_BLK_depth--
endm

このままでも使えますが、もっと分かりやすくするために、
分岐条件とif_n_を組み合わせたマクロを作っておくと便利です。
「スキップする条件」=「ifブロックを実行する条件」になるので、
例えば、Zフラグを条件とする場合は、こうなります。
if_z_   macro
btfss STATUS,Z
if_n_
endm

これで、こんな書き方ができるようになります。
        movf    MODE,W
xorlw 0x01
if_z_
movf N2,W
addwf N1,F
_else_
movf N1,W
if_z_
movlw 1
_endif
subwf N2,F
_endif

・インデントはお好みで。
・_else_はあってもなくてもかまいません。
・もちろん何重にもネストできます。

2008/05/17

PICの小技: Wを破壊せずにレジスタ間コピー

最近ずっとPICのアセンブラで遊んでいます。
PICで良いプログラムを書くのは、
まるでパズルを解くようなモノですね。
で、それをうまくやるマクロを書くのが、
また面白い。

たとえば、こんなのとか。
xorwf SRC,W
movwf DST
xorwf SRC,W
xorwf DST,F
これでSRCからDSTへのコピーができます。
このとき、Wを経由して処理しているにもかかわらず、
結局Wの内容は変化しない、というのがミソ。
したがって、Wの値を保持しておく必要がある場合でも使えます。
必要な命令数は、普通にWを退避してコピーするのと同じですが、
この方法だと退避先の心配をしなくて良いので便利です。

コピー元がリテラルの場合も同様。
xorlw DATA
movwf DST
xorlw DATA
xorwf DST,F
リテラルを2回使いますが、マクロ化すれば特に問題ないでしょう。
というか、マクロ化しないと読みにくくてしょうがないですね。

2008/05/06

1.5VでLED

今度は100Vじゃなくて1.5Vです。
とりあえず簡単そうなのを作ってみました。




HT7733Aで3.3Vに昇圧して白LEDを点灯させます。
簡単にするために部品をいくつか省略しました。
電圧が低めなので、LEDの電流制限抵抗もなしです。







小さく作って電池ケースにくっつけました。
固定と絶縁をかねてエポキシで固めたら、
なんだか微妙にグロい感じの仕上がりに。
思ってたのとちがうぞ。。







裏側に小さなスイッチが付いています。
押したらONですが、ずっと押してなくても、
普通の向きで置いたら自重でONになります。