honeylab's blog

各種ハードウェアの改造、主にファミコンミニなどをやってます(ました)

ドンキで売ってた5000円のCo2モニタを改造して無線LAN対応にする

先日、ドン・キホーテをうろうろしていたところこんな商品を見つけました。

 

室内用の格安Co2モニタのようです。
性能的には安かろうなんとやら、であることは承知の上、
仕事柄Co2センサについての情報収集は必要なためサクッと買ってみました。

 

早速ですが分解します。

 

Co2センサや温度・湿度センサがこの辺に格納してありました。

 

メインボードとCo2センサはUART接続されているようです。

 

 

 


ここに内蔵されているCo2センサは「CM1106-C」のようです。
データシートがここにあり、UARTのプロトコルも明記されています。

f:id:honeylab:20210221020527p:plain

そのため、Co2センサ自体は単体で動作させることもできますが、
ここではあくまでもこの本体を生かし、
改造して外部から値を収集できるようにしてみます。

ほら、みんな

「またなんかよくわかんないセンサ買ってきたの?」とか

「これで何がわかるの?」とかいわれて

やっとのこと組み立てて頑張ってケースに収めたところで

「ガラクタ?」

って言われたことないですか?ないですかね。

まぁ、

Co2センサってエンジニア的には今特に興味のあるものだと思いますが、
それをうまいこと使いこなしたり、定期的に校正したり、
「誰にでも」見やすい値として表示する、ってちょっと難しいことなんですよ。

ところが、これはもう形はできてて値もカッコよく表示されるんですよ。
この状態で、中に何入れても、値をとってきても誰にも文句言われたりしないですからw
さらに、このメーカが最低限商品として成り立つレベルに実装してきた自動構成の仕組みなどをそのまま利用できるわけです。
それが5000円、これを安いとみるかどうか。

 

脱線しましたか。

 

さて、せっかくですから無線でデータをとれるように、無線LAN対応マイコンを中に入れてみたいと思います。

今回使用するのはなんかその辺に転がっていたESP8266のマイコンボードです。
これに限らず、ご家庭にある無線対応マイコンや、場合によってはただのUART-TCP変換機などを使用することも可能でしょう。

 

このマイコンボードを、データシートを参考に配線していきます。

5VはCo2センサの根元からとりますが、これをマイコンボードに直結していしまうと、マイコンボードに書き込むためにUSBケーブルを接続したときに逆流してしまい、
ちょっと嫌な感じになるため、ショットキーバリアダイオードを挟むことにします。


Co2のデータ収集は、もともとのマイコンが勝手にやってくれていますので、Co2からの返答が送られてくるTXD端子だけを無線LANマイコンの入力に突っ込みます。

f:id:honeylab:20210221021623p:plain

 

そして、シリアルからCo2の読み取りパケットを解析してppmの値を取得し、
HTTPレスポンスで返すようなスケッチを書きこみます。

せっかくなのでmDNSに対応させたかったため、mDNSのサンプルコードを書き換えて使用しています。

 

gist.github.com

 

家の中に置いておいて、家庭内のネットワーク上のPCなどから値を取得することを想定し、クライアントモードで立ち上げていますが、
こいつをAPにして動かすようにすることももちろん可能です。

さて、ブラウザでアクセスしてみると…?

 

f:id:honeylab:20210221022319p:plain

できたできた。二つ目の数字はフリーズ検出のため、パケット解析ごとにインクリメントされる値です。

 

自動化のために、wgetを使ってみます。(wslではmDNSが使えなかった…)

f:id:honeylab:20210221022431p:plain

おっけー。

あとは、これをスクリプトでもなんでもして、DBに入れるなり、CSVにするなり何でもできます。

13f:id:honeylab:20210221032329p:plain

これは、この作業をしているとき(1600ppm)→窓を開けて(1350ppm)→誰もいないリビングで(650ppm)と移動してみた時のグラフです。

amazonなんかで無線対応のCo2センサはなかなか見つかりませんし、
国内のものでネット対応のものは、謎のメーカ専用クラウドにアップロードされてグラフしか見れなかったりして柔軟性に欠けます。
しかし、このようにすれば生のデータが取得でき、自由に使用することができるという利点があります。
改造にかかる費用も1000円程度です。


Co2センサ自体の正確性ですが…その辺は追々確認していきたいと思いますが、買って半年ぐらいのおんどとり(自動校正無効化)と大体同じ値を表示してくれているようです。

 

raspberry pi picoのGPIO制御速度とマジョカアイリス液晶の制御

皆さんお待ちかねのRaspberry pi PICO 、無事入手したので
早速マジョカアイリス液晶に接続してみることにしました。

最近発売されている普通のRaspberyPi用の液晶はほとんどSPI接続ですが、パラレル接続の液晶を制御しようとすると、それなりのピクセルレートで信号を生成しないといけないため、結構早くGPIOを制御する必要があります。

それだけの信号を生成できるか、まず確認してみます。

 

検索用:「Raspberry Pi PICO GPIO 高速」

 

Raspbery pi PICOはMycroPythonとやらで簡単にプログラムを書けるらしいですが、残念ながら私は ぱいそん はさっぱりなのです。
仕方ありませんのでC言語で書いていくことにします。

ここからいろいろ書いていきますが、C言語での開発環境は公式などを参照してすでにできているものとします。

 

C言語でGPIOを制御するには

付属のSDKの中にある「Blink」を改造して作っていきます。
まず、通常のGPIOを1ピンずつ制御してみることにします。

f:id:honeylab:20210205105100p:plain

このような、単純にforループで出力した場合、1ピン当たり少々遅延して出力されているのがわかると思います。

 

f:id:honeylab:20210205103320p:plain

この時のパルス幅は1.31us*2=2.62us周期、周波数にすると381KHz、決して高い周波数ではありません。

 

forループを展開してみます

f:id:honeylab:20210205105018p:plain

 

f:id:honeylab:20210205103818p:plain

明らかに速くなりました。… forの判定にそんなに時間がかかっているのでしょうか??ここまでの二つは順次ON/OFFでしたが、

今度は一ピンの上げ下げを連続させてみます。

 

f:id:honeylab:20210205104935p:plain

f:id:honeylab:20210205104302p:plain

…何だこりゃ??

一ピンの上げ下げはすぐですが、隣のピンを触ろうとするとまた時間がかかります。

f:id:honeylab:20210205104359p:plain

拡大してみると、一ピンのパルスは10nsで済みますが、隣のパルスの発生まで465nsぐらいかかっています。

これは、gpio_put関数周辺の処理がなんか複雑なんだと思います。
このように、ピンの制御が厳密なタイミングで行えるとは限りません。
クロック同期式ならまぁどうにか通信できるとは思いますが、ちょっと気持ち悪いです。

あれこれ探してみると、複数ビットを一括で制御する関数「gpio_put_masked」もありました。

f:id:honeylab:20210205110106p:plain

これを使ってみると…

f:id:honeylab:20210205110028p:plain

 お、はやいやはい。そして出力も同期しています。
(ずれてるのはたぶんロジアナが悪い)。

この時、周波数は1/70ns=約14MHzとなり、そこそこの速さが出せるようです。

 

では、PICOの売りであるPIO(Programmable IO)の機能を使ってみることにします。

これは、内蔵のステートマシンにアセンブラを食わせて、SPIやパラレル出力、LED制御用のパルス幅デジタル出力などをメインCPUとは別に行うことができる機能です。

詳しくはこちら

blog.boochow.com

などに書かれています。

今回は、マジョカアイリス液晶制御を目標にしているため、もともとSPI液晶用に準備されていたサンプルコードをもとに修正することで超高速パラレル出力を実現させました。

github.com

 

改変したファイルはこのあたりです。
コメント等が修正されていないため、嘘コメント部分があります(ひどい)
そのうちメンテしたい…

まぁ、GPIOがどのぐらい出るか、っていうのを見てみてください。

f:id:honeylab:20210205111222p:plain

この機能を使うと、きちんとクロック同期させたパラレル信号を、CPU時間を消費することなく出力することができます。
PIOファイルを適当にいじったので、もしかするともっと早くできる気がするんですが、いまいちわかんないですこれw

拡大してみると、

f:id:honeylab:20210205111407p:plain

書き込みパルスを5-10nsで生成できているようです。
上にある最短パルス幅に近いようですね。

この方法を使ってマジョカアイリス基板を制御しているのがこちらです。

 まだまだチューニングの余地はあるんですが、結構なフレームレートで画面更新ができている気がします。

 

・まとめ

 速度:遅い順にgpio_put →gpio_put_masked→PIO

 難易度はまさにこの逆です。

 

 

まずは、GPIOの制御方法の違いとその速度、PIOの存在についてこれからラズピコで遊ぶ人の参考になればと思いまとめてみました。

 

「マジョカアイリス」を魔改造して「アイリスオーヤマ」の照明のリモコンにする

さて、ぼちぼち各方面からのハックも佳境となり、
液晶単体での使用や、内蔵リソース書き換えの技術も整ってきました。

そんな中で、どうしてもやらないと気が済まなかったネタが

「内蔵赤外線LEDを使ってリモコン操作をする」ということです。

 

マジョカアイリス、マジョカランタンとの連携のために赤外線LEDが内蔵されています。

 

f:id:honeylab:20210118031026p:plain

せっかくなので、マジョカアイリスを振って何かを操作出来るようにしてみましょう。

 必殺技の発動などの時に赤外線信号が出ますが、あくまでもランタンと連動させるための単純な信号しか出ていません。

 

この信号だけでは外部機器を制御できませんので、マジョカアイリス基板に外付けした小型のマイコンにリモコンの赤外線信号を学習させておいて、この信号をトリガにリモコン信号を出力させるようにします。

これなら、必殺技などのモーションはそのまま残し、リモコンとして使用できます。

 

先駆者として、中身を引っこ抜いて別マイコンに置き換えてエアコンのリモコンにした方はいたようですが、ちょっと中身を引っこ抜くのは私の美学じゃないのですよ…

 

まず、内蔵赤外線LEDの配線を確認してみます。

すると、内蔵LEDは+側ではなく、-側を制御して点灯させているということがわかりました。この信号はあくまでもLEDを点灯させるための制御のため、外付けマイコンのトリガとするのには少し面倒です。

 そのため、そのLED信号を制御信号をいったんフォトMOSリレーに入力し、外付けマイコンに入力することにします。
フォトMOSリレーは内部的にLEDが入っているために、元の基板の回路に与える影響が少ない、という利点もあります。

 内蔵赤外LED自体は一般的なリモコンのLEDと互換性のあるものですので、この部分はそのまま利用することにします。

  

最終的な回路構成はこんな感じです。

 

f:id:honeylab:20210118032014p:plain

Arduinoのリモコン送出ライブラリでは+制御のLEDしか使用できませんので、

-制御の基板のまま赤外LEDを制御するために、赤外LEDの手前に2SC1815を使用した反転ドライブ回路を追加しています。

 

このようにすることで、最小の改造でマジョカアイリスをリモコンにすることができます。
さて、なんのリモコンにするか…派手なアクションをしてくれたほうがいいよな…照明…

 

ん!!! うちの照明 「アイリスオーヤマ」

リモコン付き照明じゃん!!!!

(しかもAlexa連携とかもついてて便利)

https://www.amazon.co.jp/dp/B07J5VTMS2

  

 

まさかのアイリス被り!!!これやこれ!!!

 

というわけで、

リモコン受信モジュールとArduinoを接続してリモコンコードを取得します。
受信モジュールは、マジョカランタンに入っていたものを毟り取りました。

 

 スケッチは、サンプルにあるIRRecvDumpV2を使っています。
ネットで探せばたくさん例が出てきます。

www.shibuya24.info

 

この信号を、マジョカアイリスの赤外線信号をトリガにし、アクション映像が流れた分の時間を待ってリモコン信号として送出するようにArduinoのスケッチを作成します。

gist.github.com

 

Image

Image

こんな感じで適当に配線して突っ込みます。

 

幸い内部には十分なスペースがありました。

Image

ついでに、起動画面をちょっと書き換えてみました。

 

f:id:honeylab:20210118032155p:plain

 

アイリスオーヤマのロゴ、ハートが入ってて意外と親和性が高いのでは…?!

リソース書き換えの方法はこちら

honeylab.hatenablog.jp

 

さて、実際にやってみましょう!!!

 

www.youtube.com

 

 

魔法少女 部屋の電気をつけられるおっさん誕生!!!

 

…あぁぁぁあ! 
ちょっと楽しいぞこれ!!

そういう風に作ったんだから動くのは当たり前なんだけど、
なんだろうこのワクワク感wwww

 

さて、本体魔改造系はこんなもんかなぁ…

 

マジョカアイリスハック

アストロシティミニをほったらかしてこんなことやってました。

 

こちらのblog

kako.com

 

や、Twitterなどで広まって
もはや電子工作おっさんみんなが買っちゃったんじゃないかと思われる
「マジョカアイリス」

 

www.takaratomy.co.jp

詳しい成り行きは各種まとめなんかを見てもらうことにして

 

twitter.com

 

みんな、この横長 64x480 液晶の特殊性と在庫過多による圧倒的値引きにひかれて買いあさってしまったようです。
ところで、この液晶を真面目に使おうとすると、フラットケーブルの処理やマイコンのプログラムなど、すでに電子工作の猛者と化しているレベルでないと
結構処理の難しい工作になってしまいます。

 

 ここまでの工作、結構むずいです。

github.com

しかし、この「マジョカアイリス」、ロットによって本体基板上にmicroSDスロットが搭載されているモデルがあることがわかっています。
このSDカードの中に、おそらく画像や動画が入っているので、これを差し替えてしまえばとりあえず画像が表示できるではないか、というソフトウェア的な取り組みを行ってみました。

 

内蔵microSDカード、2Gのものと4Gのものが現在確認されています。

 中身を一通り確認しましたが、普通のFATフォーマットのパーティション内に、いくつかのフォルダ、データがあるのみです。

この中で、ルートフォルダにあるAB565.binというファイルが、このオモチャの操作中に表示される画像であることがわかりました。

 このファイルは16bitRAW画像データが連結された特殊な形式ですので、これを編集しやすくなるように分離し、再度結合できるようにするツールを作成し、ファイルを置き換えてみました。

 ファイルをいくつか編集してSDカードを更新してみると…

 見事、待機時に表示されるアニメーションが変化しました。

液晶を単体で接続したときのように滑らかに動かすことはできませんが、
この工作、はんだ付け等難しい作業が必要ないため、オモチャハックの入り口としてはそこそこ難易度が低く、結果もわかりやすいのでいい教材かと思います。

 

この作業に必要なC#のプログラムのソースコードは公開しておきます。

 

microSDからコピーしたファイルを使って、このプログラムに読み込ませることでファイルが分離できます。
このソースコード、VisualStudioで作成したものですが、あえてプロジェクトファイルなどは置かず、単一のクラスだけ置いておきます。
そのため、まずはこれをコンパイルして、自分の環境で実行できるというのが最低限必要な力です。それ以下の方はサポートできません。

ここまで登ってきてください。

このソースコードを使って、すでに同様に差し替えに成功されている方もいるようです。

 

 

microSD内には、このほかにもアクション時に再生される動画や音声などが収められていますが、まだフォーマットに未確定の部分があるためその部分の差し替えはまだできません。私の興味が続けばその辺もできるようになるかもしれません。

 

 

 

 

 

アストロシティ解析用メモ(入力回り)

内蔵レバー・ボタン イベント情報

root@z7213-astro-pp:/mnt/UDISK# ./evtest.bin
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0: axp22-supplyer
/dev/input/event1: gpio-keys-polled
/dev/input/event2: sunxi-keyboard
/dev/input/event3: headset
/dev/input/event4: 6B controller
/dev/input/event5: 6B controller
/dev/input/event16: sunxi-ths
Select the device event number [0-16]: 1
Input driver version is 1.0.1
Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100
Input device name: "gpio-keys-polled"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 21 (KEY_Y)
Event code 30 (KEY_A)
Event code 44 (KEY_Z)
Event code 45 (KEY_X)
Event code 46 (KEY_C)
Event code 48 (KEY_B)
Event code 59 (KEY_F1)
Event code 60 (KEY_F2)
Event code 103 (KEY_UP)
Event code 105 (KEY_LEFT)
Event code 106 (KEY_RIGHT)
Event code 108 (KEY_DOWN)
Event code 116 (KEY_POWER)
Properties:
Testing ... (interrupt to exit)

------

^C
root@z7213-astro-pp:/mnt/UDISK# hexdump -C /dev/input/event1
00000000 03 2b 05 00 a8 a2 0c 00 01 00 69 00 01 00 00 00 |.+........i.....|
00000010 03 2b 05 00 bd a2 0c 00 00 00 00 00 00 00 00 00 |.+..............|
00000020 04 2b 05 00 d4 de 05 00 01 00 69 00 00 00 00 00 |.+........i.....|
00000030 04 2b 05 00 e1 de 05 00 00 00 00 00 00 00 00 00 |.+..............|
00000040 05 2b 05 00 40 01 02 00 01 00 6a 00 01 00 00 00 |.+..@.....j.....|
00000050 05 2b 05 00 4d 01 02 00 00 00 00 00 00 00 00 00 |.+..M...........|
00000060 06 2b 05 00 2b 91 0b 00 01 00 6a 00 00 00 00 00 |.+..+.....j.....|
00000070 06 2b 05 00 38 91 0b 00 00 00 00 00 00 00 00 00 |.+..8...........|
00000080 07 2b 05 00 bf 8c 0a 00 01 00 6c 00 01 00 00 00 |.+........l.....|
00000090 07 2b 05 00 ce 8c 0a 00 00 00 00 00 00 00 00 00 |.+..............|
000000a0 09 2b 05 00 73 83 02 00 01 00 6c 00 00 00 00 00 |.+..s.....l.....|
000000b0 09 2b 05 00 80 83 02 00 00 00 00 00 00 00 00 00 |.+..............|
000000c0 0a 2b 05 00 4d 28 02 00 01 00 67 00 01 00 00 00 |.+..M(....g.....|
000000d0 0a 2b 05 00 5a 28 02 00 00 00 00 00 00 00 00 00 |.+..Z(..........|
000000e0 0b 2b 05 00 54 35 02 00 01 00 67 00 00 00 00 00 |.+..T5....g.....|
000000f0 0b 2b 05 00 61 35 02 00 00 00 00 00 00 00 00 00 |.+..a5..........|
00000100 0d 2b 05 00 39 3a 09 00 01 00 1e 00 01 00 00 00 |.+..9:..........|
00000110 0d 2b 05 00 47 3a 09 00 00 00 00 00 00 00 00 00 |.+..G:..........|
00000120 0d 2b 05 00 f7 8c 0d 00 01 00 1e 00 00 00 00 00 |.+..............|
00000130 0d 2b 05 00 04 8d 0d 00 00 00 00 00 00 00 00 00 |.+..............|
00000140 0e 2b 05 00 d8 09 01 00 01 00 30 00 01 00 00 00 |.+........0.....|
00000150 0e 2b 05 00 e5 09 01 00 00 00 00 00 00 00 00 00 |.+..............|
00000160 0e 2b 05 00 16 0a 04 00 01 00 30 00 00 00 00 00 |.+........0.....|
00000170 0e 2b 05 00 23 0a 04 00 00 00 00 00 00 00 00 00 |.+..#...........|
00000180 0e 2b 05 00 0e 6e 06 00 01 00 2e 00 01 00 00 00 |.+...n..........|
00000190 0e 2b 05 00 1a 6e 06 00 00 00 00 00 00 00 00 00 |.+...n..........|
000001a0 0e 2b 05 00 6b bc 09 00 01 00 2e 00 00 00 00 00 |.+..k...........|
000001b0 0e 2b 05 00 77 bc 09 00 00 00 00 00 00 00 00 00 |.+..w...........|
000001c0 0e 2b 05 00 de 4b 0d 00 01 00 2d 00 01 00 00 00 |.+...K....-.....|
000001d0 0e 2b 05 00 eb 4b 0d 00 00 00 00 00 00 00 00 00 |.+...K..........|
000001e0 0f 2b 05 00 e8 30 01 00 01 00 2d 00 00 00 00 00 |.+...0....-.....|
000001f0 0f 2b 05 00 f5 30 01 00 00 00 00 00 00 00 00 00 |.+...0..........|
00000200 0f 2b 05 00 d3 6d 03 00 01 00 15 00 01 00 00 00 |.+...m..........|
00000210 0f 2b 05 00 e0 6d 03 00 00 00 00 00 00 00 00 00 |.+...m..........|
00000220 0f 2b 05 00 db eb 05 00 01 00 15 00 00 00 00 00 |.+..............|
00000230 0f 2b 05 00 e8 eb 05 00 00 00 00 00 00 00 00 00 |.+..............|
00000240 0f 2b 05 00 80 f0 09 00 01 00 2c 00 01 00 00 00 |.+........,.....|
00000250 0f 2b 05 00 8e f0 09 00 00 00 00 00 00 00 00 00 |.+..............|
00000260 0f 2b 05 00 53 6a 0e 00 01 00 2c 00 00 00 00 00 |.+..Sj....,.....|
00000270 0f 2b 05 00 60 6a 0e 00 00 00 00 00 00 00 00 00 |.+..`j..........|
00000280 10 2b 05 00 a8 bc 0c 00 01 00 3c 00 01 00 00 00 |.+........<.....|
00000290 10 2b 05 00 b5 bc 0c 00 00 00 00 00 00 00 00 00 |.+..............|
000002a0 11 2b 05 00 d4 fc 00 00 01 00 3c 00 00 00 00 00 |.+........<.....|
000002b0 11 2b 05 00 e0 fc 00 00 00 00 00 00 00 00 00 00 |.+..............|
000002c0 11 2b 05 00 7d c5 0e 00 01 00 3b 00 01 00 00 00 |.+..}.....;.....|
000002d0 11 2b 05 00 8b c5 0e 00 00 00 00 00 00 00 00 00 |.+..............|
000002e0 12 2b 05 00 53 a6 04 00 01 00 3b 00 00 00 00 00 |.+..S.....;.....|
000002f0 12 2b 05 00 60 a6 04 00 00 00 00 00 00 00 00 00 |.+..`...........|

 

Select the device event number [0-16]: 4
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0xca3 product 0x24 version 0x111
Input device name: "6B controller"
Supported events:
Event type 0 (EV_SYN)
Event type 1 (EV_KEY)
Event code 288 (BTN_TRIGGER)
Event code 289 (BTN_THUMB)
Event code 290 (BTN_THUMB2)
Event code 291 (BTN_TOP)
Event code 292 (BTN_TOP2)
Event code 293 (BTN_PINKIE)
Event code 294 (BTN_BASE)
Event code 295 (BTN_BASE2)
Event code 296 (BTN_BASE3)
Event code 297 (BTN_BASE4)
Event type 3 (EV_ABS)
Event code 0 (ABS_X)
Value 127
Min 0
Max 255
Flat 15
Event code 1 (ABS_Y)
Value 127
Min 0
Max 255
Flat 15
Event type 4 (EV_MSC)
Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)

astro コマンドラインオプション

getopt_long(in_stack_00000038,in_stack_0000003c,"hb:w:e:o:a:s:d:z:v",in_stack_00000030)

バーチャ1

293 root 274m R astro -b SGM01X-01 -o lcd -d 20 -e none

コラムス

398 root 248m S astro -b SGSC2X-05 -o lcd -d 20 -e none

dに20以外を設定したら単体起動できた なぜ

 

astroの入力ルーチン

アストロシティミニでRetroArch-MAMEを動作させてみた

さて、ここまでいろいろやってきた中で

honeylab.hatenablog.jp

 

どうも、メガドラミニで動くProject Lunarからファイルを引っ張ってくれば、さらっとRetroArchが動くのではないかという結論に達しました。

modmyclassic.com

 

現時点では、はんだ付けやシリアルコンソールへのアクセスが必要ですが、
ほんの少しの修正を行うだけで、とりあえずRetroArchを起動させることができました。

ただし、例えば動的なLCDHDMIへの出力変更周りなどはサポートされていないため
諸々調整をすれば問題なく使用できそうです。

 

RetroArch自体はProject Lunarへのパッチで動くレベルだと思うのですが、
メガドライブミニではFELボタンがあったのに対し、PCエンジンミニはUSB FELモードへの突入部分の調整や、Linuxカーネルの書き換えを行わないとMDminiゲームパッド以外使用できないためその辺は時間がかかりそうです。

 

また、出荷時に内部に格納されたゲームのデータの一部は、変換さえすれば
MAMEで読み込み可能な形式に変更できる可能性があることがわかりました。

 

これをもとに、内蔵エミュレータではなく、RetroArchでぷよぷよ通を動かしてみたのがこちらです。

 

以下に、今後自分必要そうなメモを書き残していきます

・音声出力先の変更 

root@z7213-astro-pp:/mnt/UDISK/retroarch# amixer -c 1 cset name='Speaker Function' 1
numid=27,iface=MIXER,name='Speaker Function'
; type=ENUMERATED,access=rw------,values=1,items=6
; Item #0 'headset'
; Item #1 'spk'
; Item #2 'spk_headset'
; Item #3 'earpiece'
; Item #4 'btout'
; Item #5 'bt_button_voice'
: values=1

LCDHDMIの変更

 change_output.sh 1  #HDMI出力、720p

 change_output.sh 1  480 #HDMI出力、480p

 change_output.sh 0 # LCD出力

  ※ LCDHDMIでは縦横が違うので、Video Rotate Settingを変更する必要あり

※音声切り替えはRetroArch切り替え後でもOK、映像はRetroArchの再起動が必要

・USBネットワークデバイスの有効可(WindowsのRNDISドライバ経由、インターネット共有使用可能)

echo rndis,acm > /sys/class/android_usb/android0/functions
echo 0 > /sys/class/android_usb/android0/bDeviceClass
echo 1 > /sys/class/android_usb/android0/f_rndis/wceis
echo 1 > /sys/class/android_usb/android0/f_acm/instances
echo 1 > /sys/class/android_usb/android0/enable

ifconfig rndis0 up
udhcpc -i rndis0

 

も~っと アストロシティミニ 内部にアクセスする 詳細

honeylab.hatenablog.jp

 

↑前回に引き続き、より詳しいことが分かったのと、
意外とこのブログが(ゲームギアミクロの時より圧倒的に)読まれていることが分かったのでもう少し詳しく書いてみます。

 

まず、基板詳細図のアップデートです。
UART端子が見つかりました。
これにより、シリアルポート経由でシステムのより深い部分まで解析できました。

f:id:honeylab:20201220002333p:plain

基板上にあった4ピンの並び、一般的な組み込み機器だと 電源-GND-TXD-RXDみたいな配置出てていることがあるんですが、今回ここに出ていたのは RXD-GND,そしてI2Cの信号モニタ用の端子でした。
どうも、IC7がセキュリティ用のチップであり、そのチップに対するアクセスのデバッグ・観測などのためにこのピンを設けていたのではないかと思います。

 

さて、シリアル端子を使ったシステム解析の方法をせっかくなので書いてみます。

実際に手を動かして試すこともできない方も多いと思いますので、これを見ながらなんとなくイメージしてみてください。

本体裏から基板にアクセスし、USB-シリアルケーブルなどでPCと接続します。

今回、シリアル通信ソフトはRloginというものを使っています。

 

f:id:honeylab:20201220002956p:plain

接続がうまくいくと、電源投入時にこのような出力が見えてきます。

f:id:honeylab:20201220003031p:plain

ログインプロンプトが表れます。

ここで、ユーザ名はroot、ですが、パスワードはわかりません。

これではここから進めません。
いったん電源を切り、ターミナルから's'(小文字のs)を押しながら電源を入れなおします。

すると、さっきより詳しい起動メッセージが表れます。

f:id:honeylab:20201220003331p:plain

さらに、Linuxが起動する前のブートローダである、u-bootのモニタモードで起動できます。

この時のログをこちらに置いておきます。

 

gist.github.com

u-bootのモニタモードでは、ブートローダ環境変数Linuxの起動オプションなどを確認、変更することができます。

「help」コマンドで使用可能なコマンド一覧が表示されます。

f:id:honeylab:20201220003557p:plain

さて、ではここからどうするか。

Linuxを起動した際、パスワードを求められたのはログインシェルが起動したからです。
これを起動せず、コマンドラインを使用できるようにする方法があります。
一般的なLinuxディストリビューションでは、起動後に/sbin/initを呼び出し、自動実行スクリプトやログインシェルの起動を行います。これをストップし、最小限であるbusyboxのシェルだけが起動するようにLinuxコマンドラインを書き換えてしまいます。

(※詳しく書くとアレなのでここは割愛します)

 

このモードで起動すると、パスワード入力など関係なく、rootファイルシステムがマウントされ、busyboxのシェルが起動した状態にすることができます。

f:id:honeylab:20201220003909p:plain

いきなり / # というコマンドライン入力待ちになりました。
しかし、この状態ではいつものアストロシティのゲームは動いていませんし、ファイルシステムのマウントも不十分な状態です。緊急レスキューモードみたいな感じです。

この状態で触れる範囲でこねくり回してやり、改めて通常のLinux起動状態にした際に、パスワードを入れなくてもログインできるようにしてしまいます。

幸い、この状態でrootfsはinitramfsではなくNAND完全にマウントされていて、しかもrwの状態でした。
ここで、/etc/passwd ファイルを見てみます。

f:id:honeylab:20201220004257p:plain

すると、rootの行、赤丸で囲った部分に"x"と書かれています。
これは、rootのパスワードは別途 /etc/shadow に記載されている、という意味です。

では、/etc/shadowは、と見てみると

f:id:honeylab:20201220004400p:plain

rootの行に$6から始まる長々とした文字列が書かれています。
これは、rootのパスワードはSHA512で暗号化されて保存されている、ということです。
実は、メガドラミニ→PCEミニ→アストロシティミニは同じ開発会社によるLinuxディストリビューションが採用されています。
メガドラミニではSoCの名前を含む短めの文字列だったのですが、その後、暗号化強度が増している気がします…気のせいかもしれませんが…
本当に必要ならば、このハッシュを結果にもつ文字列を総当たりで探すこともできるのですが、それは今回時間の無駄です。もともとの/etc/passwordの中の'x'を削除してしまうだけで、/etc/shadowは参照されなくなります。また、パスワードは空になります。

f:id:honeylab:20201220004749p:plain

今回はこのファイルを含むファイルシステムがマウントされていたためこの手法がうまくいきました。

では、パスワードを削除した状態で改めてLinuxを通常起動に戻します。

 

f:id:honeylab:20201220004916p:plain

ユーザ名にrootを入力するだけで通常のLinuxとしてログインできるようになりました。

ここから、システム内部を詳しく調べていきます。

まず、SoCはAllwinner A33互換のZ7213とわかってはいますが、Linuxからどのように見えているかをコマンドで確認します。

f:id:honeylab:20201220005108p:plain

スペック通り、Quad CoreのARM7プロセッサだということがわかります。

f:id:honeylab:20201220005227p:plain

/usrに移動すると、astroディレクトリが見えます。
中を見てみると、75MBの容量を持つ一つの実行ファイル'astro'が見えます。
サイズからして、この中にROMイメージも埋め込まれているのでは、と考えられます。

 

さて、このようなシリアルコンソールからだけでもある程度の観察は可能ですが、ファイル自体が手元にないと逆アセンブルやリソース吸出しなどは困難です。
内蔵されているLinuxはゲーム専用にシュリンクされていますから、USBメモリなどを使用することができません。
しかし、カーネルオプションとして、Android Gagetと呼ばれる仕組みが偶然なのか残されていて、所定のオプションを設定してPCと接続するとデータ通信が可能になります。

まず、システム上のNANDがどのような構成になっているかを確認します。

先ほどのu-bootの起動メッセージ中にはこのような表示がありました。 

 

f:id:honeylab:20201220005835p:plain

Linuxからはこのように見えているようです。

f:id:honeylab:20201220005910p:plain


root@z7213-astro-pp:/usr/astro# cat /proc/cmdline
boot_type=0 disp_para=100 fb_base=0x0 config_size=48128 boot.serialno=28078a547088ffffd979 boot.hardware=sun8i console=ttyS0,115200 noinitrd root=/dev/nandd rootfstype=ext4 rootwait init=/sbin/init ion_cma_512m=64m ion_cma_1g=176m ion_carveout_512m=96m ion_carveout_1g=150m coherent_pool=4m loglevel=0 partitions=boot-res@nanda:env@nandb:boot@nandc:rootfs@nandd:savedata@nande:misc@nandf:UDISK@nandg

cmdlineとも合わせて確認すると、例えばこのrootfsを含むパーティションはnanddであると考えられます。

このパーティションを、USB経由でPCに認識させます。

echo 0 > /sys/class/android_usb/android0/enable
echo mass_storage > /sys/class/android_usb/android0/functions
echo /dev/nandd > /sys/class/android_usb/android0/f_mass_storage/lun/file
echo 1 > /sys/class/android_usb/android0/enable

そう、アストロシティミニの背面電源USB端子は、電源だけでなく、データ配線もきちんと有効になっています。
それを利用するため、USBケーブルでPCと接続します。
データの取り扱いのためにはLinuxのPCが一番便利ですが、簡単にやるにはVMWareなどのUSBパススルーの使えるVMでもいいでしょう(私はそうしています)

PCと接続した状態で上のコマンドラインを打つと、USBメモリが接続されたように見えます。

注意点としては、Windowsマシンの場合、このコマンドラインでは「このディスクはフォーマットされていません」などのメッセージが表示されます。
このパーティションは、Linuxの標準であるext4パーティションであり、Windowsからは全く認識できません。
うっかりフォーマットしてしまうと、アストロシティミニが見事にお陀仏になりますので気を付けましょう。この場合、VMに接続し、VMLinuxから認識させます。

f:id:honeylab:20201220010706p:plain

このように、/dev/sdbとしてNANDのrootfsパーティションが認識されました。

あとは、ddコマンドでパーティションをまるごとファイル化します。

このようにして、解析に必要なパーティションを回収します。

f:id:honeylab:20201220010855p:plain

回収したファイル、ここではnandcをファイルシステムとしてマウントしてみます。

すると、

f:id:honeylab:20201220011401p:plain

linuxカーネルイメージ、uImageファイルが置かれたfat32ファイルシステムだった、ということがわかりました。
今後、新しく作ったuImageファイルはこのパーティションにおいてやれば読み込んでくれます。

rootfsも同様にマウントします。

f:id:honeylab:20201220011646p:plain

PC側でファイルにアクセスできることが確認できました。
ここまで来てしまえばあとはなんでも調べ放題です。
ファイルを一通り調べて、動きを確認したければシリアルから動作を確認する、それを繰り返してシステムの全体を把握していきます。

とはいえ、もうこのZ7213のシステムはハードも大体固定なので、これまでに作られた各種バイナリを持ってくれば大体動いちゃうんですよね…

 

解析はこの後もまだまだ続きます。