前回までにMSXとATmega328Pの送受信ルーチンが完成したので、いよいよ肝心なATmega経由でのSDカード読み書きを実装していきたいと思います。
プログラムの前に決めておかなければならないのが、読み書きするファイルのフォーマットをどうするかです。
一番行いたいことは、PCにインストールされているz88dkで作成したプログラムをそのままSDに書き込んでMSX側で実行させるということなので、z88dkがコンパイル後に出力する.casファイル(openMSXなどのMSXエミュレーターでも直接読み込める形式)を扱うことにしました。
ただし、今回扱うのはバイナリファイルだけで、同じ.cas形式のBASIC中間言語ファイルやアスキーファイルは扱いません。z88dkはCかアセンブラをコンパイルしてバイナリ出力するだけですし、BASICファイルを読み込んだ後の内部処理について個人的にまだ分かっていないためです。
また、.casファイルに対応するためMSX側のSD読み書きコマンドも若干変更しました。
SDからの読み込み IPL L "ファイル名"
SDへの書き込み IPL S "ファイル名",開始アドレス,終了アドレス[,実行アドレス]
IPL Lコマンドでは、読み込み後に設定されている実行アドレスからプログラムを実行します。
IPL Sコマンドでは、オプションとしてプログラムの実行アドレスも指定できます。省略したときは開始アドレスが実行アドレスとして設定されます。
以前にも書きましたが、SDカードのサブフォルダは無視します。とくに理由はなくただの手抜きです。
以上の仕様をもとに前回までに作成したプログラムにSD読み書きルーチンを実装してみました。プログラムは以下の通りです。
MSXのプログラム(マウスの右クリックで保存してください)
Makefile
loadsave.asm
ATmega328Pのスケッチ(マウスの右クリックで保存してください)
ATmega328MSX_SD.ino
MSX側のアセンブラソースはこれまでのようにz88dkでコンパイルします。makeを実行してloadsave.wavを作成したら、以下のコマンドでMSXのカセットインターフェイスから読み込み実行させます。
clear 0,&hdfff (BASICプログラムを使わないとき)
bload"cas:",r
IPL Sコマンドで指定するファイル名ですが、ArduinoのSDカードライブラリではMS-DOS形式のフォーマットを扱うため8文字+拡張子3文字の形式で大文字小文字を区別しない名前になります。SDカードで扱えないファイル名を指定するとエラーが表示されます。
ちなみに今回のIPLコマンドでのエラー処理はかなり手抜きをしています。どんなエラーが発生しても表示はIllegal function callだけですので、ご了承ください。
アセンブラソースでは、現時点でプログラムの開始番地をE000としていますのでこれと番地が重複するプログラムを読み込むと暴走します。将来プログラムが完成したときにはできるだけ他のプログラムの邪魔をしないようにメモリの隅に移動するつもりです。ただz88dkで作成したプログラムは通常9C40番地から配置されるようになっているので、メモリを大量に使用するプログラムでなければ問題にはならないでしょう。
ところで前回までMSXとATmega328Pをブレッドボード経由で接続していましたが、ブレッドボードが邪魔くさいので直接接続するケーブルを作成しました。
このときケーブルの配線に都合いいように接続ピンも変更してしまいました。そのため上記スケッチの#define文のピン番号が変更になっています。一応、前回までのピン番号はコメントとして残してあります。
依然としてATmegaにはデバッグ用としてoledがつなげてありますが、ほとんど活用してないのでスケッチからoledの記述を削除しても問題ありません。
ところでSDカードの抜き差しのタイミングについてですが、Arduinoの場合は電源を落としてから行うのがいいみたいです。(という話をどこかで読んだような気がするだけですが。)
でも、今回の使い方としてMSXの電源を落としてしまうと再度SDカード読み書きプログラムを読み込まなければならず面倒なので、電源を落としていなくてもIPLコマンドを処理していない時ならいつでもSDカードの抜き差しを行えるようにしてあります。
ただし、これは推奨される使い方ではないかもしれないので操作は自己責任でお願いします。
スケッチ書き込み後に手っ取り早く動作確認したい場合は、z88dkのサンプルを使うと簡単です。z88dkのexamplesフォルダの中でmakeを実行すると.casファイルがたくさん作られます。例えばこの中のglobe.casをSDカードに書き込んでipl l "globe.cas"と入力するとプログラムが読み込まれて実行されます。
プログラムのロード中、画面右上に読み込まれているキャラクタが次々と高速表示されます。PC-8801とかのマシン語モニタのテープ読み込み時に表示されるアレです。なんとなく真似したくてつけてみました。
自作のプログラムを試したければここのようなCプログラムをhello.cという名前で作り、次のコマンドでコンパイルすれば.casファイルが作成されますので、SDカードに書き込んでMSXでipl l "hello.cas"で動作確認できます。
zcc +msx -lndos -create-app hello.c -bn hello.cas
このhello.casは9c40〜a402番地にロードされるようになっていたので(.casファイルの33バイト目から開始・終了・実行アドレスの順で入っている)、上記プログラム実行後に ipl s "hello",&h9c40,&ha402 と入力すればSDカードに別のファイルとして保存されます。
確認のため今度はipl l "hello"と入力すると、いまセーブしたプログラムが読み込まれ実行されますので正常にセーブされているかどうか確認できます。
これでやっと実用的に使えるところまで出来ました。ファイル操作のコマンドを後2つほど追加して完成とするつもりです。
手持ちのMSX1にはRAMが64KBあって32KBがBASICでは使わない裏RAMとなっています。将来的にはこのプログラムのMSXBIOSを利用していない部分を裏RAMに持っていってメモリ使用領域をより少なくしたいと思っています。が、実現できるかどうかはまだわかりません。
最新の画像[もっと見る]
- ラスベリーパイのベアメタル環境でLVGLを使う 5日前
- ラスベリーパイのベアメタル環境でLVGLを使う 5日前
- ラスベリーパイのベアメタル環境でLVGLを使う 5日前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
- ILI9341搭載のタッチパネルをLVGLで利用する 2週間前
※コメント投稿者のブログIDはブログ作成者のみに通知されます