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

IchigoJamを赤外線リモコンで簡単遠隔操作!スマートホーム実現に向けて、信号の解読にも挑戦しよう!

2018/05/06
#IchigoJam #maker #asm 

家電を自在にコントロール!赤外線リモコンで操作する家電は、IchigoJamでも制御可能。
まずは予備実験として、見えない光、赤外線を使った、IchigoJam遠隔コントロール実験から。

1コ20円の赤外線受光モジュールとブレッドボード、ワイヤー3本で、回路を作りましょう。
IchigoJam CN5の5VとGND、CN4のIN1からワイヤーで赤外線受光モジュールの3本足側へ接続します。

順番は、3本足を上にして左から5V、IN1、GNDの順。
※受光モジュールの電源は、4.7-5.3Vなので、VCC(3.3V)では動きません

つないだら、早速受光しているか実験するプログラム

1 LED !IN(1):CONT RUN

赤外線受光モジュールは普段は1、38kHzで振動する赤外線を捉えたら、0が出力されます。
IN(1)でその信号をとらえ、そのまま!演算子で反転させて、LEDに連動させています。

家のテレビや電気など適当なリモコンを向けてボタンを押すと、チカチカ点滅します。

赤外線リモコンからの信号を待って、LEDをつけるプログラムはこちら。ロボットの発進制御にも使えますね!

10 IF IN(1) CONT 20 LED1

※何もしなくてもチカチカする場合、電源のノイズを拾ってしまっているので、別の電源を使うか、新品の乾電池x3(1.6*3=4.8V)を使いましょう。ノイズ対策方法も何かあるかもしれません。

ボタンをいろいろ押し分けたり、違う家電のリモコンの信号を向けてみたりすると、長さやパターンが違うことがわかります。 この信号を解読にも挑戦してみましょう。

赤外線リモコンの38kHzで点滅する赤外線LEDを光らせるパターンの違いで信号を伝えます。その信号を見るプログラムを書いてみると

1 ?IN(1);:CONT RUN

ただ、信号が一瞬すぎてうまく区別できそうにありません。BASICでは速度が足りない時は、マシン語の出番。 マシン語で光っている時間、消えている時間を計測してみます。

10 POKE#800,112,181,114,182,7,34,18,2,138,24,0,40,51,208,80,35,27,3,1,51,27,3,1,36,164,4,254,38,0,33,0,240,37,248,1,49,33,66,28,209,29,104,0,45,247,209,228,8,0,32,0,33,0,240,26,248,1,49,33,66,17,209 20 POKE#83E,29,104,0,45,247,208,17,84,1,48,0,33,0,240,15,248,73,28,33,66,6,209,29,104,0,45,247,209,17,84,1,48,176,66,231,209,0,33,17,84,1,48,98,182,112,189,156,37,173,0,1,61,253,209,112,71,80,35 30 POKE#878,27,2,1,51,27,4,4,51,1,36,0,38,17,92,73,0,0,41,234,208,28,96,0,240,22,248,30,96,0,240,19,248,1,57,247,209,1,48,17,92,73,0,0,41,221,208,0,0,0,0,0,240,8,248,0,0,0,0,0,240,4,248,1,57,245,209 40 POKE#8BA,1,48,226,231,154,37,1,61,253,209,112,71 120 N=USR(#800,1) 130 ?"LEN:";N 140 FOR I=0 TO N-1:?PEEK(#700+I);" ";:NEXT

RUNしてリモコン信号を当ててみましょう。

71 30 10 7 11 6 11 22 10 24 10 7 10 23 10 7 10 7 10 7 9 24 9 8 9 8 9 24 9 8 9 24 10 7 9 25 9 7 10 7 9 25 9 8 9 8 8 8 9 8 9 8 9 24 9 8 9 8 9 8 8 8 9 8 9 8 9 8 8 8 9 8 9 25 8 8 9 8 9 8 9 8 9 7 9 25 9 8 9 7 9 8 9 8 9 8 9 25 8 85 68 34 9 7 10 7 9 25 9 24 9 8 9 25 8 8 9 8 9 8 9 24 9 8 9 8 8 26 8 8 9 25 8 9 8 25 8 9 8 9 8 25 8 9 8 9 8 8 8 9 8 9 8 25 8 9 8 9 8 9 8 8 8 9 8 9 8 9 8 8 8 9 8 26 7 9 8 9 8 9 8 9 8 8 8 26 8 9 8 8 8 9 8 9 8 9 8 25 8 0

いくつか見ているとパターンが見えてきます。

最初の長い部分のあと、短い点灯とそのあとの消灯時間の違いで0と1を表しているようです。 数えてみるとちょうど48コ、6byte分の信号を2回送っています。 解析できた構造はこんな感じ

ヘッダ(ON:70 OFF:30) [0(ON:8 OFF:8), 1(ON:8 OFF:24)] x 48bit(6byte) フッタ(ON:8)

※数の単位は2cycle(38kHz) - 上記を2度送信している

信号の違いを確認してみましょう。

A 001101000100101010010000010000000001000001000001 B 001101000100101010010000010000000101000001000101

家の電気のリモコンAとBで切り替えで、2bit異なることががわかります。
ボタンに合わせた動作をプログラムすれば、リモコンで遠隔操作するロボットや便利道具もできそうですね。

上記、マシン語プログラム、実はリモコン送信用プログラムも含んでいます。赤外線LEDがあればリモコン発信も実験できます。

100 INPUT"1:SEND 2:RECV ?",N 110 IF N=1 N=USR(#800,0):GOTO 100 120 N=USR(#800,1) 130 ?"LEN:";N 140 FOR I=0 TO N-1:?PEEK(#700+I);" ";:NEXT 150 GOTO 100

赤外線リモコン信号読み取り&送信用マシン語プログラム(for asm15

' IN1 - 赤外線受光モジュール / OUT1 - 赤外線LED PUSH {LR,R4,R5,R6} CPSID '割り込み禁止 R2=7 'PCGの先頭 #700 R2=R2<<8 R2=R1+R2 R0-0 IF 0 GOTO @SEND R3=#50 ' IN1 の address PIO0_10 R3=R3<<(24-(10+2)) R3+=1 R3=R3<<(10+2) ' PIO0_10 R4=1 R4=R4<<18 '初回信号オーバーフロー判定 R6=254 'オーバーフロー判定 R1=0 @BACK0 GOSUB @WAIT2526 R1+=1 R1&R4 IF !0 GOTO @END R5=[R3]L R5-0 IF !0 GOTO @BACK0 R4=R4>>(18-15) 'オーバーフロー判定変更 R0=0 '配列書き込み位置 @LOOP R1=0 @BACK1 GOSUB @WAIT2526 R1+=1 R1&R4 IF !0 GOTO @END R5=[R3]L R5-0 IF 0 GOTO @BACK1 [R2+R0]=R1 R0+=1 ' 1byteずつ R1=0 @BACK2 GOSUB @WAIT2526 R1=R1+1 R1&R4 IF !0 GOTO @END R5=[R3+0]L R5-0 IF !0 GOTO @BACK2 [R2+R0]=R1 R0+=1 ' 1byteずつ R0-R6 IF !0 GOTO @LOOP @END R1=0 [R2+R0]=R1 R0+=1 CPSIE ' 割り込み許可 POP {PC,R4,R5,R6} @WAIT2526 R5=156 ' 1cycle '(48000/38*2=2526 - overhead 14cycle - 6) / 4 = 626 (=156*4) R5=R5<<2 R5-=1 ' 1 cycle IF !0 GOTO -1 ' 分岐するとき3cycle しないとき1 - 4*loop-2 RET ' 3cycle @SEND R3=#50 ' OUT1 の address PIO1_0 R3=R3<<8 R3+=1 R3=R3<<16 R3+=`00000100 'PIO1_0 R4=1 'PIOオン用 R6=0 'PIOオフ用 'R2 データが格納されたアドレス 'R0 == 0 @ON R1=[R2+R0] R1=R1<<1 ' 2倍する R1-0 IF 0 GOTO @END @ON_LOOP [R3]L=R4 GOSUB @WAIT631 [R3]L=R6 GOSUB @WAIT631 R1-=1 IF !0 GOTO @ON_LOOP R0+=1 @OFF R1=[R2+R0] R1=R1<<1 ' 2倍する R1-0 IF 0 GOTO @END @OFF_LOOP NOP NOP GOSUB @WAIT631 NOP NOP GOSUB @WAIT631 R1-=1 IF !0 GOTO @OFF_LOOP R0+=1 GOTO @ON @WAIT631 'use R5 R5=154 ' 1cycle '(48000/38/2=631 - overhead 5cycle (+10/2) - 5) / 4 = 154 R5-=1 ' 1 cycle IF !0 GOTO -1 ' 分岐するとき3cycle しないとき1 - 4*loop-2 = 618 RET ' 3cycle

links
- はじめてのマシン語 - IchigoJamではじめるARMマシン語その1
- レゴテクニックシリーズをIchigoJamと赤外線LEDで制御する(マシン語) / Control Lego Technic by IchigoJam and IR LED
- 赤外線リモコン受信モジュール SPS-440-1(38kHz): センサ一般 秋月電子通商 電子部品 ネット通販 (70コまとめ買いで@10円!)

格安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でコントロール)

変換基板到着! IchigoJam for STM32 でも動くArmマシン語3x3キャラ描画

2018/02/21
#IchigoJam #stm #KidsIT #asm 

注文していたプリント基板(PCB)が到着、動きました!

IchigoJam for STM32
LEDをつけるけすはもちろん、IchigoJam BASICのツールやゲームはそのまま動作。
Armマシン語も、仮想RAMしか使わないものならそのまま動きます!
第3回こどもプログラミングサミット」のIchigoJamワークショップにて初お披露目!

つくりかた手順
1. 変換基板を入手(PCB発注など)
2. テスターで変換基板の回路パターンを確認(電源とGNDがショートしていないかなど)
3. CPU、STM32F030K6T6をはんだづけ(0.8mmピッチなのでLPC1114FDH28より少し簡単)
* 秋月電子で入手可能なSTM32F042K6T6でもOK
4. CPUを実装していないIchigoJamを準備(IchigoJam 完全組立キットTなど)
5. 変換基板をCPUとして接続(ピンヘッダーではんだづけや、抜き差しできるようになどお好みで)
6. USBシリアルを使い、STM用のファームウェア、IchigoJam BASICをstm32writerを使って書き込みます
* ファームウェアはIchigoJam-FANにてβ公開予定、書き込み時に接続待ちがでた場合、RESETピンを一瞬GNDに

変換基板とSTM32F030K6T6。

ミニテクニック
IchigoJam BASIC、GOTOを使わないFORコマンドを使ったエルチカ無限ループ。

FOR I=0 TO 1 STEP 0:LED A:WAIT10:A=1-A:NEXT

キャラクター9つで3x3サイズの大きなキャラとして表示する、Armマシン語。
配列の先頭2つで座標を指定して、9文字分の文字列を渡すと表示します。

10 POKE#700,8,68,8,35,27,2,11,68,26,136,89,136,128,51,128,51,19,68,73,1,11,68,3,33,2,120,26,112,66,120,90,112,130,120,154,112,3,48,32,51,1,57,245,209,112,71 20 LET[0],RND(30),RND(20):U=USR(#700,"ABCDEFGHI") 30 GOTO 20

asm15でアセンブルできるプログラムはこちら
(R1を使った仮想メモリアドレスを物理メモリアドレスへ変換がポイント)

R0+=R1 R3=8 R3=R3<<8 R3+=R1 R2=[R3]W ' [0]=X R1=[R3+1]W ' [1]=Y R3+=128 R3+=128 R3+=R2 R1=R1<<5 R3+=R1 R1=3 @LOOP R2=[R0] [R3]=R2 R2=[R0+1] [R3+1]=R2 R2=[R0+2] [R3+2]=R2 R0+=3 R3+=32 R1-=1 IF !0 GOTO @LOOP RET

高速化したい時、メインループの一番内側から順にマシン語化してみましょう
Armマシン語入門

レジスタ不足に上位レジスタとスタック操作 / IchigoJamではじめるArmマシン語その12

2018/02/17
#IchigoJam #asm 

Armマシン語でWS2812Bマトリクスの表示ドライバのようにちょっと大きめのプログラムをつくると陥るレジスタ不足。 この時の、対処方法は2つ。上位レジスタとスタックです。

1. 上位レジスタを活用する
Arm Cortex-M0には、R0〜R15まで16コのレジスタ、R8〜R15は使える命令が5コに制限されますが、カウンタの回数チェックや、割り算ルーチンのポインタを格納しておくなど用途を選べば活用できます。(Cortex-M0 Armマシン語表より)

Rd=Rm Rd+=Rm Rn-Rm GOTO Rm GOSUB Rm

R8〜R11: 呼び出し元に帰る前に際には元に戻す必要がありますが自由に使えます。
R12: 破壊してOK。自由に使えます。
R13: スタックレジスタで、スタックに積んである一番上を指すポインタです。
R14: 呼び出し元のアドレスが入ったリンクレジスタ、GOSUBで呼び出す際に更新されます。
R15: プログラムカウンタ、実行中のアドレスの2つ先(4byte先)を指すポインタです。

上位レジスタをカウンタの回数チェックに使う(R0に指定した数までカウント)

R12=R0 R0=0 R0+=1 R0-R12 IF !0 GOTO -2 RET

上位レジスタを使った割り算(R0に指定した数を7で割る R0)
※IchigoJam BASIC ver1.2からR3に除算ポインタがセットされています

R12=R3 R0=7 GOTO R12

上位レジスタを使った割り算の余り(R0に指定した数を7で割った余り R1)

PUSH {LR} R12=R3 R0=7 GOTO R12 R0=R1 POP {PC}

R8〜R11までをフルに使うためにスタックに保存する

PUSH {R4-R7,LR} R4=R8 R5=R9 R6=R10 R7=R11 PUSH {R4-R7} ' R0-R12まで使い放題 POP {R4-R7} R8=R4 R9=R5 R10=R6 R11=R7 POP {R4-R7,PC}

参考、フル活用例「IchigoJam で BASIC と C とアセンブラ速度比較と最適化あそび - Qiita
マシン語で書くと、BASICの1万6千倍も速い!

1. スタックを活用する
その5で解説したスタック、POPしなくても参照できる便利な命令があります。

※u7/u8:4byte単位
※PUSH:regsの大きいレジスタから順に、SPを減らしSPへ積む 例)PUSH {R1,R2}
※POP:regsの小さいレジスタから順に、SPから読み込みSPを増やす 例)POP {R1,R2}
※N:指定したレジスタの数、PCへPOPした場合4+Ncycles(それ以外は1+Ncycles)
Cortex-M0 Armマシン語表 (asm15表記、抜粋)

SPは、R13の別名です。SPのアドレスには最後に積んだ値が入っています。+1で2番目、+2で3番目とアクセス可能です。 WS2812Bのパレットドライバをこれを利用して作っています。

' 配列の物理アドレスをPUSHしておく R2=8 R2=R2<<8 R2+=R1 PUSH {R2-R7,LR} ' 中略 ' R1をスタックに退避し、スタック2番目、配列のアドレスを取得 PUSH {R1} R1=[SP+1]L R1+=R3 ' 中略 POP {R1} ' 中略 POP {R2-R7,PC}

スタックへの書き込みも移動も自由自在ですが、ちょっと間違うとすぐ暴走しちゃいます。


Cortex-M0 Armマシン語表 (asm15表記、抜粋)」(PDF)

参考に、WS2812Bの32x8マトリクスのパレット対応ドライバのArmマシン語 asm15表記プログラムの全文です。

' OUT1用 WS2812B 32x8 @OUTを変更でOUT1-4で変更可能、#800に3byteパレット最大64色パレット、R, G, B(キャラクターコード、"0"=48から順番) ' R0 - data count ' R1 - data address #900(VRAM)から1byte 1pixel = 1color palette #800 ' R2 - temp OUT value 0/#FF, & 15 ' R3 - data value, temp ' R4 - GPIO address ' R5 - bit count ' R6 - wait count buf ' R7 - wait count ' R12 - increment or decrement address @WS2812B R2=8 R2=R2<<8 R2+=R1 PUSH {LR,R2,R4,R5,R6,R7} CPSID R0=0 R4=9 R4=R4<<8 R1=R1+R4 R4=1 R12=R4 R4=[@OUT]L @LOOP_DATA R3=[R1] ' palette R3-=48 R2=63 R3&=R2 R3=R3<<1 PUSH {R1} R1=[SP+1]L R1=R1+R3 R3=[R1] ' G R3=R3>>4 GOSUB @SEND_BYTE R3=[R1]W ' R R3=R3>>8 GOSUB @SEND_BYTE R3=[R1] ' B R2=15 R3&=R2 GOSUB @SEND_BYTE POP {R1} R1+=R12 R0+=1 R2=31 R0&R2 IF !0 GOTO @LOOP_DATA R2=R0>>5 R2-8 IF 0 GOTO @END R1+=31 R3=1 R5=-R3 R12=R5 R2&R3 IF !0 GOTO @LOOP_DATA R1+=2 R12=R3 GOTO @LOOP_DATA @END CPSIE POP {PC,R1,R4,R5,R6,R7} @SEND_BYTE R5=#80 ' R3+=2 ' offset @LOOP_BIT R2=#FF [R4]L=R2 R7=3 '(3*4+1)=13 <- 16.8+-7.2 R6=9 '(9*4+1)=37 <- 43.2+-7.2 R3&R5 IF 0 GOTO @SKIP_LOOP_BIT R7=9 '(9*4+1)=37 <- 43.2+-7.2 R6=3 '(3*4+1)=13 <- 16.8+-7.2 @SKIP_LOOP_BIT R7-=1 'wait R7*4+1 clock IF !0 GOTO -1 R2=0 [R4]L=R2 R6-=1 'wait R6*4+1 clock IF !0 GOTO -1 R5=R5>>1 IF !0 GOTO @LOOP_BIT RET @OUT DATA L #50010004

@LOOP_DATAで、#900の画面を読み取り、48=ASC("0")を引き、63でアンドをとって64色パレットとしています。[0]から[63]までの配列に入った、RGB、各4bitを@SEND_BYTEを呼び出し送信しています。

@SEND_BYTE内のR7とR6を使ってシリアル信号のタイミングは仕様に収まるようにしていますが、短い方を1、長い方を5まで短縮が可能でした。(個体によるかもしれないので要確認)

対応強化したasm15用Armアセンブラ「asm15 assembler」を使ってIchigoJamで動かしましょう。
Armマシン語表を使ってハンドアセンブルしてもOKです!

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

生きていたZ80!? 国産8bit/16bit CPU、RL78のマシン語はほぼZ80

2018/01/20
#asm #MSX 

小学生の頃、MSXの投稿されてすごいゲームが使っていたZ80マシン語に憧れ、挑戦したハンドアセンブル。
16進数で、#CD = サブルーチンのCALL、#C9 は、RET(サブルーチンから戻る)、#00 はNOP(何もせずスキップ)くらいは、ずっと覚えているまま。

国産ルネサスの8bit/16bit CPU、RL78用IchigoJamの移植も進む中、Z80 to RL78 converterを考えてみる。

RL78 ファミリ ユーザーズマニュアル ソフトウェア編」を見てみると、懐かしいレジスタ群!

A, B, C, D, E, H, Lという8bitレジスタ構成はZ80とほぼいっしょ。Xレジスタという、AXと合わせて16bitにできるレジスタや、1Mbyteまでのメモリ空間を扱うための、ES、CSレジスタを使うあたりに成長したZ80の姿を見た気がして感動できる。

RL78は16bit CPUと分類されているが、厳密にはRL78/G10のS1コアは8bit CPU、G13など一般ライン用S2コアは16bit、G14のS3コアは更に乗除算積和演算命令が加わっている。そんなこと言いながら本当は全部8bit CPUなんじゃないかと思ったが、レジスタを16bitとして使う命令に必要なクロックが、S1コアは2clock、S2/S3コアは1clockになっているので、確かにS2/S3は16bit CPUっぽい。 Z80の上位互換CPU、R800を積んだMSXturboRみたいなものだと思うと、一層愛着が湧いてくる。

命令表は下記のような感じでこれもまた馴染みやすい。

「命令マップ (1st MAP)」
RL78 ファミリ ユーザーズマニュアル ソフトウェア編に複数バイト命令用マーク追記

さすがにバイナリ互換ではないが、Z80のCALL:CD nn nn → FD nn nn、RET:CC → D7、NOP:00 → 00。など、ほぼ読み替えでいける。 Z80では、LDと表記するところ、MOV表記になっていたり、16bit操作命令が大幅増、レジスタに0や1をセットするCLRB/CLRW/ONEB/ONEWなど、進化しているなど、RL78はZ80愛好家が作ったに違いない親しみやすいマシン語となっている。

以前、逆アセンブルして解析したMSX用太字処理をするZ80のコードをRL78でかいてみると、こんな感じになる

MOVW BC,700H MOVW HL,100H @LOOP CALL 004AH MOV E,A SHL A OR A,E CALL 004DH INCW HL DECW BC MOV A,B OR A,C BNZ @LOOP RET

LD → MOV/MOVW、SRL → SHL、JR NZ → BNZ、ORはオペランドを取るのでOR A,Eなどと変わるところ、DECWでBCを1減らしてもゼロフラグが変わらないので、Aレジスタを使ってなんとかするスタイルも一緒。
*すみません、記述当初は16bitレジスタで普通にゼロフラグが使えると思っていましたが、間違ってました。Z80感覚で正しいようです。

かつてのソニーのパソコン、SMC-70の後継機、SMC-777Cの紹介記事「御三家に食い込むことはできなかった技術の結晶「ソニー SMC-777C」 - AKIBA PC Hotline!」から気になったANN表記は、asm15と同じような思想で作られていた。

BASICのようにイコールでレジスタ間転送がかけてシンプル。ローテートやジャンプ命令も短い記号を使ったところがちょっとややこしく感じちゃう点と、小文字を使って敷居が高く見えちゃう点が残念だったのかも。

コンピューターの進化に関わるエンジニアの想いが直接感じられるのが、マシン語のおもしろいところ。
RL78搭載IchigoJamが登場すれば、マシン語で伝説の16進数を直接手打ちするプログラミングするスーパーテクニックを子供に見せるチャンスかも!?

創ろう!米子高専生へプログラミングの教え方とArmマシン語講座 with IchigoJam

2018/01/09
#tottori #IchigoJam #asm 

米子高専4年生向けにIchigoJamを使ったプログラミング教え方入門。
秒間5000万回の計算速度を持つコンピューターを操る、Armマシン語入門付き!

Armマシン語で、1+1を計算

POKE#700,1,48,112,71 ?USR(#700,1) 2

+10に変更

POKE#700,10,48,112,71 ?USR(#700,1) 11

マシン語から返ってくる命令"112,71"を変更すると・・・、IchigoJamを暴走させることができます!

POKE#700,10,48,11,71
?USR(#700,1)

CPUの命令数、スピード優先、Intel x86アーキテクチャの最新はなんと3500!
消費電力の少なさ優先、Arm Cortex-M0/M0+は56とコンパクトなので学ぶなら、Armがオススメ!
最新スマホや、今後登場するArmサーバーでもIchigoJamでも同じマシン語が使えますよ。
詳しくは「連載、Armマシン語入門」「Cortex-M0 Armマシン語表(抜粋)」をどうぞ!


ゲームも音があると盛り上がる!(圧電サウンダーの接続方法紹介スライド)


LED1で、光った瞬間が一番感動した。
ゲームづくりが楽しかった。
これを1年生でやって置きたかった。
など、感触上々、ぜひ周りのこどもへ広めてみましょう!


「プログラミングを教えよう」スライド(オープンデータなので自由にカット&ペースト&加工してください)


放課後は講演会「楽しいを武器に!」


おいしかったカニ雑炊!


さすが蟹取県!


福井県の小学生向けロボコン、越前がにロボコンとのカニロボ頂上決戦もおもしろいかも。
戦う姿まぶしい小学生、動画でふりかえる「越前がにロボコン」
ASCII.jp:小学生が自作ロボットで競い合う「越前がにロボコン」が熱かった


米子高専の河野先生を代表にPCN米子立ち上げ準備がスタート!
MAKER FES 境港」など、発表の機会もありますねっ

STM32F0版IchigoJam、シリアル通信バージョンβ

2018/01/02
#IchigoJam #stm32 #asm #maker 

お気に入りCPU、Arm Cortex-M0NXP社製LPC1114シリーズと同じクラス、STMicroelectronics社製STM32F0シリーズでIchigoJamが動きました!


シリアル通信でIchigoJamを便利に使える、IJUtilitiesを使うとスクリーンを使ったゲームも動かせます!


今回は、秋月電子で手に入るSTM32F042K6T6へ書き込んだら、そのままシリアル通信で使えます。 (Nucleoにbinファイル書き込みでも動くかもしれません)

I/Oは、まだLED(PB3とPA7)のみ使えます。他、配置と機能、検討中です。

同じArmなので、USRコマンドを使ったマシン語はそのままで動きます!
ハンドアセンブルで超速計算! - IchigoJamではじめるArmマシン語その2
I/Oを使うマシン語は、LPC1114とSTM32F0、I/Oのメモリマップが違う点に注意です。

ターゲットにしている、STM32F030K6T6TRは、LPC1114と同じ48MHz/Flash32KB/RAM4KBで、1コ175円、12,000コ買えば1つあたりなんと74円

STM32で始めるC言語」で紹介した上級者向けミニマム開発環境サンプルも拡充
(GPIO/Clock変更/UART/割り込み/TIM/SPI/Flash書き込み)

ちっちゃいコンピューターをプログラミングで味方に付け、身の回りをどんどん便利にしちゃいましょう!

STM32で始めるC言語、アセンブリ言語と比べてみよう

2017/12/30
#stm32 #asm 

Mbed対応のSTM32の開発環境Nucleoでマシン語でエルチカに成功したので、次はいろいろ製品化を見越して、CPUそのままを使って作ってみます。


今回使用したのは、秋月で売っている一番安いSTM32、STM32F042K6T6です。
Arm Cortex-M0 48MHz, Flash32KB, SRAM6KB, LQFP32
LQFP32に対応するDIP化基板へはんだづけ!
0.8mmピッチなので、0.65mmピッチ28ピンのLPC1114FDH28のはんだづけより簡単です。


USBシリアルを使って書き込みます。LEDとUSBシリアルとの接続の仕方はつぎの通り。
VDDA、VDDIO2にも電源供給が必要です。BOOT0をHIGHにすることで、書き込みモードになります。
RTSが使えない場合は、リセットする際、手でジャンパー線をGNDにつなぐか、タクトスイッチをつけましょう。

3.3VVDD 1STM32F032 VSSGND
OSC_IN 231 BOOT03.3V
OSC_OUT 330 PB7
RTSNRST 429 PB6
3.3VVDDA 528 PB5
PA0 627 PB4
PA1 726 PB3
PA2 825 PA15
PA3 924 PA14
PA4 1023 PA13
PA5 1122 PA12
PA6 1221 PA11
PA7 1320 PA10TXD
PB0 1419 PA9RXD
LEDPB1 1518 PA8
GNDVSS 1617 VDDIO23.3V
USBシリアルの書き込みに、"STM32 FLASH Writer Program Using Python" stm32writerを使わせてもらいました。 stm32用プロジェクト一式をGitHub"my-first-stm32" からダウンロードし、マシン語のエルチカを書き込んでみましょう。(Mac用です。USBシリアルの設定は、makefile内を書き換えてください)

t0-asm$ make ../tools/stm32writer/stm32writer.py --port=/dev/tty.SLAB_USBtoUART --go "obj.mot" stm32writer (version: 20171231py) ...

うまくいけば書き込み終了後に自動的にエルチカが始まります。
書き込み終わっているので、USBシリアルを外して、BOOT0をGNDに接続し、3Vくらいにつなげばエルチカマシンのできあがりです!

アセンブリ言語でマシン語プログラムも楽しいですが、C言語で開発できるようにすると楽です。
例えば、48MHzへの切り替えの一部 (asm15 アセンブリ言語 from STM32エルチカ)

R0=[@RCC]L R3=R0+4 ' RCC_CFGR R1=[R3]L R2=`1111 R2=R2<<18 R2=~R2 R1&=R2 R2=4 ' PLLMUL6 R2=R2&lt;<18 R1|=R2 [R3]L=R1

これがC言語だと1行で書けます!

RCC->CFGR = (RCC->CFGR & ~(0b1111 << 18)) | (4 << 18);

t1-led-blinkがC言語でのエルチカ、t2-clockがクロックを48MHzに変更と、stm32の取説に合わせて必要最小限のプログラムになっているので、C言語の雰囲気をつかむのにのぞいてみてください。

t2-usartではstm32とのシリアル通信が一応できていますが、どうも内蔵クロックの精度が悪く計算上の値とは5%ほどずれてしまう点と、切り替えるべきAF(Alternate Function)の番号がstmのシリーズによって違う点が注意です。

STM32F0シリーズの取説は、日本語版もあって親切丁寧です!
参考資料 RM0091 リファレンスマニュアル STM32F0x1/STM32F0x2/STM32F0x8 advanced ARM-based 32bit MCUs

コンピューターをフル活用できる、マシン語とC言語の世界もぜひどうぞ!

BASICでプログラムの楽しさを知り
マシン語でコンピューターを知り
C言語でツールの便利さを知る
かつての王道、今でも通じる!?

links
- taisukef/my-first-stm32: first step of STM32F0
- IchigoJamではじめるArmマシン語

2019新卒エンジニア募集! 無いものを創ろう - asm15 supported SREC format!

2017/12/29
#jig #asm #web #stm32 

jig.jp、2019年4月入社となる新卒エントリーページをオープン!

新卒採用案内 | スマホ(Android/iPhone)アプリ・携帯アプリならjig.jp(ジグジェイピー)

コンテンツ:代表の想い、募集要項、弊社エンジニアの声、座談会、使用技術、使用言語!
jig.jp本店、鯖江の開発センターの雰囲気にビビっと来た人のエントリー、待ってます!

今日の一日一創は、JavaScriptで無いものづくり。

シンプルなアセンブリ言語を「IchigoJamではじめるArmマシン語入門」の解説用に使っていたら、作ってCC0で公開してくれたboxheadroomさんによるasm15アセンブラ! GitHubに載せてオープンソースでオープンライセンスな気軽に使えるWebアプリとして、必要に応じて成長させています。

ターゲットデバイスへのプログラムのバイナリを記述するためのフォーマット、IntelのHEXフォーマットと並ぶ、SRECフォーマット(モトローラSフォーマット、とも呼ばれる)への対応追加!

IoTに最適Arm Cortex-M0からLinuxが動いちゃうCortex-M7までのシームレス感が美しいSTM32の開発環境整備の一貫です。


asm15」 SREC format supported!!

コードを書き足し、テストして、GitHubへコミット!
検索してあえば使う、無ければ創って、共有する。
エンジニアの醍醐味です。

新卒採用案内 | スマホ(Android/iPhone)アプリ・携帯アプリならjig.jp(ジグジェイピー)

Arm社訪問! クリスマスはArmマイコン IchigoJam を使ったオリジナルツリーづくりはいかがでしょう? Armマシン語 LPC810 x WS2812B 24MHz版

2017/12/19
#IchigoJam #KidsIT #lpc810 #asm #Arm 

Arm社の日本法人、アーム株式会社を訪問。Armと言えば、に、LPC810に、Z80以来のマシン語、楽しませてもらっています!(連載、Armマシン語入門
* 今年、2017.8.1、Arm社は、ARMからArmへと社名とブランドとロゴを変更(ロゴは全部小文字)。合わせて、本ブログ表記もArmへと変更しました。

内海社長ともお会いできました!クリスマスツリーの電飾は、おなじみWS2812B、Armでコントロールされたました!

おみやげに頂いた厚い本「ディジタル回路設計とコンピュータアーキテクチャ[ARM版]
スイッチサイエンスさんも翻訳出版に協力
原著はなんとKindleでも1万円オーバーの超大作「Digital Design and Computer Architecture: ARM Edition

なぜコンピューターは計算が速いのか?」で解説したスイッチの実体、トランジスタや2進数などの基本もしっかり。

マシン語、アセンブリ言語に関する解説もArmの実アーキテクチャーに添っていて実用的!

HDLや、具体的なCPU設計にまで踏み込むマイクロアーキテクチャの章まで揃っていて読み応え抜群。

サイトからI/Oや、C言語に関する解説などをpdfで読むことができます。
Elsevier · Harris, Harris: Digital Design and Computer Architecture · Welcome

2017.12.25(月)、クリスマス。Yahoo! Japan ロッジにて、Armマイコン、IchigoJamで作るクリスマスツリーづくりワークショップを復興庁さん主催で開催!

Fw:東北Weekly 家族でプログラミングしてみよう! 東北発のほやアートをつくってみよう! | Peatix
小中学生のこどもと保護者の方が対象です。プログラミングがはじめての人でもOK!自分だけのオリジナルキラキラツリーを作りましょうっ

(おまけ)Arm訪問記念マシン語プログラム for LPC810、24MHzで800kHz正確コントロール版。

DATA L #10000400 ' stack DATA L #21 ' entry point DATA L 0, 0, 0, 0, 0 DATA L #EFFFFBDF ' VALID_CODE = 0x100000000-0x10000400-0x21 @ENTRY R0=[@SYSAHBCLKCTRL]L R1=#DF 'SWT, GPIO, I2C:off, FLASH, FLASHREG, RAM, ROM, SYS [R0]L=R1 R0=[@FLASHCFG]L R1=[R0]L R2=3 ' flash no wait: set 0b00 R2=~R2 R1&=R2 [R0]L=R1 ' clock setting 24MHz R0=[@PDRUNCFG]L ' PLL power on R1=[R0]L R2=128 R2=~R2 R1&=R2 [R0]L=R1 R0=[@MAINCLKSEL]L R1=3 ' set PLL [R0]L=R1 R0=[@SYSPLLCTRL]L R1=1 ' 0:12MHz 1:24MHz, 2:36MHz, 3:48Mhz, 4:60MHz, 7:96MHz, 8:108MHz NG [R0]L=R1 R0=[@MAINCLKUEN]L R1=0 [R0]L=R1 R1=1 [R0]L=R1 ' GPIO setting R0=[@PINENABLE0]L R1=[@PINENABLE0_DATA]L [R0]L=R1 R0=[@GPIO_DIR0]L R1=`1100 ' PIO0_2 and PIO0_3 [R0]L=R1 R4=[@GPIO_NOT0]L R2=`100 ' PIO0_2 ' WS2812B driver ' R0 - data count ' R1 - data address (G1,R1,B1,G2,R2,B2 ....) ' R2 - OUT value ' R3 - data value ' R4 - GPIO address ' R5 - bit count ' R7 - wait count @WS2812B R0=15 R1=@DATA_LED @LOOP_DATA R5=#80 R3=[R1] @LOOP_BIT [R4]L=R2 R3&R5 IF !0 GOTO @ONE @ZERO ' 10-20clock R7=2 ' wait 2*3 = 6clock R7-=1 IF !0 GOTO -1 NOP [R4]L=R2 R7=3 ' wait 3*3 = 9clock R7-=1 IF !0 GOTO -1 GOTO @JOIN @ONE ' 20-10clock R7=5 ' wait 5*3 = 15clock R7-=1 IF !0 GOTO -1 NOP [R4]L=R2 NOP @JOIN R5=R5>>1 IF !0 GOTO @SKIP2 ' 7clock == 1 R1+=1 R0-=1 IF !0 GOTO @LOOP_DATA GOTO @END @SKIP2 NOP NOP NOP GOTO @LOOP_BIT @END R7=[@WAIT_N]L R7-=1 'wait R7*3+1 clock IF !0 GOTO -1 GOTO @WS2812B ' init @SYSAHBCLKCTRL DATA L #40048080 @FLASHCFG DATA L #40040010 @PINENABLE0 DATA L #4000C1C0 @PINENABLE0_DATA DATA L #FFFFFFBF @GPIO_DIR0 DATA L #A0002000 @GPIO_NOT0 DATA L #A0002300 ' clock setting @MAINCLKSEL DATA L #40048070 @MAINCLKUEN DATA L #40048074 @SYSPLLCTRL DATA L #40048008 @PDRUNCFG DATA L #40048238 ' WS2812B @WAIT_N DATA L 4000000 @DATA_LED DATA B 10,0,0, 0,10,0, 0,0,10, 10,0,10, 0,10,10

正確に10clockと20clockに合わせているので、きれいな800kHzの波形がでているはず!
Flashのwait stateを0にしながら、24MHzが正しいのかはちょっと謎ですが、動いてはいるようです。
asm15 アセンブリ言語、アセンブルは、asm15 Assembler でどうぞ!

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