メモリに所有権を導入して安全性を確保するプログラミング言語「Rust」がおもしろそうです。お気に入りのJavaScriptの実行環境 Deno でも使われていることもあり、本格的に入門してみます。 今回のターゲットは、IchigoJam (Arm NXP LPC1114)です!


1. シンプルに 1+1 を計算するRustプログラム
2. エルチカ(LEDをチカチカさせるループ)
3. かわくだりゲーム in Rust!
4. CPUに書き込んでいるので、ケーブルを外しても動きます!

Rustで書くメイン関数はこんな感じです。c4ijをベースに作っていただいた rust4ij by mitsujifork して改造しながら使いました。 main関数の返り値は、IchigoJAM BASICのコンソールで表示されます。マシン語起動用のBASICコードは、Makefile内にあります。

fn main(_param:i32, _ram:i32, _rom:i32, _divfunc: fn(u32, u32) -> u64) -> i32 { return 1 + 1; }

i32は符号付き32bit整数、u32は符号なし32bit整数。fnは関数を表します。

エルチカはこんな感じ。実際には、IchigoJam用のライブラリ以外、余計なものをリンクしないような設定が6行、加わります。(src on GitHub)

fn main(_param:i32, _ram:i32, _rom:i32, _divfunc: fn(u32,u32) -> u64) -> i32 { loop { out(7, 1); wait(10); out(7, 0); wait(10); } }

led関数を定義しておくのもいいですね。コンパイル型の言語の場合、使わない関数はメモリを消費しないので、分かりやすいライブラリをいろいろ作っていくのがお得です。


ゲームもこのように作れます。IchigoJAM BASIC版C言語版Ruby版Armマシン語版とも比べてみましょう。

fn main(_param:i32, _ram:i32, _rom:i32, _divfunc: fn(u32, u32) -> u64) -> i32 { cls(); let mut x:u32 = 15; let mut score:u32 = 0; loop { locate(x, 5); putc(236 as char); locate(rnd(32), 23); putc('*'); putc(10 as char); wait(3); let c:u32 = inkey(); if c == 28 { x -= 1; } if c == 29 { x += 1; } if scr(x, 5) != 0 { break; } score += 1; } putstr(b"SCORE:\0" as *const u8); putnum(score); putc(10 as char); return 0; }

Rustの真骨頂は、メモリ管理にあり!ここまではほぼBASICやC言語などと変わらない感じですが、必要に応じてメモリを確保したり開放したりする際、Rustらしさがでてくるはず。 プログラムで7KBまで、RAMも1KBくらいはフリーで使えるので、IchigoJam BASICでは難しい大作づくりにチャレンジするのもおもしろいかも!?


MacとUSBシリアルで接続して、sector指定書き込み対応のlpc21ispを使用して、書き込みます。

LEDを付ける out(7, 1) だけのプログラムを逆アセンブルしてみました(make disasm)

Disassembly of section .data: 00000000 <.data>: 0: b580 push {r7, lr} 2: af00 add r7, sp, #0 4: 20d8 movs r0, #216 ; 0xd8 6: 8802 ldrh r2, [r0, #0] 8: 2007 movs r0, #7 a: 2101 movs r1, #1 c: 4790 blx r2 e: 2000 movs r0, #0 10: bd80 pop {r7, pc} 12: 0000 movs r0, r0 14: ffec 7fff ; <UNDEFINED> instruction: 0xffec7fff 18: 0001 movs r1, r0 ...

素直でコンパクトなマシン語になってました!
小さいコンピューターにコンパクトに実装するのが好きうれしい Rust でした!

links
- Rust Programming Language
- taisukef/rust4ij: Rust language for IchigoJam (forked from rust4ij by mitsuji)
- 高専でなぜC言語を学ぶのか? IchigoJamマシン語生成プログラム c4ij で作る、C言語版かわくだり

以前紹介した、5コ950円で買える、安価でIchigoJam BASICだけでも使える超音波センサー「HC-SR04」。 他デバイスとの関係で、どうしてもBTNを使いたいとご要望あり。


できました!IchigoSodaにつないでIoT化していますが、IchigoJam、IchigoDakeでもOKです!

BTNはIchigoJam付属のボタンとSLEEPからの復帰のため外部でプルアップ抵抗をつなげていて、ANA(0)としてアナログ入力としても使えます。 つまり、CPU内部の設定としてはアナログになっているので前回紹介したマシン語で読み出そうとしてもうまくいきません。


BTNを割り当てているPIO1_4、LPC1114のデータシートの IOCON_PIO1_4 (アドレス#40044094) を見ると設定方法が書いてあります。 一度、マシン語を使ってどういう設定になっているか読み出してみましょう。

R0=[@IOCON_PIO1_4]L R0=[R0]L RET @IOCON_PIO1_4 DATA L #40044094

asm15でアセンブルして、読みだした値を8桁の2進法で表示

POKE#700,1,72,0,104,112,71,0,0,148,64,4,64 OK ?BIN$(USR(#700,0),8) 01000001

2:0 つまり最下位の0bit目から2bit目の3bitを使ったFUNCは1、次の2bitのMODEは0(プルアップなどなし)、次の1bitのHYSは0(無効)、6bit目はReservedとして予約されていて1を設定することになっていて、7bit目ADMODEが0でアナログ入力モードとなっています。

これをADMODE:デジタル入力+FUNC:PIO1_4と、`11000000 に一時的に変更する作戦でいきます。前回のカウントプログラムの前後にこの設定を足します。

PIO1のベースアドレスは #50010000、BTNは、PIO1_4の場所なので
?"#5001";HEX$(1<<(4+2),4) → #50010040 を@INに設定します。

'BTN(PIO1_4) <- digital R1=`11000000 R3=[@IOCON_PIO1_4]L [R3]L=R1 'count check R0=0 R1=[@IN]L @LOOP R2=[R1]L R0=R0+1 R2-0 IF !0 GOTO @LOOP R0=R0>>9 'BTN(PIO1_4) <- analog R1=`01000001 [R3]L=R1 RET @IOCON_PIO1_4 DATA L #40044094 @IN DATA L #50010040 'BTN=PIO1_4

アセンブルして、BASICのプログラムと組み合わせて、できあがり!

10 POKE#700,192,33,6,75,25,96,0,32,5,73,10,104,64,28,0,42,251,209,64,10,65,33,25,96,112,71,0,0,148,64,4,64,64,0,1,80 20 OUT1,1:OUT1,0:?USR(#700,0) 30 WAIT 5:GOTO 20

マシン語でカウントした値、R0をBASICに返す前に9ビット右シフト、つまり512分の1にしています。マシン語のカウントだと速すぎて大きな値になってしまうからですが、ここをいじると精度アップが見込めます。 ただ、IchigoJamでは1秒間に1.5万回くらい画面表示用の割り込みが発生するので、高い精度で計測するには割り込みを一時的に止める必要があります。

CPSID R0=0 R1=[@IN]L @LOOP R2=[R1]L R0=R0+1 R2-0 IF !0 GOTO @LOOP R0=R0>>5 CPSIE RET @IN DATA L #50001000 'IN1=PIO0_10

割り込みの一時停止は CPSID、最下位は CPSIE です。戻し忘れると何も操作できなくなってしまいます。下記、CPSIDした後リターンする危険なプログラム、SAVEした後、お試しください。

LET[0],#B672,#4770:?USR(#800,0)

完成した、超音波センサー、TrigをIN1に接続し、精度16倍バージョンがこちら!

10 POKE#700,114,182,0,32,3,73,10,104,64,28,0,42,251,209,64,9,98,182,112,71,0,16,0,80 20 OUT1,1:OUT1,0:A=USR(#700,0):?A 25 LED A<300 30 WAIT 5:GOTO 20

一定距離から近づくとLEDがついてお知らせ、リレー経由でスゴイ照明と組み合わせると防犯ライトにもなりますね!

5 B=0 26 IF B=0 AND A<300 B=1:N=N+1:IOT.OUT N:?"IOT!";N:WAIT30 27 IF B=1 AND A>=300 B=0

IchigoSodaを使って通ったらIOT.OUTでカウントを送るように改造も簡単です!
福井県で始まった「混雑状況オープンデータ」との連携も便利そう。


Let's IoT with IchigoJam x various sensors!

links
- 200円 超音波距離センサー HC-SR04 を IchigoJam で使う方法 - Armマシン語で時間を測ろう
- 今週末は越前がにロボコン! IchigoJamで超音波センサーをIN1とは違うポートで使う方法 BASIC編 マシン語編

マシン語や、アセンブリ言語、高専で習いましたか?

コンピューターはマシン語で動く機械。家電が電機で動くくらいの基本です。
全小学生がプログラミングする時代、さらっと15分でマシン語の肝、押さえましょう。

前提知識は、鯖江市の小学4年生向け総合2コマでも実施しているプログラミング体験。
大きな文字が大人に優しい、はじめてのプログラミング with IchigoJam スライド資料3種のオープンデータ! KDDI連携、福井県小浜市編
まだの方は IchigoJam または IchigoJam web と上記スライドを使って、まずはさらっとご体験ください!

IchigoJam BASICを使った、1から100までの地道な足し算。

A=0:FOR I=1 TO 100:A=A+I:NEXT:?A 5050

AやIは変数と呼ぶ、コンピューター内の記憶です。Aはひとまず0と覚えてもらいましょう。 リファレンスを見ると、FORとNEXTコマンドでIが1から100まで繰り返すことがわかり、変数Aがどんどん書き換えられて、最終的に?(=PRINT)で、表示するプログラムと読めると思います。(A=A+1 は LET A,A+1 の省略形)

コンピューターは数の計算しかできません。上記のプログラムもすべて数として処理されています。IchigoJam BASICというOSは、かかれたプログラムを1文字ずつ文字コードを照合しながら、知っている言葉を見つけたら、その処理を行うことを繰り返します。知らない言葉に遭遇したら「Syntax error」と返すのもOSの役目です。

一文字ずつ、丁寧に処理しているので、真の力は発揮できていません。
そこでマシン語の登場です!

?USR(#800,100) Segmentation Fault

指定したメモリをマシン語として解釈して、動かすコマンドUSR(ユーザー)を使うと、エラーになります。(IchigoJam 1.4未満だと固まるので、電源入れ直しましょう)

IchigoJamで使っているNXP社のCPU LPC1114は、Arm Cortex-M0アーキテクチャーなので 0-65535(16bit)の数(=マシン語)によって動作を指定します。
BASICと同じように、繰り返し足し算するプログラムをマシン語でいれてみます。

LET[0],#2100,#1841,#3801,#D1FC,#4608,#4770 ?USR(#800,100) 5050

LETコマンドは配列に連続した値をセットしていきます。HELPコマンドで確認できますが、IchigoJamの配列はコンピューター内のメモリ#800(16進法で800という位置)に記憶された数の並びです。

マシン語を解読してみましょう! Armマシン語の仕様は2進法で区切ると読みやすいので、BIN$コマンドを使います。

?BIN$([0],16) 0010000100000000

マシン語表をみて、0と1の並びが一致するものを探しましょう。 早速、一番最初の Rd=u8 が、一致しますね。Rdの部分、6〜8番目が0なので、2進法で001、つまりR1、その後8bitが全部0、つまり R1=0 と解読できます。(R0〜R15は、CPUがもっている記憶領域、レジスタと呼びます)

同じように、6つのマシン語を解読していきましょう。

FORI=0TO5:?HEX$([I],4),BIN$([I],16):NEXT 2100 0010000100000000 1841 0001100001000001 3801 0011100000000001 D1FC 1101000111111100 4608 0100011000001000 4770 0100011101110000

解読すると、下記のような動作をしていることがわかります。

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

IF !0 GOTO n8 は、ちょっとややこしいです。11010001の並びでまずマシン語がわかります。n8とは、2進法で8bit(8桁)使った飛び先を指定しますが、一番上の桁が1になっているものはマイナスの数を表します。全部8桁、全部が1だと-1、最後が0だと-2・・・と続く、2の補数表現を使います。 -4だとわかりますが、実はこれに2を足した場所 -2 が飛び先となります。R0を1減らして、0でなければ2つ前のマシン語、R1=R1+R0 のマシン語へ飛びます。

RETでBASICに戻ってくるときの R0 の値が、USRコマンドの値となって、表示されます。

CPU、Arm Cortex-M0 アーキテクチャーのLPC1114の最大動作周波数は50MHz、IchigoJam標準の設定では48MHzで動かしています。 1Hzは、1秒間に1回という単位、M(メガ)は、100万の意味。ほとんどのマシン語を1つ1クロックで処理するので、秒間最大5000万回で計算できるというわけです!

ループさせずにRETで戻らせてみたり、引き算、掛け算など、いろいろいじって思い通りになったり、ならなかったり、遊んでみましょう!

命令をいろいろ組み合わせれば何でもできそうな感が伝わりましたか? このマシン語をいい感じに生成するプログラムのことをコンパイラやランタイムと呼び、C言語をはじめ、いろいろな言語が動いている裏っ側となります。
(参考、C言語開発者「C言語は初心者にはお勧めできない」 エントリーにオススメBASICは、世界初のクラウド対応言語だった!

スマホで使われているのは 64bit化された Arm Cortex-Aシリーズ、PCでは Intel/AMD、これから活躍楽しみな RISC-Vなど、CPUによってマシン語の違いはありますが、基本は同じです。

もうちょっとマシン語遊んでみたい人は、こちら「はじめてのマシン語」をどうぞ!
マシン語も分かったし、いろいろ作ってみたい人にオススメは、JavaScript。サーバーからスマホ、PC、ゲーム機まで動くプラットフォーム数、最高です!

プログラミング好きな高専生、鯖江の自然豊かな古民家でのインターン、来てみませんか?

LPC1114やラズパイで動く IchigoJam が対応しているマシン語は、Arm Cortex-M0 の16bitが基本のThumb命令。 マシン語表を見れば一目瞭然、とってもシンプルで使いやすい!

C言語でArm Cortex-M0を真似る(エミュレーション)プログラムを作り、IchigoJam web に組み込んでみました。

年賀アプリ2020のマシン語版を動かしてみた様子。


こちらArmマシン語入門から「画面をイチゴで埋め尽くす12の方法

これで実機でなくてもマシン語の世界に触れられます!
ただ、圧倒的なスピードを感じられないので、引き続き実機で触れるのが一番です。

まだ作りがいい加減なので、実機と挙動が違うところが多々あるはずです。
オープンライセンスなオープンソースなので、ご興味ある方、気軽にコミッターとしてご参加ください!
IchigoJam/acm0emu: CPU emulator for Arm Cortex-M0
組み込み簡単、とってもシンプルなC言語ヘッダー1ファイル、わずか700行あまり。
おかしな挙動のご報告(issues)や、テストコード寄稿も大歓迎です。

一日一創、デザインをシンプルに見やすくプチリニューアル。
鍵は、HTML viewportの幅指定。

<meta name="viewport" content="width=650">

iPhoneからの見た目、いい感じになりました。

結論、できる!
ただし、コンピューター自体の仕様であるマシン語へ都度翻訳する、インタプリタ型の IchigoJam BASIC では無理。

真の力を引き出す、マシン語と、プログラミング言語の世界をのぞいてみよう! for 福井高専電子情報工学科1年生。


IchigoJamのハーフキット、はんだづけからスタート!


つないで、LED1、光った!完成! (90分1コマちょっとでほぼ全員完成、はんだごての準備などをしておけば短縮可能、失敗した人用完成版もいくつかあるといい)


授業としてははじめてのプログラミング!


LEDが点滅するロボットの仕組み、かわくだりゲームによるアプリづくりの基本を小学生向けの3倍速で紹介!
IchigoJamは、本当に1秒に5000万回計算できるのか!? 〜IchigoJam マシン語入門〜(keynote/PDF)」
はんだづけから、はじめのいっぽ、ゲームづくりまでの資料はこちら!アレンジ自在のオープンデータ。
一度やったら大丈夫、きっと先生として小学生に教えられますよ!


IchigoJamは、本当に1秒に5000万回計算できるのか!? 〜IchigoJam マシン語入門〜(PDF)」
今回初公開、マシン語入門!かわくだりゲームまでやった人向け、小学生でもきっとOK!


100円のコンピューターがなんと1秒間に5000万回!・・・でも、本当に?


実際測ってみると、VIDEO0で表示を消してもせいぜい1秒に1000回・・・、遅い!
その理由は、IchigoJam BASICがインタプリタ型のプログラミング言語だから。


マシン語ではなそう!


IchigoJamのCPU、NXP LPC1114の説明書と、Armの説明書をまとめてできた、マシン語表


足し算は、Rd += u8 を使う!


2進数、10進数、16進数の変換は IchigoJam BASICのコマンドでも簡単!


マシン語をメモリに書き込んで、USRを使って呼び出し!(呼び出し元にかえる #4770 がないと、どうなっちゃう!?)


マシン語で足し算のループを作ろう!


1000回でも1万回でもCLTとTICK()では1/60秒未満で測定不能なので、ループ回数を100倍に!


ビデオ表示を消して、1ループ1000万回になった!プログラムとマシン語表のサイクルを見てみると、確かに1秒間に5000万回計算できてることが判明!


実は、CPUだけだと、最新のCPUでも、1つだけならたかだか40倍くらいしか変わらない。
3D計算やAIなど、特定の計算に特化したハードウェア(GPU)の活用が、圧倒的計算力を活かす鍵!


圧倒的パワーが魅力なコンピューター。いろいろたのしいものつくっちゃおう!


好評だったNT鯖江2019、来年のNT鯖江2020の開催は、2020/10/3-4が有力!
見に来るだけでももちろん歓迎、でも、せっかくなら、なにかつくって出展しよう!

links
- はじめてのマシン語 - IchigoJamではじめるArmマシン語その1
- 福井で初開催!なにかつくろう、NT鯖江2019! ダイジェスト動画と交互連打で目指せ世界記録ゲーム!

IoT人流センサーでも活躍、超音波で距離を測るセンサー「HC-SR04」は、デジタル入力を使ってアナログ量が測れます。
0か1かしかないデジタルでどうやって、量がわかるのでしょう?
1になるまでの時間を見るのです。

改めて、このセンサーの使うプログラムを見てみましょう。
(測距センサーHC-SR04:IchigoJam、Trig:OUT1、Echo:IN1、GND:GND、Vcc:5V)

10 OUT1,1:OUT1,0:A=0 20 A=A+1:IF IN(1) CONT ELSE ?A 30 WAIT 5:GOTO 10

OUT1としてしまうと、他のOUTポートもまとめてコントロールしてしまうので、OUT1,1:OUT1,0と変更しました。
これがセンサーのTrigとなり、超音波センサーの2つの丸めの1つから超音波のパルス(短い時間の1)が発射されます。
この超音波が返ってくるまでの時間を変数Aを使って、IN1が0になるのを待つ。Aが距離。
以上が使い方の基本です。

OUT1が埋まっている時は、TrigをOUT2から6まで空いているところに挿して、例えば10行をOUT3,1:OUT3,0とかすればOK!
IN1が埋まっている時は、EchoをIN2から4までの空いているところに挿して、例えば20行をIN(2)とかすればOK!

(測距センサーHC-SR04:IchigoJam、Trig:OUT3、Echo:IN2、GND:GND、Vcc:5V)

10 OUT3,1:OUT3,0:A=0 20 A=A+1:IF IN(2) CONT ELSE ?A 30 WAIT 5:GOTO 10

IchigoJamが速いほどに、近いものが認識でき、細かく測れます。高速化した1.4β、お試しください!

いろんなセンサーやモーターを組み合わせて、誰も作ったこと無いものつくっちゃいましょう!


HC-SR04 x IchigoJam S

更に、精度が必要な場合や、ファームウェアの書き換えが面倒な場合、マシン語を使って時間計測を高速化します。

R0=0 R1=[@IN]L @LOOP R2=[R1]L R0=R0+1 R2-0 IF !0 GOTO @LOOP R0=R0>>9 RET @IN DATA L #50001000 'IN1

IN1のアドレスは #50001000 でした。
IN2はアナログ入力設定になっているので切り替えが必要なため、少しややこしい。
IN3のアドレスは #50000080
IN4のアドレスは #50000100
となります。

これをasm15を使ってアセンブルするか、マシン語表を見ながらハンドアセンブルしてできるマシン語がこちら。(OUT3を使う場合は20行をOUT3,1:OUT3,0に変更、IN3を使う場合は10行末尾を#80,#00,#00,#50に変更)

10 POKE#700,0,32,3,73,10,104,64,28,0,42,251,209,64,10,112,71,#00,#10,#00,#50 20 OUT1,1:OUT1,0:?USR(#700,0) 30 WAIT 5:GOTO 20

このアドレスの求め方、IchigoJamのCPU、LPC1114の取説によると、PIO0のベースアドレスは #50000000
IN1は、PIO0_10の場所なので ?"#5000";HEX$(1<<(10+2),4) → #50001000
IN3は、PIO0_5の場所なので ?"#5000";HEX$(1<<(5+2),4) → #50000080
IN4は、PIO0_6の場所なので ?"#5000";HEX$(1<<(6+2),4) → #50000100
(参考、マシン語でLEDを光らせよう! - IchigoJamではじめるArmマシン語その4


Hana道場、越前がにロボコンに向けて開発が進んでます!超音波センサーを違うポートで使いたい?


2つのモーター制御に、たまごを惑星においてくるためのサーボ制御、ライントレース用の2つセンサー、もりもりです!
これにレアメタル判定用に、超音波センサーを追加!


福井の小学生向けご当地ロボコン「越前がにロボコン」いよいよ今週末11/3開催
11/3日 9:00-17:00 ショッピングシティ ベル、あじさいホールにて!(Googleマップ

最終調整に入ったIchigoJam 1.4β、音を鳴らすと画面右端にツブツブが出るという報告。

ミニモニターでは気が付かなかったが、大画面に映すと確かにでる。音を鳴らしているときだけ。
SPIの方式を16bit単位から要領削減のため8bit単位に変更してから発生していると判明。詳細な原因は謎。

IchigoJam 1.4β13
- 音を鳴らしている時に画面右端にツブツブがでる不具合を修正
- F12キーに行削除を割り当て、F11キーにカーソル以下削除を割り当て(以前から)

ファンクションキーがF11/F12があるキーボードの人向けに、ちょっと便利な機能追加。(IchigoJamの特殊キー一覧更新)


新兵器、Armのマイコン用開発ツール「Bumpy - SWDデバッガー
最近のArmのマイコンのデバッグ用窓口はSWDで統一され、どのメーカーのものでもこれで転送、デバッグができる。
IchigoJamで使っているNXP社のLPC1114も、ブレークポイントを指定しながら実機上でステップ実行!
ややこしいバグにも強くなれそうです。

ベーマガ&電子工作マガジン、最新号発刊!
楽しそうな IchigoJam BASIC のプログラムの数々。小学校現場の声から生まれた新型IchigoJam、IchigoDyhookがマンガで紹介されてます!

楽しそうな画面、ムーンレスキューはプログラムも1KB以内でコンパクト、オールBASICでわかりやすく打ちやすい。遊んだ後も、豊富な解説を参考にいろいろ改造して遊んで二度おいしい! (電子工作マガジン2019年秋号 別冊付録付き


こちらは1Kプログラムx4で、4kbyte使ったRPG!
豪華3Dアニメーション付きのRPGもプログラムの基本や構造は一緒。
最大132KB使ったプログラムがかけるEEPROMを使うのもありです!
ちょっと長めのプログラムも、部分的に動かして遊びながら打ち込んでいくのも勉強になって良いですよ!
作者への思いを巡らせながらのプログラミング写経。作れる幅を広げる伝統ある学習方法です。


ハードウェアと親和性高い、実機版IchigoJamがイチオシですが、学校のコンピューター室や、PCを持っている子供や大人への体験版として IchigoJam ap、最新1.4β版を用意しました。

IchigoJam 1.4β12
- IchigoJam ap 追加(for Windows / for Mac)


IchigoJam-FANで話題のライフゲームを使った比較動画ですが、ap、メチャクチャ速い!

10 CLS:VIDEO3 20 FORI=1TO50:LCRND(14)+1,RND(10)+1:?CHR$(1):NEXT 30 FORI=#911TO#9A1STEP16:FORJ=ITOI+13 40 A=PEEK(J-17)+PEEK(J-16)+PEEK(J-15)+PEEK(J-1)+PEEK(J+1)+PEEK(J+15)+PEEK(J+16)+PEEK(J+17) 50 IF A=2 B=PEEK(J) ELSE B=A=3 60 POKEJ+192,B:NEXT:NEXT 70 COPY#900,#9C0,192:IF INKEY() RUN ELSE GOTO30

キーを押すともういちど!
ランダムの代わりに、有名で動きがかわいいパターン、グライダーにするプログラムはこちら

20 LC1,3:?CHR$(1,1,1,LEFT,UP,1,LEFT,LEFT,UP,1)

どのくらい速いのか、ベンチマークしてみたところ、IchigoJam 1.4β12、LPC1114での実機版と180倍違いました。 IchigoJamのArm Cortex-M0 48MHzとMacの Intel Corei5 2.3GHzで、58倍。画面描画で速度が3分の1程度になっていることを加味すると計算ぴったり。


小学生の内に自分のパソコンを持ってほしい!
「じぶんでつくる、じぶんのパソコン IchigoJam」起動時にPRしてみました。
IchigoJam ap β版、いろんな環境での動作報告、お寄せいただけるとうれしいです。
IchigoJam-FAN - Facebook

進む、jigインターン2019の選考プロセス。面接で好きなプログラミング言語を聞いて、C言語と答える高専生は割と多い。 黒い画面にテキストで動く地味なプログラム、それで楽しさは伝わるのだろうか?

中学生の頃、その頃のパソコン好きが辿った、BASIC、Z80マシン語の次のC言語。妙に気に入ったのが、ファイル変換プログラム。バイナリデータをテキストに変換するプログラム(matsumoto)や、K&Rスタイルしか対応していなかったMSXのC言語をモダンに使えるように変換するプログラムなど、BASICでは遠かった実用性を感じて感動。

時は現代、IchigoJamβのバグフィックス。C言語なくてはありえない24KBのOSづくり。スクリプト言語ではランタイムが収まらず。マシン語で書くには複雑すぎる。 C言語の魅力は、生成されるマシン語が想像でき、コンピューターの本来の力をほぼ最大限に引き出してあげられてる感にある。

コンパイラが生成したLPC1114用24KBのバイナリをAPI追加するポストプロセス。インテルHEXファイルに反映し忘れていた不具合を直すため、変換プログラムを書く。 RubyでもPythonでもJavaでもJavaScriptでも書けるが、エコなC言語が気持ちいい。このくらいの規模だと、自作コンパイラでも手が届く。


「bin2hex.c - バイナリデータからインテルヘックスファイルへの変換プログラム in C」

このプログラムを使ってできあがったもの
IchigoJam 1.3.2β15 - 「ichigojam-1.3b15.zip
(USキーボードで効かないキーがあった不具合修正、HEXファイルでAPIが使えない不具合修正)

API呼び出しサンプルプログラム RNDを使ったサイコロプログラム(for IchigoJam 1.3.2b15)

10 LET[0],#21C0,#8809,#4708:?USR(#800,6)+1 RUN 5

地味ゲー好きだとカミングアウトしてくれた鯖江の少年に後押しされて誕生したIchigoJam。 自動運転、キラキラVR、ロボット、ドローンなど、派手な応用領域も地味なファイル変換も根っこは同じ、コンピューターとの対話、プログラミング。


福井県小中学生 プログラミング・フェス
福井新聞との取り組み、小中学生プログラミングフェスも4年目!
今年の舞台は禅のふるさと、福井県永平寺町の曹洞宗の大本山、永平寺。
座禅とプログラミングで、自分自身をアップグレードし続ける楽しさに気づけるか!?

去年大活躍した、自分でプログラミングする自動運転車「らでぃっしゅ」今年も登場!


プログラミングフェス2018の様子を、福井県庁の岩田さんが取材してくれた様子。
体当たり撮影「すごい」県庁職員 福井県広報課の岩田早希代さん | 政治・行政 | 福井のニュース | 福井新聞ONLINE

伝えよう、世界中のどこにもないものを創り出せるワクワク感。

links
- 福井県小中学生 プログラミング・フェス

bin2hex.c

#include <stdio.h> void out(int address, char* buf, int nbuf) { int crc = nbuf + address + (address >> 8); printf(":%02X%04X00", nbuf, address); for (int i = 0; i < nbuf; i++) { printf("%02X", buf[i] & 0xff); crc += buf[i]; } printf("%02X\n", -crc & 0xff); } int main(int argc, char** argv) { char buf[16]; int nbuf = 0; int address = 0; for (;;) { int c = getchar(); if (c == EOF) { if (nbuf > 0) { out(address - nbuf, buf, nbuf); } printf(":00000001FF\n"); break; } buf[nbuf++] = (char)c; address++; if (nbuf == 16) { out(address - nbuf, buf, nbuf); nbuf = 0; } } return 0; }

IchigoJamのCPU、LPC1114 Arm Cortex-M0のマシン語には、割り算命令がありません。
参考:マシン語表Cortex-M3以降にはあります SDIV/UDIV)

無いものは作ればOK!(IchigoJamでのR3はここでは封印

N / M = A ... R(A:商、R:あまり、ただしNもMも正の整数とする)という割り算をする場合、割り算記号を使わずに作成できればOKです。何か、得意な言語で作ってみましょう。

例えば、IchigoJam BASICなら

10 INPUT N 20 INPUT M 30 A=0 40 N=N-M:IF N>=0 A=A+1:CONT 50 N=N+M 60 ?A;"...";N RUN ?300 ?7 42...6

割り算記号を使わない割り算、できました!

これをasm15マシン語にします(USRでは引数が1つなので、割る数R1に7と設定)

R1=7 R2=R0 R0=0 @LOOP R0+=1 R2=R2-R1 IF GE GOTO @LOOP R0-=1 R1=R2+R1 RET

アセンブルしたバイナリ(18byte、R1設定を除くと16byte)を使って、動かしてみましょう

POKE#700,7,33,2,70,0,32,1,48,82,26,252,218,1,56,81,24,112,71 ?USR(#700,300) 42

これで完成! ・・・としてもいいのですが、割られる数が大きくて、割る数が小さい時、何万回もループすることになって遅そうです。

例えば、30000/1を計算する場合、1ループ5cycle3万回で15万cycle。CPUの周波数48MHzの逆数、21nsecが1cycleにかかる時間なので、63万nsec = 630usec = 0.63ミリ秒かかります。 足し算引き算かけ算の15万倍も遅いとなると、高速処理が命のゲームで使うには厳しいこともありそうです。

そこで登場、アルゴリズム(問題解決手法)!

ひとまず簡単に思いつくところで、2進数を使った筆算アルゴリズムで高速化してみます。 割り算を手で計算するときに筆算を使うように、大きな桁からかけ算して引いてを繰り返して答を求めます。 幸い、2進数の筆算は0か1かしかないので、とってもシンプル。何か書きやすいプログラミング言語でアルゴリズムを確かめます。

10 INPUT N 20 INPUT M 30 A=0 40 FOR I=10 TO 0 STEP -1 50 L=M<<I 60 IF N>=L N=N-L:A=A+1<<I 70 NEXT 80 ?A;"...";N RUN ?300 ?7 42...6

(変数が16bit用に、IchigoJam BASIC桁溢れ防止のため10bitシフトからスタート)
前の手法に比べて速くなったことが体感できましたね?では、こちらをマシン語にします。

R1=7 PUSH {LR,R4} R2=R0 R0=0 R3=16 @LOOP R4=R1 R4<<=R3 R2-R4 IF LT GOTO @SKIP R2=R2-R4 R4=1 R4<<=R3 R0+=R4 @SKIP R3-=1 IF !MI GOTO @LOOP R1=R2 POP {PC,R4}

ループ回数が16回にまで劇的に減り、先の最悪の場合と比較し、約1000倍高速です!

ただし、その代償として、マシン語の量が32byteと16byte増えてました。これが多いか少ないかは状況次第です。 また、割る数と割られる数が近い場合は毎回150cycleかかる今回の手法と違って、単純ループの実装の方が速かったりします。 状況によって使い分けましょう。

OSとしてのIchigoJamとしては、汎用的に使われることを想定して、あまりに遅い除算は残念なので、第二案でいきたいです。 ただ容量は極力小さくしたいので、かけ算が1cycleで動くことを利用して、もうひと工夫縮めてみます。

R1=7 PUSH {LR,R4} R2=R0 R0=0 R3=1 R3=R3<<16 @LOOP R4=R1 R4*=R3 R2-R4 IF LT GOTO @SKIP R2=R2-R4 R0+=R3 @SKIP R3=R3>>1 IF !0 GOTO @LOOP R1=R2 POP {PC,R4}

2byte縮み、引き算する場合のcycleが2減りました!
たった2byteと笑うかもしれませんが、その2byteを削るのに結構苦労したりするんです。

POKE#700,7,33,16,181,2,70,0,32,1,35,27,4,12,70,92,67,162,66,1,219,18,27,24,68,91,8,247,209,17,70,16,189 ?USR(#700,300) 42

実は、まだ落とし穴があります。マイナスの値で割り算の計算をさせてみてください。
おかしくなりますね。また、割る数に0を指定した時にどんな動きをしてほしいです���?
すべては、あなたの思い次第!

より高速で効率良いアルゴリズムを探してみるのも楽しそうです。Wikipediaの「除算」を見てみると、懐かしの割り算バグありPentiumの話がでてました。 試行錯誤の積み重ねで、今のコンピューター社会ができていることがわかります。

- 連載、IchigoJamではじめる、Armマシン語入門
1. はじめてのマシン語
2. ハンドアセンブルで超速計算!
3. マシン語メモリアクセスで画面超速表示!
4. マシン語でLEDを光らせよう!
5. 楽しさ広がるマルチバイトメモリアクセスとスタック
6. マシン語使いこなしTIPS
7. カジュアルに使うインラインマシン語
8. アセンブラを使って楽しよう
9. マシン語で高速SPI
10. マシン語を制するもの時間を制す
11. 画面をイチゴで埋め尽くす12の方法
12. レジスタ不足に上位レジスタとスタック操作
13. コンパイラはじめのいっぽ、EVAL実現法とマシン語生成
14. サイズを取るかスピードを取るか、割り算のアルゴリズムとマシン語実装
15. マシン語化で1万倍速!? セットで学ぶアルゴリズムとコンピューター

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