幼少期の憧れを追い 1998 年にリリースされた LEGO RCX を 2023 年に動かす (NQC 使用)


# 背景
盆休みに暇すぎて LEGO で遊んでた。
久しぶりに LEGO やったら楽しすぎてマインドストームやりたくなってきたのでヤフオクで購入。

## マインドストームとは

https://ja.wikipedia.org/wiki/MINDSTORMS

いつも遊ぶレゴに加えてモーターやらセンサーやらを使い、プログラミングが学習できるといった代物。
**これで性癖狂わされてこっちの世界に来た人も多いはず。**(自分がそうだったので...)

## RCX とは
3 代あるマインドストームの中で初代、リリース 1998 年。黄色いやつ。
画像にあるのは RCX 本体、IR タワー、モーター。

![syJ6jXUXQGy1JuYkWypwxw.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1852474/a1262213-7650-8e13-5e21-af96ebbfde1d.jpeg)


令和の時代に RCX 動かしたい変態さんがいるならこちらのページが参考になる。


https://www.johnholbrook.us/RCX_guide.html


**RCX の中でも 1.0, 1.5, 2.0 と 3 バージョンに分かれている。**

頭部に IR 受信部分があり、IR タワーと通信することによって作成したプログラムを転送することができる。
(赤外線通信なんて小さいころにやってた DS 以来だよ…)

-----
(以下個人的な感想)
**なんと H8 マイコンを積んでいるらしい。** [組み込み OS 自作入門](http://kozos.jp/books/makeos/)読んだことある人なら知ってるやつ。
正直これに惹かれてこんなことしてるまである。

あと幼少期欲しくても手が届かなかったマインドストームを社会人パワーで買えるのがうれしかった。
その頃は図書館でマインドストーム関連の本を読み漁り、組んでみたい要求に悶々としていた。
当時の自分に今手元にあるマインドストームを見せたら、狂ったように遊ぶんだろうなぁと思った。

-----
### RCX でのプログラム開発
昔 (リリース直後、Windows98 とかの時代) は ビジュアルプログラミングができる開発環境が公式で用意されていたらしいが、当然今は存在しない。
そのため有志が作成した開発環境を使わせてもらう。
開発環境としては主に 2 つある。
- NQC
``Not Quite C`` (意 : C じゃないよ！) と名前の通り？ C ライクに開発ができる。
 **RCX の純正ファームウエアを使用。**

だいたいこんな感じに記述できる。
```test.nqc
task main()
{
 OnFwd(OUT_A);
 OnFwd(OUT_C);
 // A, C ポートにつながれたモータを前転
 Wait(400);
 // 4s 待機
 OnRev(OUT_A+OUT_C);
 // A, C ポートにつながれたモータを逆転
 Wait(400);
 // 4s 待機
 Off(OUT_A+OUT_C);
 // A, C ポートにつながれたモータを停止
}
```

感覚としては ``Arduino`` に近いと思われる。
**今回はこちらを使用し、開発を行う。** 

----
- brickOS

https://brickos.sourceforge.net

OS と名の付く通り、RCX 上にて OS を動かすらしい。
その使用上、純正ではないファームウエアを使用する必要がある。
今回 ``Arch Linux`` 環境で開発を行うが、 .deb でのファイルしか見つからないため断念。



## 開発環境
OS : Manjaro Linux (ノートパソコンにインストール済み)
RCX : 1.0
IRタワー : USB 接続ができるもの 

## 環境構築
環境構築するにあたり、こちらの記事が参考になる。(というか丸パクリ)

https://pbrick.info/2013/10/configuring-the-lego-usb-tower-on-linux/

### USB ドライバ導入

-----
#### 1. パソコンとIR タワーを接続し以下コマンドを実行する
```terminal:terminal
find /lib/modules -name *lego*
```
自分の環境では以下のようなレスポンスがあった。
```terminal:terminal
/lib/modules/6.1.44-1-MANJARO/kernel/drivers/usb/misc/legousbtower.ko.zst
```
ここで何らかの反応があれば、その OS で IR タワーは使える。

-----

#### 2. /etc/modules に legousbtower を追加
以下コマンドでファイルを新規作成する
```terminal:terminal
sudo vi /etc/modules
```
開かれたらファイルに ``legousbtower`` と記述し、再起動する。
これにより起動時に該当モジュールが読み込まれるようになる。

----

#### 3. IRタワーモジュールが認識されているか確認
```terminal:terminal
ls -l /dev/usb
``` 
自分の環境では以下のようなレスポンスを確認。
```terminal:terminal
total 0 
crw------- 1 root root 180, 160  8月 24 19:30 legousbtower0
```
-----
### NQC インストール
-----

**実は NQC が USB IR タワーをサポートしていないため、パッチを当てたうえでインストールを行う。**
適当なディレクトリ (今回は ``NQC`` というディレクトリとする) を作成し、そのうえで作業を行う。

#### 1. NQC のソースコードをダウンロード
``NQC`` をカレントディレクトリにした状態で以下コマンドを実行し、``nqc-3.1.r6`` というディレクトリを作成する。
そのディレクトリ内にて、ソースコードのダウンロードと解凍を行う。

```terminal:terminal
mkdir nqc-3.1.r6
cd nqc-3.1.r6
wget http://bricxcc.sourceforge.net/nqc/release/nqc-3.1.r6.tgz
tar xfz nqc-3.1.r6.tgz
```

----

#### 2. ソースコードのパッチをダウンロード
``NQC`` をカレントディレクトリにした状態で以下コマンドを実行する。
```terminal:terminal
wget http://sourceforge.net/p/bricxcc/patches/_discuss/thread/00b427dc/b84b/attachment/nqc-01-Linux_usb_and_tcp.diff
```

この状態で ``ls -l`` を実行すると以下のような出力となる。
```terminal:terminal
total 20
-rw-r--r-- 1 winzu44 winzu44 13912  1月  3  2013 nqc-01-Linux_usb_and_tcp.diff
drwxr-xr-x 9 winzu44 winzu44  4096  8月 24 19:48 nqc-3.1.r6
```

ディレクトリ構造は以下のようになっているはず。

```
- NQC
  - nqc-3.1.r6
  - nqc-01-Linux_usb_and_tcp.diff
```

----

#### 3. パッチを当てる
以下コマンドを実行。なお上記と同じディレクトリ名にしないとエラーが出るので注意。
```terminal:terminal
patch -p0 < nqc-01-Linux_usb_and_tcp.diff 
```
正しくパッチが当たれば以下のような出力が出るはず。
```terminal:terminal
patching file nqc-3.1.r6/Makefile
patching file nqc-3.1.r6/nqc/nqc.cpp
patching file nqc-3.1.r6/rcxlib/RCX_Link.cpp
patching file nqc-3.1.r6/rcxlib/RCX_Pipe.h
patching file nqc-3.1.r6/rcxlib/RCX_Result.h
patching file nqc-3.1.r6/rcxlib/RCX_TcpPipe_linux.cpp
patching file nqc-3.1.r6/rcxlib/RCX_TcpPipe_none.cpp
patching file nqc-3.1.r6/rcxlib/RCX_USBTowerPipe_linux.cpp
patching file nqc-3.1.r6/rcxlib/RCX_USBTowerPipe_win.cpp
```

#### 4. ソースコードを修正し、インストールを行う。
パッチを当てたうえで、nqc-3.1.r6 のディレクトリ内にて ``make`` を行おうとすると以下のようなエラーが出た。

```terminal:terminal
~~~~~
~~~~~
lexer.cpp:(.text+0x1d54): undefined reference to `isatty(int)'
```

以下リンクに対処法があった。


https://bbs.archlinux.org/viewtopic.php?id=160933

**要するに ``lexer.cpp`` にて、 ``isatty()`` の参照が未解決であるということ**

そのため、``#include <unistd.h>`` を以下ファイルに追加する。

```
default/lexer.cpp
compiler/lexer.cpp
```

追加したら NQC のインストールを行う。

```terminal:terminal
sudo make install
```

特にエラーが出なければ、インストール完了。

```nqc``` とターミナルで実行し、以下のようなレスポンスであることを確認する。

```terminal:terminal
nqc version 3.1 r6 (built Aug 23 2023, 20:17:07)
    Copyright (C) 2005 John Hansen.  All Rights Reserved.
Usage error: try 'nqc -help' to display options
```

-----
### NQC からプログラム作成
上記手順でインストールが終わったら、PC から RCX 上へ、プログラムを転送できるようになる。
転送前に、 RCX と電源を接続し、 IR タワーと PC を接続する。
そのうえでタワーと RCX を近づけておく。
(赤外線通信をするため。なんか DS で通信プレイした時を思い出すね。)

転送するために、以下のようなコマンドを実行する。

```terminal:terminal
nqc -Susb:/dev/usb/legousbtower0 -d test.nqc 
```

ここで test.nqc は以下のような内容のテキストファイルとし、保存しておく。

```test.nqc
task main()
{
 OnFwd(OUT_A);
 OnFwd(OUT_C);
 // A, C ポートにつながれたモータを前転
 Wait(400);
 // 4s 待機
 OnRev(OUT_A+OUT_C);
 // A, C ポートにつながれたモータを逆転
 Wait(400);
 // 4s 待機
 Off(OUT_A+OUT_C);
 // A, C ポートにつながれたモータを停止
}
```

ただ自分の環境では、```nqc No firmware installed on RCX``` というエラーが出てしまったため、転送できなかった。
そのためファームウエアの更新を行う

-----

#### ファームウエア更新


https://github.com/jverne/nqc/tree/master/firmware

こちらから任意のファームウエアをダウンロードする。
自分の環境 (RCX 1.0) では ```firm0309.lgo``` をダウンロードする。

ダウンロードしたら、以下コマンドでファームウエアを転送する。

```terminal:terminal
nqc -Susb:/dev/usb/legousbtower0 -firmware firm0309.lgo 
```

ダウンロード中は、RCX の画面上で、数値がカウントアップしていく。
**数分近くかかるので気長に待つ。**

----

#### プログラム転送

ファームウエアの更新が終わったら、再度プログラムを転送する。

```terminal:terminal
nqc -Susb:/dev/usb/legousbtower0 -d test.nqc 
```

プログラムのダウンロードが完了し、 ``RUN`` することで、モーターが 4秒ごとに回転、逆転したりする。
**これで実質 Hello World! でしょ。**

-----

## 感想 (ほぼポエム)
実は NXT (2 代目のマインドストーム) は触ったことあるがそれよりもブロック感があって好みだった。
昔は喉から手が出る程欲しかったものが、今では社会人パワーで簡単に手に入るので大人になるのも悪くない。

ただしこの環境構築で満足している自分もいて、少し寂しくもある。
狂ったようにマインドストーム関連の情報を読み漁ったり、手持ちのレゴで何とかそれっぽいものを再現できないか試行錯誤していたあの頃のほうが、生き生きとしていただろう。

そんな寂れてしまった自分だが、久しぶりにレゴを触ることで、あの頃の楽しさを思い出せた気がする。
また **「何かを作る楽しみ」** を思い出せるように、少し何か作ってみようと思う。