福野泰介の一日一創 - create every day

格安7セグディスプレイ「LED&KEY」を使ってカチカチカウンターづくり、TM1638 x IchigoJam用マシン語SPIドライバの作り方

2018/04/14
#IchigoJam #asm 

7セグディスプレイ、LED、タクトスイッチがそれぞれ8つずつ実装済みで、AliExpressでは$1.5、Amazonでは2コで850円で売ってる謎の商品、LED&KEYを使ってカウンタづくり。 TM1638というSPIというスーファミのコントローラーなどと同様のよくある信号方式でコントロールできるとのこと!(IchigoJam(10) : Yoshiのブログより)

まずはハードウェア的にIchigoJamと接続。ちょうどいいことにIchigoJamの拡張端子CN4のVCC,GND,OUT1,OUT2,OUT3の並びで使えそうです。

裏面にピンソケット、L字ピンヘッダー、ピンヘッダーをはんだづけして、準備完了。
STBをOUT1で、CLKをOUT2で、DIOをOUT3でコントロールします。

SPIは、指揮者がタクトを振った時に楽譜を見てその音を鳴らす的な通信方式なので、BASICでも実現できます。ただ、パッとすばやく書き換えたいときにはマシン語の出番です。

10 POKE#700,112,181,12,24,24,75,25,166,143,32,0,34,90,96,0,240,32,248,1,34,90,96,64,32,0,34,90,96,0,240,25,248,1,34,90,96,192,32,0,34,90,96,0,240,18,248,8,37,32,120,48,92,98,120,210,1,16,68,0,240 20 POKE#73C,10,248,96,120,64,8,0,240,6,248,2,52,1,61,241,209,1,34,90,96,112,189,8,33,1,34,2,64,146,0,154,97,2,50,154,97,64,8,1,57,246,209,112,71,0,0,1,80,63,6,91,79,102,109,125,7,127,111 RUN

配列に表示したいパターン番号を入れて、マシン語呼び出しで表示されます。

[0]=1:U=USR(#700,#800)

こちら、ぐるぐると描画するデモプログラム

100 FORJ=1TO100 110 U=USR(#700,#800):N=7 120 [N]=[N]+1:IF[N]=10[N]=0:N=N-1:IFN>=0CONT 130 NEXT 140 WAIT30 200 FORJ=1TO20 210 FORI=0TO7:[I+8]=RND(10)+RND(4)<<8:NEXT 220 U=USR(#700,#800+16) 230 NEXT 240 WAIT30 250 GOTO100

書き込んだマシン語のデータの末尾10byte(#76C-#775)は、7セグディスプレイ用のパターンデータです。 0を小さな0に変更してみましょう

POKE#76C,#5C:U=USR(#700,#800)

元に戻す時はこちらでOK(#3F=63)

POKE#76C,#3F:U=USR(#700,#800)

オリジナルなパターンを表示したい場合は、#776以降を使って10以降の数字を指定すればOK

POKE#776,6,88,116,221,92,14,220,212 FORI=0TO7:[I]=I+10:NEXT:U=USR(#700,#800)


IchigoJam、と、ムリヤリ表記


7セグメントディスプレイのパターンづくりに作成「7seg sim
いろんな演出をしてみたり、ゲーム電卓風な遊びもできますね!
「ゲーム電卓」って何? 80年代で大人気だったものをカシオが復活

配列にいれるのも面倒な場合、マシン語へ呼び出す数を指定するだけ表示版が便利です

10 POKE#702,152,70,4,70,25,79,25,166,143,32,0,34,122,96,0,240,33,248,1,34,122,96,7,37,64,32,0,34,122,96,0,240,25,248,1,34,122,96,192,32,40,68,40,68,0,34,122,96,0,240,16,248,32,70,10,33,192,71,4,70 20 POKE#73E,8,70,48,92,0,240,8,248,0,32,0,240,5,248,1,34,122,96,1,61,226,213,8,33,1,34,2,64,146,0,186,97,2,50,186,97,64,8,1,57,246,209,112,71,0,0,1,80,63,6,91,79,102,109,125,7,127,111 RUN

使い方は簡単、数を入れてマシン語を呼び出すだけ(12345を表示する場合)

U=USR(#700,12345)

プログラム領域の末尾(#FFE-#FFF)を使って数を保存するテクニックを使い、電源を切っても途中からカウントできる、カウンターを作ってみました。

10 POKE#702,152,70,4,70,25,79,25,166,143,32,0,34,122,96,0,240,33,248,1,34,122,96,7,37,64,32,0,34,122,96,0,240,25,248,1,34,122,96,192,32,40,68,40,68,0,34,122,96,0,240,16,248,32,70,10,33,192,71,4,70 20 POKE#73E,8,70,48,92,0,240,8,248,0,32,0,240,5,248,1,34,122,96,1,61,226,213,8,33,1,34,2,64,146,0,186,97,2,50,186,97,64,8,1,57,246,209,112,71,0,0,1,80,63,6,91,79,102,109,125,7,127,111 30 N=PEEK(#FFE)|PEEK(#FFF) 40 U=USR(#700,N) 50 IF BTN() CONT 60 IF BTN()=0 CONT 70 N=N+1 80 U=USR(#700,N) 90 POKE#FFE,N>>8,N 100 SAVE 110 GOTO 50

Yoshiさんのプログラムを元に、タクトスイッチ読み込みもマシン語化してみました。
(DIOにIN3ではなくOUT3を使っている点に注意、タクトスイッチのどれかを押すとカウントアップモードになります)

10 'TM1638 15 POKE#700,18,75,8,33,1,34,2,64,146,0,154,97,2,50,154,97,64,8,1,57,246,209,112,71,12,75,128,34,18,2,154,24,17,104,6,180,4,32,65,64,17,96,0,33,0,32,0,34,154,96,26,105,138,64,210,8,16,68,2,34,154,96 16 POKE#73E,1,49,8,41,244,209,6,188,17,96,112,71,0,0,0,0,1,80 20 LET[80],#3F,#06,#5B,#4F,#66,#6D,#7D,#07,#7F,#6F,#77,#7C,#39,#5E,#79,#71 30 GSB@HELLO:OUT1,1:OUT2,0:D=7:GSB@DSPON 40 @LOOP1:N=N+1:GSB@GETKEY:[8]=K:N=N+1 50 IF K B=16:GSB@SETNUM:GSB@DSP7SEG:GSB@HELLO:GOTO@LOOP1 60 GSB@DSP7SEG:W=[0]:FORI=0TO6:[I]=[I+1]:NEXT:[7]=W:GOTO@LOOP1 70 @HELLO:LET[0],0,0,0,#76,#79,#38,#38,#3F:RTN 80 @SETNUM:W=N:FORI=7TO0STEP-1:[I]=[80+W%B]:W=W/B:NEXT:RTN 100 @DSPON:OUT1,0:U=USR(#700,#88|D):OUT1,1:RTN 110 @DSPOFF:OUT1,0:U=USR(#700,#80):OUT1,1:RTN 120 @DSP7SEG:OUT1,0:U=USR(#700,#40):OUT1,1:OUT1,0:U=USR(#700,#C0) 130 FORI=0TO7:U=USR(#700,[P+I]):U=USR(#700,[8]>>I&1):NEXT:OUT1,1:RTN 140 @GETKEY:K=0:OUT1,0:U=USR(#700,#42):FORI=0TO3:K=K|USR(#718,0)<<I:NEXT:OUT1,1:RTN

asm15マシン語のソースはこちら。

@SPIW1 R3=[@GPIO1]L R1=8 @LOOP R2=1 R2&=R0 'F=N>>I&1 R2=R2<<2 [R3+`110]L=R2 ' OUT2,0:OUT3,F R2+=2 [R3+`110]L=R2 ' OUT2,1 R0=R0>>1 R1-=1 IF !0 GOTO @LOOP @END RET @SPIR1 R3=[@GPIO1]L R2=#80 ' GPIO1DIR OUT3 to IN7 R2=R2<<8 R2=R3+R2 R1=[R2]L PUSH {R2,R1} R0=4 R1^=R0 [R2]L=R1 R1=0 R0=0 @LOOP R2=0 [R3+`10]L=R2 ' OUT2,0 R2=[R3+`100]L ' IN(7) (== OUT3) R2<<=R1 R2=R2>>3 ' ?2 R0+=R2 R2=2 [R3+`10]L=R2 ' OUT2,1 R1+=1 R1-8 IF !0 GOTO @LOOP @END POP {R2,R1} [R2]L=R1 RET @GPIO1 DATA L #50010000

SPIの書き込みと読み込み(IchigoJam BASICでOUT3,-1で入力にするとアナログ設定になるので、デジタルのまま入出力の方向をマシン語で切り替えています)

数値直接用ドライバでは、R3レジスタを使った除算を使います。

PUSH {LR} R1=10 GOSUB R3 POP {PC}

Armマシン語で10で割るテスト

POKE#700,0,181,10,33,152,71,0,189 ?USR(#700,1234) 123

割り算を呼び出すと、R1に余りが入った状態にしてくれます。

PUSH {LR} R1=10 GOSUB R3 R0=R1 POP {PC}

Armマシン語で10で割った余りを求めるテスト

POKE#700,0,181,10,33,152,71,8,70,0,189 ?USR(#700,1234) 4

これを使った数値直接表示ライブラリのプログラム。

@LEDS PUSH {R4-R8,LR} R4=R0 R8=R3 ' divide func R7=[@GPIO1]L R6=@PTN7SEG R0=#8F ' display on #88+7 R2=0 [R7+`001]L=R2 GOSUB @SPIW1 R2=1 [R7+`001]L=R2 R5=7 @SENDLOOP R0=#40 R2=0 [R7+`001]L=R2 GOSUB @SPIW1 R2=1 [R7+`001]L=R2 R0=#C0 R0+=R5 R0+=R5 R2=0 [R7+`001]L=R2 GOSUB @SPIW1 R0=R4 R1=10 GOSUB R8 R4=R0 R0=R1 R0=[R6+R0] GOSUB @SPIW1 R0=0 GOSUB @SPIW1 R2=1 [R7+`001]L=R2 R5-=1 IF !MI GOTO @SENDLOOP POP {R4-R8,PC} @SPIW1 R1=8 @LOOP R2=1 R2&=R0 'F=N>>I&1 R2=R2<<2 [R7+`110]L=R2 ' OUT2,0:OUT3,F R2+=2 [R7+`110]L=R2 ' OUT2,1 R0=R0>>1 R1-=1 IF !0 GOTO @LOOP RET @GPIO1 DATA L #50010000 @PTN7SEG DATA B #3F,#06,#5B,#4F,#66,#6D,#7D,#07,#7F,#6F

links
- はじめてのマシン語 - IchigoJamではじめるARMマシン語その1
- 54byteのスーファミコントローラドライバ、IchigoJam BASICとマシン語でつなぐ極上のコントローラ
- IchigoJam(10) : Yoshiのブログ (TM1638をIchigoJam BASICでコントロール)

Tweet
クリエイティブ・コモンズ・ライセンス
この作品は「Creative Commons — CC BY 4.0」の下に提供されています。
CC BY 福野泰介 - Taisuke Fukuno / @taisukef / アイコン画像 / プロフィール画像