LoginSignup
3
1

More than 3 years have passed since last update.

IchigoJam R に関する諸々

Last updated at Posted at 2021-02-07

IchigoJam R は、2020年末に発表されたIchigoJamの新型です。

紹介ページ:IchigoJam R & IchigoSand 発表、HHKB他USBキーボード対応するRISC-V版、Zen言語でかんたんマシン語両対応 zen4ij #IchigoJam #riscv #zen / 福野泰介の一日一創 / Create every day by Taisuke Fukuno
販売ページ:【β版】IchigoJam 組み立て済完成品 R | Programming Club Net...

※IchigoJamはjig.jpの登録商標です。

本体の写真

パッケージ

IchigoJam R パッケージ

基板表面

IchigoJam R 基板表面

基板裏面

IchigoJam R 基板裏面

実行速度

紹介ページでは「なんとインタプリター、10倍速!」と主張していますが、
実測では従来製品と比べて8~9倍速程度のようです。
また、ビデオ出力ありでの速度が大幅に上がっている一方、VIDEO 0による速度の改善効果は下がっているようです。

詳しくはこのあたりをどうぞ。

自分の記事:IchigoJam速度比較 ~IchigoJam Rが10倍速いってマジ?~ - Qiita
他の人の記事:IchigoJam Rの速度検証 - SHIROのIchigoJam日記

時間の精度

以前書いた記事のキッチンタイマー(本格版)を実行したところ、
1時間に設定して約3秒早くカウントが終わりました。
これは1日あたり72秒、1ヶ月(30日)あたり2160秒(36分)ずれる計算になります。
時計として使うには、ちょっと精度が低いという印象が強いです。

Complex expression耐性

以下のプログラムでネストが深い式を作って実行させ、どこまでComplex expressionが出ずに実行できるかを調べました。

プログラム
cetester.c
#include <stdio.h>

void meow(int cur, int max) {
    putchar(cur % 10 + '0');
    if (cur < max) {
        putchar('-');
        if (cur + 1 < max) putchar('(');
        meow(cur + 1, max);
        if (cur + 1 < max) putchar(')');
    }
}

int main(void) {
    int i;
    for (i = 1; i <= 100; i++) {
        putchar('?');
        meow(1, i);
        putchar('\n');
    }
    putchar('\n');
    for (i = 1; i <= 100; i++) {
        int j;
        putchar('?');
        for (j = 0; j < i; j++) putchar('(');
        putchar('1');
        for (j = 0; j < i; j++) putchar(')');
        putchar('\n');
    }
    return 0;
}

従来製品では、以下のような実験結果になりました。

ファームウェア 実行できた式 Complex expressionになった式
1.0.0 (VER()=10017) ?1-(2-(3-(4-5)))
?(((1)))
?1-(2-(3-(4-(5-6))))
?((((1))))
1.3.1 (VER()=13106) ?1-(2-(3-4))
?((1))
?1-(2-(3-(4-5)))
?(((1)))
1.4.1 (VER()=14114) ?1-(2-(3-(4-(5-6))))
?((((1))))
?1-(2-(3-(4-(5-(6-7)))))
?(((((1)))))

IchigoJam R (1.5b, VER()=15001)では、以下のようになりました。

実行できた式

?1-(2-(3-(4-(5-(6-(7-(8-(9-(0-(1-(2-(3-(4-(5-(6-(7-(8-(9-(0-(1-(2-(3-(4-(5-(6-(7-(8-(9-(0-(1-(2-(3-(4-(5-(6-(7-(8-(9-(0-(1-(2-(3-(4-(5-(6-(7-(8-(9-(0-1)))))))))))))))))))))))))))))))))))))))))))))))))
?(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((1)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

Syntax errorになった式

?((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((1))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

引き算を使った式では、Too longにならない限界までネストを深くしても、エラーにならずに実行できました。
カッコのみを重ねた式では、98段のネスト(あと2段深くするとToo long)でSyntax errorとなりました。
Complex expressionは確認できませんでした。

惜しくも書ける式フルサポートとはならなかったものの、
従来製品と比べて書ける式の深さが大幅(1.4.1と比べて約24倍)に改善していることがわかります。

EEPROMモジュールの使用法

IchigoJam R ではI2Cの端子の配置が従来製品から変わっているため、
EEPROMモジュールを以前と同じように接続しても使えません。

うちでは、このような自作のモジュールを使っています。

EEPROMモジュール EEPROMモジュール 配線図

従来製品では、GNDとVCCが合うように左側の端子に接続し、飛び出ているコードを右側のEX1に接続します。

EEPROMモジュール 従来製品との接続

しかし、IchigoJam R ではこの接続では動きません。
そもそも仕様変更により「EX1」は無くなっています。

IchigoJam R では、このEEPROMモジュールは、GNDとVCCが合うように「右側」の端子に接続し、
飛び出ているコードを5ピンの端子の真ん中に接続することで、使うことができるようです。

EEPROMモジュール IchigoJam R との接続

キーボード

IchigoJam R では、USBキーボードが使えます。
ただし、一部の製品はうまく動かないようです。
実際に、いくつかの製品について動くかどうかを調べてみました。

なお、今回の検証結果は各製品1個についての実験結果です。
同じ型番・製品でも、ロットの違いや個体差などにより結果が変わる可能性が否定できません。

うまく動いたもの

YDKBU11BK (BUFFALO)

YDKBU11BK パッケージ YDKBU11BK 本体

  • 実験中、動作が止まることはありませんでした。
  • Num Lock は効かず、テンキーを押すと(機能の実行ではなく)数字が入力されました。
  • Caps Lock は効いたものの、状態を表すLEDは点灯しませんでした。

さらに、この機種は従来製品の IchigoJam S (1.3.1) でも使えました。
パッケージなどに記載は見当たりませんでしたが、こっそりPS/2にも対応していたようです。

HC56TU (DENSO)

以前中古屋で購入したバーコードリーダーです。
読み取った内容をUSBキーボードとして入力するモードがあります。

HC56TU 本体

  • 初期状態では、バーコードのデータと入力でアルファベットの大文字と小文字が逆になりました。
    • Caps Lock を手動設定でONとするモードにすることで、改善しました。
    • Caps Lock の状態を自動判別するモードでは、改善しませんでした。
  • CRやLFは、CODE128のデータ・ターミネータともに反応しませんでした。
  • ターミネータとしてEnterを設定すると、期待通り改行処理が行われました。

便利なように、LED1LED0のバーコード(CODE128)を用意しました。
名刺サイズ (55mm × 91mm) に合わせたサイズの画像になっています。

バーコード

うまく動かなかったもの

SKB-KG2BK (サンワサプライ)

SKB-KG2BK パッケージ SKB-KG2BK 本体

  • 最初の数文字~数十文字程度は入力できましたが、その後キーを押しても反応しなくなりました。
  • スイッチを入れ直すと、最初の「Ichigojam~」すら表示されないことがありました。

AOK-184WH (アオテック)

AOK-184WH パッケージ AOK-184WH 本体

  • 最初の数文字~数十文字程度は入力できましたが、その後キーを押しても反応しなくなりました。
  • スイッチを入れ直すと、最初の「Ichigojam~」すら表示されないことがありました。
    • このとき、通常は点灯するキーボードのLEDが点灯していませんでした。

ワンボタンキーボード (TOKYO FLIP-FLOP)

Arduinoの開発環境を用いたプログラミングにより、動作を変えることができます。
今回は、初期状態(キーを押すとwが入力される)で実験を行いました。
なお、写真中のUSBケーブルは付属していませんでした。

ワンボタンキーボード 本体+ケーブル

  • キーを押しても反応しませんでした。

公式でUSBハブ内蔵のキーボードは動かないとされていますが、ハブでなくても、
USB Composite Device が挟まるタイプのデバイスは動かないようになっているという仮説が考えられます。

マシン語呼び出し時の引数

IchigoJam 1.2以降の仕様においては、

  • 第1引数:USRの第2引数で指定した値
  • 第2引数:フォントRAMの0番地相当のアドレス
  • 第3引数:フォントROMの0番地相当のアドレス
  • 第4引数:符号なし除算を行う関数のポインタ

という引数が渡されることになっているはずです。

出典:

以下のプログラムを用いて、マシン語呼び出し(USR関数)時の引数の値を調査しました。

10 ' マシンゴ パラメータ チョウサ
20 POKE#700,183,47,41,224,151,15,0,0,19,135,207,15,8,195,76,195,16,199,84,199,19,5,7,240,8,203,35,42,39,0,147,133,5,112,249,154,49,69,51,135,165,0,28,67,19,135,79,17,42,151,28,195,51,7,166,0,28,67
30 POKE#73A,19,135,79,18,42,151,28,195,51,135,166,0,28,67,19,135,79,19,42,151,28,195,113,21,227,90,5,252,130,128,164,70,41,164,32,96,97,96,162,96,227,96,32,70,128,56,128,56,32,97,104,70,96,97,112,36
40 POKE#772,36,1,9,25,1,32,131,67,15,36,38,160,13,93,5,85,41,160,21,93,5,85,43,160,29,93,5,85,1,60,244,213,100,70,112,71
50 X=USR(#700,#1234)
60 ?"ARG0 = #";HEX$([1],4);HEX$([0],4)
70 ?"ARG1 = #";HEX$([3],4);HEX$([2],4)
80 ?"ARG2 = #";HEX$([5],4);HEX$([4],4)
90 ?"ARG3 = #";HEX$([7],4);HEX$([6],4)
100 ?"PC   = #";HEX$([9],4);HEX$([8],4)
110 ?"SP   = #";HEX$([11],4);HEX$([10],4)
120 ?"*(ARG1+#700):";:FORI=0TO15:?" ";HEX$(PEEK(#818+I),2);:NEXT:?""
130 ?"*ARG2       :";:FORI=0TO15:?" ";HEX$(PEEK(#828+I),2);:NEXT:?""
140 ?"*(ARG3&~#1) :";:FORI=0TO15:?" ";HEX$(PEEK(#838+I),2);:NEXT:?""

マシン語部分のソースコード
R7 - #B7
GOTO @TRAD
MODE RV32C

    R31 = PC + 0
    R14 = R31 + #FC ' R14 = @ARG0
    [R14 + 0]L = R10
    [R14 + 4]L = R11
    [R14 + 8]L = R12
    [R14 + 12]L = R13
    R10 = R14 + -#100
    [R14 + 16]L = R10
    [R14 + 20]L = R2

    R11 = R11 + #700

    R13 &= -2

    R10 = 12
@LOOP_RV32C
    R14 = R11 + R10
    R15 = [R14 + 0]L
    R14 = R31 + #114 ' R14 = @ARG1_DATA
    R14 += R10
    [R14 + 0]L = R15
    R14 = R12 + R10
    R15 = [R14 + 0]L
    R14 = R31 + #124 ' R14 = @ARG2_DATA
    R14 += R10
    [R14 + 0]L = R15
    R14 = R13 + R10
    R15 = [R14 + 0]L
    R14 = R31 + #134 ' R14 = @ARG3_DATA
    R14 += R10
    [R14 + 0]L = R15
    R10 += -4
    IF R10 >= R0 GOTO @LOOP_RV32C

    RET

MODE M0
@TRAD
    R12 = R4
    R4 = @ARG0
    [R4 + 0]L = R0
    [R4 + 1]L = R1
    [R4 + 2]L = R2
    [R4 + 3]L = R3
    R0 = R4
    R0 -= #80
    R0 -= #80
    [R4 + 4]L = R0
    R0 = R13
    [R4 + 5]L = R0

    R4 = #70
    R4 = R4 << 4
    R1 = R1 + R4

    R0 = 1
    BIC R3, R0

    R4 = 15
@LOOP_M0
    R0 = @ARG1_DATA
    R5 = [R1 + R4]
    [R0 + R4] = R5
    R0 = @ARG2_DATA
    R5 = [R2 + R4]
    [R0 + R4] = R5
    R0 = @ARG3_DATA
    R5 = [R3 + R4]
    [R0 + R4] = R5
    R4 -= 1
    IF PL GOTO @LOOP_M0
    R4 = R12
    RET

ORGR #100
@ARG0
    SPACE 4
@ARG1
    SPACE 4
@ARG2
    SPACE 4
@ARG3
    SPACE 4
@PC
    SPACE 4
@SP
    SPACE 4
@ARG1_DATA
    SPACE 16
@ARG2_DATA
    SPACE 16
@ARG3_DATA
    SPACE 16

従来製品 1.0.0 (VER()=10017)

ARG0 = #00001234
ARG1 = #00001234
ARG2 = #10000188
ARG3 = #10000187
PC   = #10000188
SP   = #10000DF0
*(ARG1+#700): D1 FA 48 E0 00 F0 22 FB 45 E0 FF F7 1F F8 31 4B
*ARG2       : B7 2F 29 E0 97 0F 00 00 13 87 CF 0F 08 C3 4C C3
*(ARG3&~#1) : 00 00 B7 2F 29 E0 97 0F 00 00 13 87 CF 0F 08 C3

1.1以降における第2引数以降の仕様には従っていないものの、
「第1引数はUSRの第2引数」という仕様には従っていることがわかります。

従来製品 1.3.1 (VER()=13106)

ARG0 = #00001234
ARG1 = #0FFFF9E0
ARG2 = #00005310
ARG3 = #00005171
PC   = #100000E0
SP   = #10000E30
*(ARG1+#700): B7 2F 29 E0 97 0F 00 00 13 87 CF 0F 08 C3 4C C3
*ARG2       : 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF
*(ARG3&~#1) : 00 22 43 08 8B 42 74 D3 03 09 8B 42 5F D3 03 0A

第4引数の値付近から読み取ったデータを逆アセンブルすると、

    R2 = 0
    R3 = R0 >> 1
    R3 - R1
    IF CC GOTO 118
    R3 = R0 >> 4
    R3 - R1
    IF CC GOTO 97
    R3 = R0 >> 8

となりました。
意図はわかりにくいですが、第1引数や第2引数を操作している様子が見られ、
割り算ルーチンである可能性が感じられます。
その他の引数も、仕様どおりになっていそうであることがわかります。

さらに、PC(≒フォントRAMの場所)およびSPの値が、
IchigoJam BASIC RAM 4kbyte のつかいかた(メモリマップ) #KidsIT #IchigoJam #lpc1114 / 福野泰介の一日一創 / Create every day by Taisuke Fukuno
に沿っていることが読み取れます。

従来製品 1.4.1 (VER()=14114)

ARG0 = #00001234
ARG1 = #0FFFFD80
ARG2 = #00005800
ARG3 = #000056D5
PC   = #10000480
SP   = #10000310
*(ARG1+#700): B7 2F 29 E0 97 0F 00 00 13 87 CF 0F 08 C3 4C C3
*ARG2       : 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF
*(ARG3&~#1) : 00 29 01 D1 00 20 70 47 01 22 00 23 52 00 49 00

第4引数の値付近から読み取ったデータを逆アセンブルすると、

    R1 - 0
    IF !0 GOTO @L708
    R0 = 0
    RET
@L708
    R2 = 1
    R3 = 0
    R2 = R2 << 1
    R1 = R1 << 1

となっていました。
最初に割る数が0でないかをチェックしている様子が読み取れるので、
これは割り算ルーチンの冒頭部分だと考えるのは妥当だと考えられます。
その他の引数も、仕様どおりになっていそうであることがわかります。

また、PC(≒フォントRAMの場所)よりSPがメモリ上で前に来ていることが読み取れます。

IchigoJam R (1.5b, VER()=15001)

ARG0 = #00001234
ARG1 = #20000A2C
ARG2 = #20000010
ARG3 = #00000000
PC   = #2000112C
SP   = #20007D70
*(ARG1+#700): B7 2F 29 E0 97 0F 00 00 13 87 CF 0F 08 C3 4C C3
*ARG2       : 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF
*(ARG3&~#1) : 71 AA 01 00 00 00 00 00 00 00 00 00 00 00 00 00

第1引数~第3引数の値は仕様に沿った値になっているものの、第4引数が0になっています。

第4引数の値付近から読み取ったデータは、

MODE RV32C
GOTO #CE
NOP

というマシン語に相当します。
ただし、そもそもIchigoJam R のCPUであるGD32VF103CBT6において、
アドレス0x00000000はRESET service routing vectorであるよう(User Manualの5.1.2を参照)なので、
これが割り算ルーチンであるとは考えにくいでしょう。

(CPUの種類の出典:IchigoJam BASIC 1.5β1、USBキーボード対応 RISC-V版 IchigoJam Rβ 出荷スタート! #KidsIT #IchigoJam / 福野泰介の一日一創 / Create every day by Taisuke Fukuno)

アライメントされていないメモリアクセス

マシン語でnの倍数でないアドレスからnバイトの読み込みができるかを実験しました。
今回は、以下のコードでn=4についてのみ実験しました。

10 ' unaligned read test
20 POKE#700,183,47,6,224,23,5,0,0,19,5,197,15,5,5,8,65,130,128,59,160,1,48,0,104,112,71
30 POKE#800,#11,#22,#33,#44,#55,#66,#77,#88
40 ?HEX$(USR(#700,0),4)

マシン語部分のソースコード
R7 - #B7
GOTO @TRAD
MODE RV32C

    R10 = PC + 0
    R10 = R10 + #FC ' R10 = @ARRAY
    R10 += 1
    R10 = [R10 + 0]L
    RET

MODE M0
@TRAD
    R0 = @ARRAY
    R0 += 1
    R0 = [R0 + 0]L
    RET

ORGR #100
@ARRAY

従来製品ではこのような読み込みは許されず、1.4.1ではSegmentation Faultになります。
一方、IchigoJam R では3322が出力され、このような読み込みも許されることがわかりました。

この記事のまとめ

IchigoJam R においては、

  • BASICのプログラムが従来製品の1.4.1に比べて8~9倍速程度で実行できる
  • 従来製品より時刻の精度が上がっているが、時計を作るにはまだ誤差が大きい印象
  • 従来製品より大幅に複雑な式が使える
  • 従来製品とEEPROMの接続方法が異なる
  • USBキーボードを用いるが、一部のキーボードでは止まったり動かなかったりする
  • マシン語を実行する際、割り算ルーチンのポインタは渡されない
  • アライメントされていないメモリアクセスが可能

となっているようです。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1