PICアセンブラ#02-1行で比較
マイコン好きの多くの人が2011年にガイガーカウンターを何種類も自作したかもしれませんが、筆者もその一人です。
その年の夏ごろまではGMT(ガイガーミュラー管)入手が突然難しくなってしまい、様々な代替品や自作品をテスト。筆者の傑作としてはGT双三極管のプレート間に高圧をかけて利用することなどいろいろ。段々進歩し樹脂パイプにアルゴンガスを詰め自作したり。しかしプラトー電圧範囲などで、なかなか満足に至りません。遂にフォトダイオードを使いますが、β線が検知できないのが不満。
そうこうするうち、海外のネットで良いGMTがたくさん入手できるようになりました。それを使った作品の1例は上で、8ピンPIC12F1822(信号検出、音と光表示、信号伝達)+14ピンPIC16F1823(カウント、計算、LCD表示、SDへデータ記録)。この場合は全部をアセンブラで書いているのが特徴です。
実はこれについて書こうと思っているのですが、今の手持ちの趣味の時間では書けませんので、そのうち時間が作れる時に書くことにします。
とにかく、こういうものをアセンブラで書く時は四則演算を上手にこなさなければなりません。また、表示したりSDカードに記録する場合にはどうしても10進数にしたいものです。Cで書けばいとも簡単ですが、短い信号検出には不向きなことがあり、メモリーもずっと多く必要とします。ここでわざと使った最大2Kステップのマイコンでは無理があります。もちろん性能は素晴らしいマイコンですが。
アセンブラを使い倒す(?)筆者独自のアイデアは、1バイトを百進数(ヘクト、あるいはセンテシマルと呼べばよさそう)として扱うことです。1バイトの変数に0~99しか入れないわけで、つまり、1の桁の次は百の桁、その次は万の桁という具合です。
こうやると、四則演算はほぼ筆算のとおりにやれば難なくできますし、10進数の表示やSDへの記録では加工の必要が殆どなく、ごく単純になります。このやり方にたどりついて以来、処理が簡単になりました。それほど楽ちんな「ヘクト処理」については、どこかで詳しく説明したいと思います。とはいえ、そういう演算の基礎として、大小比較をアセンブラ1行で書けるようにしておきます。これでほぼ全てが簡単になりますし間違いも起きなくなります。
これまでの記事でも少しだけ書きましたが、様々な大小比較を1つのマクロ命令で書けるようにしておきます。どんな工作にも便利ですね。例えば次のような一連のマクロの定義をプログラムの最初のほう(その命令を使うより前)に挿入するだけなのです。
;Mcompare - Comparison macros by Akira Tominaga V08-01
; CabSEL, CabSO, CalSEL, CalSO, CalEO, CalLO, CalUO
; Septemeber 17, 2018
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Comparison macros ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare A w/ B and branch to Smaller, Equal, or Larger(next statm't line)
CabSEL macro Aadr,Badr,Smladr,Eqladr
movf Badr,W ; W=B
subwf Aadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladr ; If A<B goto Smaladr
btfsc STATUS,Z ; A=B? No skip next
goto Eqladr ; If A=B goto Eqladr
; ; If A>B then next (here)
endm
;
; Compare A w/ B and branch to Smaller or Others (Equal or Larger)
CabSO macro Aoadr,Boadr,Smloadr
movf Boadr,W ; W=B
subwf Aoadr,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smloadr ; If A<B goto Smaladr
; ; If A≧B then next (here)
endm
;
; Compare A w/ literal and branch to Smaller, Equal, or Larger(next statm't)
CalSEL macro Aadd,Blite,Smladd,Eqladd
movlw Blite ; W=B
subwf Aadd,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smladd ; If A<B goto Smaladr
btfsc STATUS,Z ; A=B? No skip next
goto Eqladd ; If A=B goto Eqladr
; ; If A>B then next (here)
endm
;
; Compare A w/ literal and branch to Smaller, or Others (Equal or Larger)
CalSO macro Aado,Blito,Smlado
movlw Blito ; W=B
subwf Aado,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto Smlado ; If A<B goto Smaladr
; ; If A≧B then next (here)
endm
;
; Compare A w/ literal and branch to Equal, or Others
CalEO macro Aa,Bl,Eql
movlw Bl ; W=B
subwf Aa,W ; W=A-B
btfsc STATUS,Z ; A=B? No skip next
goto Eql ; If A=B goto Eqladr
; ; else next (here)
endm
;
; Compare A w/ literal and branch to Large, or Others
CalLO macro Aaddl,Blitel,Laddl
movlw Blitel ; W=B
subwf Aaddl,W ; W=A-B
btfss STATUS,C ; A≧B? Yes, skip next
goto $+3 ; If A<B goto Others
btfss STATUS,Z ; A=B? Yes skip next
goto Laddl ; If A>B goto Laddr
; ; If A≦B then next (here)
endm
;
; Compare A with Literal and branch to Un-equal, or Others
CalUO macro Aad,Blit,Uneql
movlw Blit ; W=B literal
subwf Aad,W ; W=A-B
btfss STATUS,Z ; A=B?
goto Uneql ; No, goto unequal
; ; If yes then next (here)
endm
マクロ命令だけなら、いくらたくさん定義しても、それを使わなければPICのプログラムメモリーを全く消耗しません。こうしておけば、これらの命令を好きな場所で何度でも使えます。ただしここで定義したマクロの場合、数値は全部0か正の場合で、負数は扱いません。
例えばAの内容とBの内容を比較して、A<BならSmallrへ、A=BならEqualrへ、A>BならLarger に行きたい場合、次のように1行で書くことができますし、間違いも起きません。展開される命令も4~6ステップだけです。
CabSEL A,B,Smallr,Equalr
Larger equ $ (この行はとくに書かなくてもOK)
AがBより大きい場合は命令の下に抜けるようにしていますから。
他の例として、Koreの中身がデシマルの99ならOnajirへ行き、違うならChigaurへ行きたい場合は次のように1行で書けます。
CalEO Kore,D'99',Onajir
Chigaur equ $ (この行はとくに書かなくともOK)
等しくない時は命令の下に抜けるようにしていますから。
3つ目の例として、Areの中身がデシマル99未満ならMadarへ行き、99に達したらKetarに行きたい場合は次のように1行で書けます。
CalLO Are,D'99',Madar
Ketar equ $ (この行はとくに書かなくともOK)
99に達したときは命令の下に抜けるようにしていますから。
上に定義した他のマクロ例の使い方も、同様ですのでお分かりいただけるかと思います。また、必要なら同様な他のマクロも定義すればよいわけです。
ではすみませんが時間切れとなりました。今回はこの辺で。
(c)2018 Akira Tominaga, All rights reserved.