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

マシン語を制すもの時間を制す「DMX512事例」 / IchigoJamでまなぶARMマシン語入門その10

2017/09/07 23:55:00
#DMX #maker #IchigoJam 

マシン語の気持ちいいところは、実行時間が正確に読めるところ。
割り込みを止めて、各命令の所要クロック数を数えることで、さまざまなデバイスとつながります。

一応動いた「DMX512対応の照明」仕様書とちょっと違った動きの謎は、オシロスコープで解けました。

照明業界の標準規格「DMX512」は、250kbpsの差動信号によるシリアル通信で、25byte〜513byteまでを一塊にデータを送る仕様です。(ケーブル加工方法
塊の始まりを示す信号などに特徴があり、stopbitもIchigoJamの標準1bitと異なるので、IchigoJamのシリアル通信を使わず、OUT1とOUT2ポートで制御することにします。

とはいっても、250kbpsとは、1bitを4μ秒で表現となかなかに高速なため、IchigoJam BASICでは追いつきませんし、C言語では細かい時間が合わせができません。 そこで登場、マシン語です!

1命令、約21nsec(21ナノ秒=1/48MHz)で動くIchigoJamのARMマシン語なら、この1bitの送信時間内に192クロック分使えるので、十分に対応できそうです。

まずはループを使って正確に待つプログラムをつくります。

@WAIT R0-=1 IF !0 GOTO @WAIT RET

ARMマシン語表を見て、必要クロック数を計算します。
R0-=1 は 1
IF !0 はジャンプする時 3、しない時 1
RET は 3
ということで、R0が1のときは5クロック、2で9、3で13・・・R0*4+1クロック分、待ちます。
R0に30000を指定すると、1/48000000*(30000*4+1)*1000=2.5m(秒)
R0に183を16bit左シフトした値で、約1秒となります。

R0=R0<<16 @WAIT R0-=1 IF !0 GOTO @WAIT RET

これをマシン語に変換して、TICKで測ってみましょう

[0]=`00000 10000 000 000 :'r0=r0<<16 [1]=`00111 000 00000001 :'r0-=1 [2]=`11010001 11111101 :'if!0goto@wait [3]=`01000111 01110000 :'ret CLT:U=USR(#800,183):?TICK() 126

おや、1秒=60のはずが2秒ちょっとかかってしまいました。
実はこの差は割り込みから来ます。IchigoJamは常時、画面出力処理を割り込み処理によって行っているので、その分遅くなってしまうわけです。

VIDEO0:CLT:U=USR(#800,183):?TICK():VIDEO1 69

だいぶ1秒に近づきました。ただ実はまだフルスピードではないのです。TICK()の値すすめるために内部でのカウントや、キーボードの割り込みなどが残っています。 完全に割り込み処理を止めるマシン語、CPSID(割込禁止)とCPSIE(割込許可)を使います。

CPSID R0=R0<<16 @WAIT R0-=1 IF !0 GOTO @WAIT CPSIE RET

アセンブル

[0]=`1011011001110010 :'CPSID [1]=`00000 10000 000 000 :'r0=r0<<16 [2]=`00111 000 00000001 :'r0-=1 [3]=`11010001 11111101 :'if!0goto@wait [4]=`1011011001100010 :'CPSIE [5]=`01000111 01110000 :'ret CLT:U=USR(#800,183):?TICK() 0

画面出力が一旦途切れて、1秒後戻ってきましたか?
TICK()の数値が0になるのは、割り込み処理が完全に止まっていた証拠です。

正確に待ち時間をコントロールすることができるようになったので、DMX512制御プログラムを作ってみます。
制御コードと24ch〜512chのデータを1byteずつ送るので、送るチャンネル数の半分を先頭に指定し、制御コード、チャンネルデータと指定することにして、マシン語プログラムを作ります。

' R0 - 開始アドレス 送信数/2、送信コード(0)、ch1、ch2・・・送信個数分 ' R1 - base address (初期はRAM offset) ' R2 - OUT value (初期はROM offset) R2=1(on) R2=2(off) ' R3 - DMX value ' R4 - loop1 ' R5 - loop2 ' R6 - #100 ' R7 - loopwait @DMX512 PUSH {LR,R4,R5,R6,R7} CPSID R0=R0+R1 R1=#50 'R1=#50010000 GPIO1 R1=R1<<8 R1+=1 R1=R1<<16 R6=#80 R6=R6<<1 R2=2 [R1+`11]L=R2 R7=4 'wait 22*192clock R7=R7<<8 R7+=29 CALL @WAIT R2=1 [R1+`11]L=R2 R7=93 CALL @WAIT R4=[R0] R4=R4<<1 R4+=1 R0+=1 @LOOP2 R2=2 [R1+`11]L=R2 R7=45 CALL @WAIT R5=1 R3=[R0] @LOOP3 R2=2 R3&R5 IF 0 GOTO @SKIP R2=1 @SKIP [R1+`11]L=R2 R7=44 CALL @WAIT R5=R5<<1 R5-R6 IF !0 GOTO @LOOP3 R2=1 [R1+`11]L=R2 R7=93 CALL @WAIT R0+=1 R4-=1 IF !0 GOTO @LOOP2 CPSIE POP {PC,R4,R5,R6,R7} @WAIT R7-=1 IF !0 GOTO @WAIT RET

asm15を使ってアセンブル。
DMX512の端子、1をGND、2をOUT1、3をOUT2へ接続。
初期設定としてOUT1が1、OUT2が0をプログラムに加えてテストします。

10 POKE#700,240,181,114,182,64,24,80,33,9,2,1,49,9,4,128,38,118,0,2,34,202,96,4,39,63,2,29,55,0,240,37,248,1,34,202,96,93,39,0,240 20 POKE#728,32,248,4,120,100,0,1,52,1,48,2,34,202,96,45,39,0,240,23,248,1,37,3,120,2,34,43,66,0,208,1,34,202,96,44,39,0,240,13,248 30 POKE#750,109,0,181,66,244,209,1,34,202,96,93,39,0,240,5,248,1,48,1,60,229,209,98,182,240,189,1,63,253,209,112,71 40 OUT1,1:OUT2,0 RUN OK POKE#800,12,0,255,0,0,255:U=USR(#700,#800) OK

CH1〜4に設定した、DMX512対応の照明「Lixadaステージライト」が青く光ったら成功です!
この照明の仕様は、1byte目に全体的な明るさ(0-127/255)や点滅(128-250)や、2〜4byte目でR/G/Bの明るさを指定するとありました。 チャンネル数は照明によって異なり、ムービングライトの場合X/Y軸の値なども合わせて指定するためチャンネル数は多くなります。

ランダムに原色を混ぜた7色をじわっと光らせ、じわっと消すプログラムはこうなります。

100 R=RND(7)+1:G=R>>1&1:B=R>>2&1:R=R&1 110 FOR I=0 TO #FF STEP 4 120 POKE#800,12,0,255,R*I,G*I,B*I 130 U=USR(#700,#800) 140 NEXT 150 FOR I=#FF TO 0 STEP -4 160 POKE#800,12,0,255,R*I,G*I,B*I 170 U=USR(#700,#800) 180 NEXT 190 GOTO 100

プロトコルのマシン語制御、うまくいかないときに便利、オシロスコープ!
Break信号の長さがちょっと長かったのでおかしかったと判明。WAITするカウントを1減らして修正完了!

信号の反射を防ぐために、ターミーターを作って接続しておくと良さそうです。(2と3を120Ω1/4Wでつなぐ)
DMX512について|サウンドハウス

DMX512に対応したスモークマシンも!
DMXに対応した自作デバイスづくりにもぜひ挑戦してみてください!

links
- 最大512chの照明コントロール!照明界の標準DMX512 x IchigoJam
- DMX512について|サウンドハウス
- "DMX512 照明"で検索 on Amazon

- 連載、IchigoJamではじめる、ARMマシン語入門
1. はじめてのマシン語
2. ハンドアセンブルで超速計算!
3. マシン語メモリアクセスで画面超速表示!
4. マシン語でLEDを光らせよう!
5. 楽しさ広がるマルチバイトメモリアクセスとスタック
6. マシン語使いこなしTIPS
7. カジュアルに使うインラインマシン語
8. アセンブラを使って楽しよう
9. マシン語で高速SPI
10. マシン語を制するもの時間を制す

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