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

港で異国を感じる佐世保、マシン語によるメモリ探検

2018/10/07
#IchigoJam #sasebo #asm 

初、佐世保。長崎県は高専の時の工場見学旅行以来。

大きい船!インドネシアから来た、トレーニング船「BIMA SUCI」 at 佐世保港


乗って、中を見ることができました。

異国が身近に感じられるっていいですね!

身近な英語を話すコンピューター、IchigoJamの英語メッセージをメモリから探してみましょう。

10 S="Syn" 20 POKE#700,0,120,112,71:'R0=[R0]:RET 30 I=24576 40 C=USR(#700,I) 50 IF C=ASC(S) IF USR(#700,I+1)=ASC(S+1) IF USR(#700,I+2)=ASC(S+2) GOTO 100 60 I=I-1:GOTO 40 100 P=I:?"ADR:";P 110 FOR K=0 TO 10 120 FOR J=0 TO 1:C=USR(#700,I):?CHR$(C);:I=I+1:J=C=0:NEXT:? 130 NEXT

Syntax error の場所が見つけて、11のエラーメッセージを表示!
20行は、asm15表記のArmマシン語で、メモリの内容を取得しています。

船で感じる世界、いいものですね!

links
- はじめてのマシン語 - IchigoJamではじめるARMマシン語その1

より速く! jig.jp 第15回定時株主総会のお土産と会長就任のお知らせ

2018/06/27
#jig #asm 

株式会社jig.jp、15回目の株主総会と取締役会。 今までの2人代表制を1トップ化し、事業展開の高速化を図り、 私は新たに設けた会長職に就任、次の15年を見据えた広域な価値創造にコミットする新体制がスタートです。

福野泰介 新肩書
株式会社 jig.jp 取締役会長(株式会社 A Inc. 取締役 / 株式会社 B Inc. 代表取締役社長)
英語表記:jig.jp co., ltd. chair Taisuke Fukuno
※オープンデータや、IchigoJamなど、事業構築中のグループ会社 B Inc. は社長継続


社内全メンバーと株主の方へ、IchigoJam 15th anniversary edition をプレゼント。
BASICのスピードが気になるならば、Armマシン語を使ってフルパワーを出し切りましょう。

Armマシン語でハローワールド
HELPコマンドでメモリマップを確認

HELP MEM MAP #000 CHAR #700 PCG #800 VAR #900 VRAM #C00 LIST

まずは画面の左上(VRAM:#900)に一文字表示させるマシン語

R3=#9 R3=R3<<8 [R3+R1]=R0 RET

からハンドアセンブルするか、asm15でアセンブルして、メモリに書き込み実行!

POKE#700,9,35,27,2,88,84,112,71 U=USR(#700,ASC("A"))

プログラミングの楽しさが伝わりづらい「ハローワールド」を、ちょっとひねって、大文字を小文字に変換するプログラムにしてみます。

R3=#9 R3=R3<<8 @LOOP R2=[R0+R1] R2-34 IF 0 GOTO @END R2+=#20 [R3+R1]=R2 R3+=1 R0+=1 GOTO @LOOP @END RET

終了記号がダブルクォート(アスキーコード34)なのがポイントです。
どんなモダンな言語でプログラミングしようとも、マシン語レベルではGOTO分岐とGOTOループが基本なのだと気がつけます。

POKE#700,9,35,27,2,66,92,34,42,4,208,32,50,90,84,1,51,1,48,247,231,112,71 U=USR(#700,"HELLO WORLD")

スペースがアットマークに変わってしまう問題に気が付きました?どう直すといいでしょう?
ヒント:Cortex-M0 Armマシン語表 (asm15表記、抜粋)と試行錯誤!
参考:はじめてのマシン語 - IchigoJamではじめるArmマシン語その1

1段ギアが上がった、スピードのjig、ツールのjig。
ミッションは不変の「利用者に最も近いソフトウェアを提供し、より豊かな社会を実現する」
これからもよろしくおねがいいたします!

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)<<8|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マシン語

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