アイマスMADをMZ-700実機で再生するまでの道のり

 それは2008年8月2日のこと。PC-6001ユーザーvsMZ-700ユーザーのニコニコ動画における常軌を逸した争いの末、ついにMZ-700でもソフトの力で動画再生が可能になったところから物語は始まる…。


8月2日〜3日:発露

 各種レトロPCエミュレータ開発で有名な武田俊也氏(たけだP)が、EMMに置いたデータを、ラスタごとにアトリビュートエリアを操作する方法で解像度を増し、カラーで動画再生する方法の開発に成功したとのこと。その動画をニコニコ動画で公開している。たけだPは実機を持っていなくて全てエミュレータでの開発だが、アイマスオープニングや野球拳2000などを正確に実行・再生できるエミュレータをすでに開発しているため、その動画(アイマスMAD)も問題なく再生できることになる。
 対応するエミュレータとデータがダウンロード可能だったのと、ちょうどEMMを含むボードを製作中だったのでそれで再生できたら楽しいなと思ってそのデータを見てみたら、なんと20MB…。純正(といってもアイ・オーデータ機器だが)を逸脱しない範囲での拡張をしたとしても16MB。もちろん逸脱してしまえば何でもありだが、それはちょっと面白くない。

 関係者の日記なんかに「残念、大きすぎるよ」などとコメントしたら、武田氏から「16MB以内に収めたデータを作るから実機でぜひ」という旨のコメントが返されてきた。さらには新たな動画データの説明文に「次はハード担当の方がネタを投下してくれるでしょうwktk」…。

 これはハード担当に対する挑戦か!?ならば受けて立たねばならない。今作ってるボードの作業を中断して、目標は14日晩のMZ-MLオフ会…うーん、きびしい。せめてもう1週間早ければ…。


8月4日〜6日:仕様検討

 さて、完成目標まで2週間弱、いや週末から夏季休暇とは言えそれまでの平日はほとんど作業できないと思われるので、実質1週間。まぁ今年は手前に一日有給をくっつけたのでもう一日あるわけだが。作業にとれる時間があまりないこともあり、できるだけ「有り物」を使って開発要素を減らしておく必要がある。

 構成は、おおざっぱにはEMMとその初期化機構の二つ。
 まずEMMはMZ-700の場合HuBASICでサポートしているので、それを実装することに。アドレスは$00〜$02がアドレス設定、$03がデータの読み書き。武田氏の当初の仕様ではアドレスのオートインクリメント以外いろいろと違っていたのを純正に合わせてもらうということで話が付いており、ここは安心して実装できる。しかしこのアドレス、コーディング中にアドレスを決定するはずがその作業を忘れたままリリースしたのではないかという気がしてならないのだが…。
 EMMを16MB実装するとなると、これだけの容量を構成するにはDRAM以外あり得ない。いや、最近はフラッシュメモリも安くなってきたからと調べたのだけれど、めぼしいものはなし。DRAMにするとして、手元には512MBのDIMMモジュールが余っているのでそれを使おうとソケットを探すも、売っている店は見つからず(Digi-Keyならありそうだが、配送時間を考えると国内の業者に限定したいところ)。メモリチップを外すという手もあるがボードに並ばないような気がするのでそれも見送り。
 とするとあとはSIMMを使うという方法。30pin SIMMモジュールも余っているけど、見ると256KBとかばっかりなので使えない。というか、そもそも4MBまでしか構成できない仕様じゃなかったっけ。とすると72pin SIMM、余ってはないけどもうDOSしか動かさないから取り外せるやつがあるな。SIMMのソケットを通販で探してみたけどこれもないみたいなので、もう使いようのないSocket4マザーから取り外そう。憧れの斜め実装ソケットなので、出来上がりもかっこいいに違いない。ということでこれは6日の晩に半田吸い取り器とか使って無事ゲット。まだ新品が手に入る可能性もあるので、基板に取り付けないでおく。でも見ると足が千鳥になってるな。どうやって取り付けようか?
 SDRAMではなく普通のDRAMを使うことになったので、書庫からトラ技スペシャルを取り出して回路の検討。

 次に初期化機構。
 動画データが8bitマシンとしては途方もなく大きいので、適当なストレージに入れておいてそこから読み出すのが適当か。とすると有り物の筆頭はSDカード。ストロベリー・リナックス取扱いのDOS on chipなんかが後のソフト作成も含めて楽そうなんだけど、品切れでは…。ヒューマンデータのALFATチップ使用のボードもひとつ手元にあるんだけれど、これはこれでALFATのコマンドがいまひとつ使いにくく(連続で255バイトまでしか転送できない、もちろん繰り返せばいいんだけど…)、乗り気がしない。転送速度も問題ありそう。
 とすると直接SDカードをアクセスしたくなるのだけれど、FATファイルシステムのアクセスプログラムはやはりそれなりに大きい。I/F初期化だけがんばって、あとは特定のセクタにデータがあるという前提を作ればアクセスする側はシンプルになるけど、データの準備が大変。とすると、1chipMSXへのMZ-700実装でAVR-Coreの実績を買って、それを引っ張ってくるのがいいかな。すると自動的にFPGAを採用することになるが…手持ちにFPGAとコンフィグROMの予備があるけど工作が大変だし…。
 ならばオプティマイズEZ-FPGAにするか。使用されているFPGA(XC2S100)ならAVR-Coreも入るだろうし、5Vトレラントなので今回のデバイスを接続するには好都合。ブロックメモリの少ないのが悩みどころだけど外付けすればしのげるかな。ただ、AVRのプログラムメモリって16bit幅なんよね。ROMをふたつ並べるのは面倒…。

 あ、ならば16bitバスのROMを用意すりゃいいんじゃん。単純な話だ。通販サイトをいくつかチェックして、でもこれは出張のついでに店頭で買うことにして。それとSRAMもチェックしておこう。どちらにしても、AVR-CoreをZ80と同じクロックで動かすとすると250ns、いやその半分の125nsで読み書きできないと辛いと思われるので、選定基準はそのあたりに。あ、EZ-FPGAは発注しておこう。


8月7日:部品集め

 東京出張のついでに秋葉原に立ち寄り。足らない部品、使いそうな物はこのチャンスに買っておかないと。

若松通商にて85nsの32KB SRAMを購入。次いで16bit幅のEPROMを買おうとしたが、120ns品だったので敬遠。
千石電商に行くと95ns品のROMを発見。あ、70nsのSRAMがある。若松より安い…。
そんな都合のいいものはないので、千鳥→平行に端子配列を変換する基板を千石にて購入。
DRAMダンピング抵抗用に、10Ωとか。100本入りを、予備としてもうちょっと高い抵抗値も併せて千石の地下にて購入。
別の動画を見るのにMZを再起動というのは使いにくいので、AVR-Coreだけリセットできるようにする押しボタンスイッチと、ファイル選択を多少でも可能にするためのロータリースイッチをマルツ電波にて購入。ロータリースイッチはコンプリメンタリのものしかなかったけど、みんな敬遠してるのんかしらん。
SIMMソケットのための基板は買ったものの、どう固定したらいいものか困り、それなら細い穴をあけて一列はそこから出すか、あとは接着剤でくっつければ…という考えもアリとしてHOZANの細いヤスリセットをマルツで購入。

 その他、基板やSDカードスロット、SRAMとEPROMのソケットは手持ちにあるので購入せず。逆に72pinのSIMMやSIMMソケットがないかと探したものの、発見できず。まぁ、SDRAMやDDRがジャンクで売られる時代ではなぁ。

 帰宅して、基板の加工。SIMMソケットの足のための細い穴をヤスリでガリガリ。それとスロットに合わない端子も切り落とし。それと基板にスロットを載せてみて、SIMMでどこまで基板を覆うか確認したくなったので半分眠りかけのDOS/VマシンからSIMMを取り出し。何枚もあってどれがどんな容量だったか忘れたな…。このチップ数の多いのは32MBか…。まぁEMMの仕様を超えてもしかたないので、こっちの16MBにしておこう。故障だった場合に備えて予備も取り出して。


8月8日:EZ-FPGA来る

 朝にEZ-FPGAが届いたので、組み立て後位置合わせ。縦にするか横にするか、考えた末に横にして余りスペースを確保する作戦を選択。Z80のクロックを入力する端子の位置を考慮に入れて…。

 開発では後半になるので配線はしないけど、SDカードスロットとスイッチ類、AVR用外部メモリのソケットを配置しておく。まだAVRのソフトに手を着けてないので確定ではないけれど、FPGA内蔵の5KBメモリではプログラム収容は無理と判断し、16bit幅ROMのソケットを取り付け。で、FPGAとSIMMの電源を配線。

 EZ-FPGAのJTAG端子についてはちょっと思案。配列がDigilentのJTAG3とは異なり、しかも2階建ての上につくのはちょっと邪魔かも。EZ-FPGA添付のコネクタって普通のじゃなくて、PC/104用なのでさらに背が高いんよね。配列はXilinx純正のフライングケーブルでどうにでもなるとはいえ、一本一本配線するのはさらに面倒。
 ならばと、信号をいったん基板に降ろして、改めてJTAG3配列に並びかえ。どうせ何回もケーブルの付け外しをするはずなので、こうしておくほうが効率がいい。

 電源が配線できたので、勢いに乗ってZ80バス信号も…。FPGAだからあまり端子の位置を気にしなくてもいいのが楽だわ。


8月9日〜10日:DRAM

 DRAM関係の信号を配線。SIMMは日立のHM5117405が使われていたので、データシートをネットで探して検討…。こいつはアドレス11bit、データ4bit構成で、8個並べて32bit幅にしている。RASを共通にして、CASが4本使われており、それぞれデータラインの8bitずつを担当している。ということは、アドレスの下位2bitでどのCASを使うか選択するようにすると、きれいに使えるというわけか。複数の8bitレーンを同時にアクティブにすることはないので、D0-D8-D17-D25(パリティがあるのでずれている)…などと接続して8bit幅のSIMMにしてしまおう。
 アドレスや制御線などダンピングが必要なやつは抵抗で直接配線。時間もないのでかなり手抜きに、時々テスターで信号を確認しながら配線…。

 夜になって配線が出来上がったので、今度はFPGAでEMMとDRAMコントローラの製作。EMMは多少アドレスレジスタの構造が違うものの、以前CPLDに実装したものがあるのでそれを流用。

 さて、肝心のDRAM。DRAMの回路とか考えたことなかったんよね〜。
 本によればZ80の場合MREQを利用してRAS・CASを作るようになっているのだが、EMMはI/O空間にあるものなので代わりにIORQを使用することとする。CASはRASを1クロック叩いたものを使用すればいいらしい。バスコネクタにRFSHが出てないのでリフレッシュはCASビフォアRASにしたいと思ったのだが、タイミング設計が難しく(というか時間不足で切羽詰まってると思考が働かないのかもしれない)無難にRASオンリに落ち着く。但しRFSHがないのは変わらないので、M1とMREQの論理を取って命令フェッチ時にリフレッシュすることにする。命令フェッチはI/Oアクセスとぶつかることはありえないし。今更で恥ずかしい気もするが、Z80のリフレッシュ機構はRASオンリを前提として作られていたことを、文献にてようやく理解。確かにこれは便利だわ。

 それなりのものができたところで実機でチェックするも、そう簡単に動くはずもなし。ロジアナでチェックするか迷ったが、ここは久々にシミュレータで確認してみよう。グラフィカルにパターンを指定するほうが簡単かと思ったが、なんかやりにくいのでテストベンチを作成するという至極まっとうな方法に落ち着く。でもベンチで使える文法がよくわからない…。
 それなりの波形ができたのでシミュレーション。波形を確認しつつ、実機とシミュレーションを往復するも、なかなか解決しない。実機での確認はEMMをサポートするHuBASICで行っているが、まだEMMの機能は使わずI/Oポートを直叩きしているだけ。読みだされる値が不定値みたいで、しかも何を書き込んでも値に変化が現れない。ところでこの程度のテストなら別にHuBASICでなくともよく、ロード時間が長いのでS-BASICに切り替えたものの、I/Oポートの命令が思い出せずHuBASICに逆戻り…。いや、マニュアルを調べればいいのだけれど、その時間も惜しい…。

 本をよく読むとCASの後に書き込み信号が有効になるようなタイミングだと、容量の大きなDRAMではテストモードに入るらしい。こちらのデータシートを確認しても確かにそのように書いてある。まぁ容量の問題ではなく、製品としての新しさなんだろうけど。で、シミュレーション波形を確認してみるとCASと書き込み信号は同時っぽい。これが問題かな、とRASの半クロック後に書き込み信号が出るようにしてみたものの、変化がない…。

 …ん?そういえばこのシミュレーション波形、Z80側データバスがずっとZ状態に見えるんだけど…あ、もしかしてZ80の方へデータパスを有効にしていなかったのか!これを変更すると…おお、動いた!!HuBASICからはちゃんとRAMディスクに見える!!!値も化けないし消えないので、リフレッシュもうまくいってるみたい。よしよし、いい調子。思ったより早くここまできたな。


8月11日:シリアルポート

 EMMはRAMディスクの管理領域と若干のデータ領域を確認しただけなので、全体をチェックするテストプログラムを別の作業中に走らせようと思っていたのだけれど、それは無理だということを悟った。AVR-Coreを実装するのに先立って、デバッグ用にシリアルポートを設けようと思いついたのだが、そのためにレベルコンバータを基板に載せる改造が必要なのだ。つまり、ボードをいじるからテストどころではない。
 レベルコンバータは以前に秋月で買っておいたADM3202を使用。送受信するつもりはないので、送信だけの回路を配線。片側だからコンデンサもこれだけ?コネクタは以前USBホストを組もうとしてデバッグ用に使用したケーブルがあるので、それが使えるようそのUSBの基板から拝借。

 端子番号が配線することで決まったので、シリアル出力ブロックをコーディング。AVR-Coreはまだないので、MZ-700で叩けば送信できるようにレジスタを増設。昔別のプロジェクトで使ったのを流用してきたので、簡単に終わると思ったら…動かない。ターミナルソフトには化けた文字。ボーレートの設定やカウンタは間違えてないし。
 やむなくこちらもベンチを作ってシミュレーション。なんか遅いなー、えらくゆっくりしたパターンだな…と思ったけど、そりゃ9600bpsは遅いわな。パターン数を増やしてようやく1バイト分確認。
 ロジックとしてちゃんと動いているとすると、直接端子を見ないといかんか。というわけでオシロを取り出し観測…なんか電圧が低いような?こんなもんなのか、今時のRS232Cは±15Vではないからよくわからんな…。でも他にいじってもボーレート変えても結果は芳しくないし、レベルコンバータの実装で手抜きしたのをちゃんとつけるようにしてみるか…。む、ちゃんと動く。やっぱり横着はいかんということか…。

 しかしここで思わぬ道草を食ってしまった。簡単に終わると思ってたんだけどなー。


8月11日〜13日:AVR-Core

 次はいよいよ本命のAVR-Coreの実装へ。MZ-700 on 1chipMSXの方で使っているソースをごっそりコピーしてきて、モジュールを接続。ブロックRAMは4KBをプログラムメモリ(つまりROM)として、残り1KBをワークRAMとして構成。
 ROMにはGCCでコンパイルしたものを埋め込む。MZ-700 on 1chipMSXでやった、ソフト的にメインプログラムを後から読み込む方法は、ソフト開発を考えると必須と言いたいところだが、その仕組みを考え実装する手間が惜しいので、手作業でソースに埋め込むことにする。ただ普通にコンパイルするだけだと1行16バイトのインテルHEX形式のファイルになるので、srecordにて横32バイトのモトローラSフォーマットに変換。あとは手で加工することにして。

 非常に簡単なテストプログラムを作成する一方、チェックのためにEZ-FPGAの未接続LEDに配線。近辺の空き端子を利用して…。
 ROMとして使用しているブロックRAMはデータバスを16bit幅とするよう設定したものの、埋め込んだプログラムがどのように読み出されるか全くわからないので、そこはシミュレーションで確認することに。ベンチを作って実行してみると、一応隣り合う2バイトずつ出力されているようなので、プログラムの埋め込みもこのままでよさそう。けど、いまいちプログラムが動き出していないみたい。MZ-700 on 1chipMSXの時も見たのだけれど、リセットベクタ(といいつつただ0番地の命令を実行しているだけ、しかもその命令とはプログラム先頭へのジャンプ命令)が実行されずに次の番地に素通りするというのは、ワードの上位下位が入れ替わってる時の現象。その入れ替え作業の中でちょっとすったもんだしたけど、シミュレーションでも正しく命令を処理し始めたので、実機に移行して動作を確認。

 DRAMにデータを書き込むことから、AVR-CoreにもEMMアクセスの機構が必要。アドレスレジスタとかZ80のものと共用したいと考えれば、AVR-CoreにZ80バスと似た信号を生成させて、Z80の代わりに駆動してやるのが楽か。とするとパスを切り替えることになってしまうけど、そこで問題になるのがDRAMのリフレッシュ。今のリフレッシュはZ80の命令実行時の信号を利用して行っているわけで、パスを切り替えてもそれを生かしてしまうとAVR-Coreのアクセスとリフレッシュが衝突してしまうだろう。とすればAVR-Core側にもリフレッシュ機構を設けないといけないのだが…そもそも内部パスを無理やり引っ張りだして使っているような状態のAVR-Coreだから、プログラムも込みだとどんなタイミングとどんな間隔でアクセスするのか見当もつかん…。まぁDRAMだからってリフレッシュをやめたらいきなり消えてしまうこともないだろうから、まずはリフレッシュなしでやってみよう。
 それと、外から見て分かりやすいように、LEDのひとつをバス切り替え信号に接続。このLEDが点灯している時はパスはZ80側にあるということだな。

 動き始めたということで、本格的にSDカードアクセスとFATファイルシステムの実装。構造はMZ-700 on 1chipMSXのもの、というよりは初期化とか細かいアクセスが改良されていたりファイルシステムライブラリのバージョンが上がっているので、SASI-SD/MMCアダプタのものを流用。今回はカードへの書き込みがないので、ライブラリのオプションでもってもうちょっとバイナリのサイズが小さくなりそう。
 FPGAもSPI I/Fの追加。これはMZ-700 on 1chipMSXの流用だけれど、そういえばあっちはかなり高い周波数のクロックを分周する構造だったな。今の構成だと最も高い周波数でもZ80の3.58MHz、とするとなんか高い周波数のクロックを用意しないといかんか…。幸いにしてEZ-FPGAには表面実装型のクロックモジュールを実装可能で、しかも以前USBホストを作ってた時の48MHzの余りがあったので、これを使おう。

 さて、ソフトとかのコンパイルも通るようになったのでバイナリのサイズを確認してみよう…えっ、4KBを超えてる?!そんな、ChaNさんのサイトでの説明なら2500バイトくらいとあるのに、なんでこんなに違うの…?コンパイル結果を見てみてもちゃんと必要な分だけ選択されているし、問題があるようには見えん…。
 しかたない、事実は事実として受け入れよう。受け入れるとして、どうしようか?ソフトはそんなに巨大化しないと踏んで、残りのブロックRAMもプログラムROMに割り当てて、SRAMを外付けしようか。実は事前の準備として16bit幅のROMを外付けすべく電源配線まで終わってたのだけれど、信号本数がギリギリっぽくて、それにROMライタで書き込んだ結果に対してまたデバッグが必要そうというところから、気乗りがしなかったのよね。
 というわけでICソケットを取り換え、SDカードとか他に残った配線、EZ-FPGAへのクロックモジュールの取り付け、などなどを徹夜覚悟で作業…そこまで根性が続くわけもなく、だいたいのめどが立ったところで就寝。


8月14日:SDカードアクセス

 配線が終わったところで、テスト開始。まずはSDカードの初期化ができないことには…できない。どこのコマンドまでできたかメッセージを出させつつやり直してみるが、ほとんど進まない。
 …で思い出したのが、ウェイトの設定。H8のプログラムから持ってきてるので、バイト単位のウェイトが消えているのであった。1chipMSXの時は入れてたんだけど、H8に持ってくるときにステータス確認できるからってんで消したのよね。というわけで昔のソースからダミーアクセスの回数を確認してウェイト挿入。

 できたのでもう一度…あれ、うまくいかない。多少はいけるんだけど…。わからないのでそろそろロジアナを持ち出そうか。掴める端子が限られているので接続が難しいけど、なんとかつないで。で、確認してみるとまだ一部コマンドがかぶってるところがあるみたい…。
 探してみると、初期化ルーチンの中でループとかでウェイトが必要な場所があるみたい。しかし、1chipMSXの時よりもウェイトがより多く必要な感じなのはどうして?…うーん、分周する元のクロックが、今回はちょっと遅いのか。で、シリアル通信が長くなってウェイトもその分必要…ということみたい。ウェイトとか入れまくって、どうにか動くようになった。

 でも動いたり動かなかったり、ちょっと動作が不安定みたい。動いても、途中で止まったりすることがあるみたいな。ロジアナで観測してみても、止まる瞬間を捉えたところで特に変わった感じはしない。というか長いので全体を見られないこともしばしば。

 何はともあれちゃんとロードできるようにもなったので、とりあえずロードしてみよう。プログラムはデータと共に今回のものをもらっているので、wav化して、ヘッドホン出力からカーアダプタを使って直接送り込み。MZTファイルをwav化できるようになって、ものすごく便利になった。
 ほどなく動画がスタート…おお、動いている…なんじゃ、この黒い帯は?周期的に現れて、下から1ラインずつ消えて、全部消えたと思ったらすぐまた現れる…。音声も妙なノイズが乗ってるみたいに聞こえるし、やはりデータの読み込みで何かあるのか…悩み、検討するも夜は更けていく…。


8月15日:MZ-MLオフ会

 出発の準備をしつつ、デバッグをするのは無理があるのではないかと思いつつも、なんとかやらなくては。ちょっと悲壮感が漂う。

 明らかに思い当たる節と言えば、AVR側のアクセス時にリフレッシュをしていないこと。と思い変更するとSDカードアクセスがうまくいかなくなるので、また戻す。他にもいろいろ考えて試してみるも、当たりがない。ここまできて未完成?こんなの持って行ってウケとかとれるかな。そもそもネタがないって言ったんだから持って行かなくてもいいんだけど…。いや、どうせ帰ってからデバッグするんだし、予告編というか、それなりに動くからどんな感じかもわかってもらえるだろうし、未完成でも持って行こう。今までもいろいろ未完成で持って行ったじゃない。

 テープの準備もしなくては。プログラムをwavファイルに変換してカセットアダプタを使えばロードできるようにはなったものの、テープに記録する手段がない。いやX1用のデータレコーダ・CZ-8RL1を使う手もあるんだけれど、なんというかアナログダビングのようなものなので、できればMZ-700自身でSAVEしたい。
 というわけで、一度アドレスを変えてロードしてからどうにかするかとMZ-700用S-OS"SWORD"をwavにしてロード、そこから本命のプログラムを$9200以降に読み込んで、モニタに移りブロック転送プログラムをコード直打ちで書き込んで実行、しかる後テープに保存。つまり、一度プログラムを実行してしまうとワークエリアを汚して初期状態ではなくなってしまうことがよくあるので、そういうことがないロードしたての状態をSAVEする方法としてこういう面倒な手段をとったわけ。もっとも、後日プログラム内にワークがないことがわかったので実行後リセットしてそのままSAVEで問題ないことがわかったのだけれど…。それはともかく、できたテープで再生を確認。

 ここで時間切れか。とりあえず現状版を見てもらえばいいかと割り切って、MZ関係の準備にまでとりかかる。MZ-700の有無はY'SeeNa.さんに確認済み。以前古籏さんのを借りっぱなしだというのを聞いたことがあったので、それを当てにしていたのだ。ただしデータレコーダが不調かもしれないという話だったので、念のため自分のデータレコーダを外して持って行くことに。あとは拡張I/Oボックスがないはずなのでそれも持参。もちろん準備したテープとボードとSDカードも忘れずに。

 関東へ移動して、夕食後Y'SeeNa.さん宅に移動。ひとしきり歓談の後、デモ開始。カラーが出ないかも、といって持ってきたMZ-700は、単にカラーモードのスイッチが入っていないだけだった。ボックスなど全て接続して、たけだPの最近の取り組みの話を枕にして、デモ開始。「けっこう見えるもんやね〜」「縦を分割してるというけど、解像度上がってないよね?」とかいろいろ感想をもらう。しかる後、ニコニコ動画を鑑賞。特に最近までのP6と700の切磋琢磨についてとか。


8月17日:再検証

 リフレッシュがないためにデータが化ける問題の解析。盛大に黒い帯が出るのだから、データの化けというか欠けがダンプしてみればわかるんじゃないか、ということで先日作ったダンププログラムを改良して、元のデータと目で比較。ある動画は最初の一瞬だけ黒一色で、次に白一色からフェードインしてくるので、それらしき部分を観察してみると、ところどころビット単位で化けている以外は問題ないみたい。特に黒帯を作りそうなまとまったデータ欠けらしいものも見つからない。
 ということは、これはハードではなくソフトの問題か?まぁたけだPも開発はずっとエミュレータ上だったから、まだエミュレータに実機を再現しきれてないところがあるのだろう。というわけでたけだPに現状報告。ありのままを見てもらうべく、簡単に動画を撮影してURLを知らせておく。


8月23日:新データ

 たけだPから新しいデータを作成したとの連絡。試してみたのだが、変化がない。せっかくなので別の動画を撮影して報告と一緒にURLを知らせる。

 その動画が役に立ったかはわからないが、クロックの数え間違いであるとの報告が入った。エミュレータもちょっと実機とずれてて、合わせたら症状が再現できたとのこと。


8月24日:新・新データ

 もう新しいデータができたとのことで、メールで送られてきた。試してみると…前よりひどい!こりゃもう泥沼かいのう…。
 残念でした報告を送る前に、データが基本的に問題ないことを確認しておこうとダンプしてみたところ、どうも雰囲気が違う。データにVRAMというかアトリビュートVRAMのアドレスらしき値が垣間見られる。これがアドレスだとすると、画素データをVRAMに書き込むのはPUSH命令だという話なので、SP(スタックポインタ)の値が動画データに埋め込まれていることになる。むーん、データが化ける現状では色が一瞬化けるのはごまかせてもアドレスがずれるのは致命傷。実際にあちこちダンプしてみても、明らかに違うアドレスに化けている箇所が発見できるので、このアルゴリズムをあきらめるか、やはり何が何でもデータ化けを克服するかしないといけない…。

 その旨報告すると、予想的中で、データにアドレスを入れているとのこと。もう一回検討すると言ってはくれるものの、こちらもなんとか解決させたい…。
 リフレッシュの手段として考えられるのは、アクセスしてない間にある信号をきっかけにしてリフレッシュのためのタイミングや信号を生成すること。Z80の場合は明らかにI/Oアクセスしない「命令実行時」を判別してリフレッシュさせていたのだけれど、AVR-Coreはタイミング的に早すぎてアクセスしない間を狙いようがないと考えられる。なにせ内部RAMもI/OレジスタもSRAM的なアクセスを前提としていて、アクセスに数クロック必要なDRAMは想定していないだろう(もちろん数倍早いクロックで動かせばいいのだけれど、プロセッサへの供給クロックがそのまま動作クロックなのでは…)。だからアクセスとリフレッシュが重ならないよう、ウェイトをかけたいがI/Oレジスタアクセスにはそんなものがないので、ステータスを見せてそれでアクセス可能になるまで待たせるしかない。EMMレジスタもすでにそういう構造にしてある。と思い変更してみるが、リフレッシュしてないように見える…。それに変更するとSDカードアクセスに失敗するのか、AVRがコケてるのか、処理が全く進まないこともある。
 あまりFPGAツールのレポートは今回見てなかったのだが、よく見るとロジックセルの使用率が98%とか100%とか言ってるじゃないか。一部しか使ってないのもあるので回路追加で破綻することはなかったのかもしれないが、もうタイミングを確保するのが難しいとか?

 ならなんとかロジックを増やさない方法でリフレッシュさせないと…あ、こんな方法はどうだろう。1chipMSXでオリジナルのESEMSX3のロジックが採用していた、ロジックとしてはリフレッシュ機構がないのにシステムを成立させている手法(と発想が近い方法)。
 簡単に言えば、RASアドレスとCASアドレスを入れ替える。CASアドレスの方が下位なので、しょっちゅう変化する。CASが無効だったDRAMチップには、RASしか有効な信号が来なかったとするとリフレッシュとなんら変わりない。ということは、その時にリフレッシュと同じ働きができるアドレスを与えられれば、リフレッシュできるんじゃない?幸いにしてデータは先頭から連続しているものなので、アドレスも順にカウントアップしていく。CASの与え方を工夫すれば、どのチップにもまんべんなくリフレッシュアドレスを与えられるではないか。
 と考えて早速実行に移すも、SDカードアクセスが失敗するようでどうにも動かない。配線を入れ替えているだけなんだが…そのためにロジックセルの使い方が替わるので、タイミングがとれなくなるのか…?タイミング調整に関するオプションをいじってみても変化なし。元のロジックに戻すとそれなりにうまく動くので、どうしてもダメというわけではないんだろうけど…。


8月25日〜26日:新・新・新データ

 数日かかるかと思いきや、もう新しいデータが送られてきた。今度は見事に再生できている。音声がチャリチャリ周期的に鳴ってたり、ブラックアウト後にチラチラ何か見えたり、周期的に縦線が入ってたりするけれど、まぁこれならごまかし可能かな。ということでまた簡易的に動画を撮影してたけだPに送信。
 とりあえずこれで一段落として実機による再生をUPする準備にとりかかることになった。水曜日は用事があって時間が取れないので、週末まで作業はおあずけだが…。


8月27日〜29日:実マイコンの検討

 FPGAのロジックに余裕がないのなら、AVRを外に出してしまえば問題は一気に解決。本物のAVRを持ってこようということで、まずは品定め。
 といってもAVRってそもそもは少ピンを基本とするマイコンで、外部メモリをサポートするタイプはあまりなく、またそういうのに限って端子数が多すぎるというジレンマが。あまり基板にスペースがないんよね。とするとシリアル系のI/FでFPGAに設けたレジスタをアクセスする必要があることになる。それにデバッグ用のシリアルポートは確保しておきたいし、それより何よりSDカードアクセス用のSPIも必要…ポートがひとつ足らないなぁ。第三のポートとしてI2Cもあるんだけど、こいつは400kbpsとやや遅め。ならSPIにする?ポートが持ってるセレクト信号でなくて、GPIOで作ったセレクト信号をSDカードとFPGA内レジスタにそれぞれ接続して、データ線はHi-Z制御する(MISOの方。MOSIは分配するだけでOK)ということでなんとかなるか。

とはいうもののなぁ…。
でもなぁ…。

…と悩むこと数日。


8月30日〜31日:新・新・新・新データ

 撮影予定日になって、たけだPから新しいデータの提供を受ける。今度は音声をPWMで鳴らす方式に改めたものらしい。つまりS-OSのBREEZEと同じ方式だ。確かにそちらの方が高音質になることは明らかなので期待してはいたが…。
 夜に確認作業。が、やはりものすごいノイズで聞くに耐えない。かすかに聞こえる音から、ちゃんと調整すればきれいになるんではないかと期待したくなるんだが…。

 その旨報告して、とりあえず現状版でいこうということになり、撮影開始…が…思いついた!!
 そうだ、リフレッシュさせないで長時間バスを奪ったままにするからいけないんであって、時々Z80にバスを返してあげればいいんじゃない?リフレッシュカウンタが一周するくらい待ってあげれば、つまりは集中リフレッシュ方式だな、平均値としては十分リフレッシュ要件を満たすんではないかと。これならAVRのプログラムをいじるだけなのでロジックに変化は与えない。タイミングが狂うこともないはず。
 EMMにデータロード中MZが何をしているか確定できないので、おおざっぱに4クロックで1命令実行していると考えれば、リフレッシュカウンタが一周するには2.5msくらい必要みたい。余裕を見て4msとることにして、AVR側のプログラムに使わないのになぜか残していた時間待ちルーチンのコンパイル結果からループのクロック数を推定、4msウェイトルーチンを作成。1セクタ読み出しごとにバスをZ80側に切り替え、4msウェイトし、AVR側にバスを戻す。転送の時間が2〜3倍になったような気がするが、それもやむなし。
 実際に動作させて、まずはダンプして中身を精査してみる…おお、化けてない。化けてないっすよ。すかさず動画再生プログラムを動かしてみると…おおお!!!綺麗な絵が!!!!一部を除いて(^_^;)。

 確かにデータ化けはなくなったのだけれど、周期的に縦線が入るという症状だけ残った。うーむ、これは化けてるから発生する現象ではなかったのか。とするとあとはSDカードアクセス絡みということになるのだけれど…初期化を疑った方がいいのだろうか?
 そこでロジアナで観測しながら、初期化シーケンスをチェック…動いたり動かなかったりするってのもよくわからんが、概ね大丈夫そう。いや、この概ねってのがくせ者なんだが。ならばとSPIクロックを何分周かして速度を落としてみる…変わらん…。というか速度を落とすと、このSPIデータの送り出しとかのタイミングをソフトでとっているので、また調整が必要になってしまう。いくつかダミーの命令を挿入して、ようやく整ったけど…やっぱり動かない。

 元の速度に戻して再度ダンプして調べてみると、あるところから突然1バイト若いアドレスの方向にずれてデータが格納されていることが判明。うーん、1バイトずれているから、音声に使うべきデータが表示されて変な模様ができていたというわけか。すると1バイトずれる要因として考えられるのは

  1. SDカードからの読み込みで1バイト欠けた
  2. FATライブラリのバッファからプログラムのバッファに転送する際に1バイト欠けた
  3. プログラムのバッファからEMMに書き込む際に1バイト欠けた

のいずれかということになる。さすがに2.はライブラリの動作なので、純粋にソフトということから除外してよかろう。残るはハードの絡む1.か3.。もし3.だとすれば、EMMに書き込んだ際アドレスカウンタを見て512の倍数になってなければずれたと判断して、今読み出したセクタをもう一回読み出してアドレスカウンタも設定し直すとかすれば、例えずれてもリカバリがきく。対症療法的であまりいい気分ではないが。1.だった場合は1バイト欠けているのにFATライブラリを正常終了していることになるので、バッファの内容も512バイト分あって欠けたかどうか判別がつかない。

 改めてEMMをダンプして調べてみると、ずれているのはセクタの範囲内だけで、次のセクタに入るとずれが解消していることが判明。しかもずれたセクタでは最後のバイトがなんだか怪しいデータになっているみたいなので、おそらく読み出し自体が511バイト分しかできなくて最後のはデータではないものをデータとして読み出したか前のが残っているか。つまり正解は1.だということ。

 さぁてどうするか?ソフト的には、ライブラリがエラーとして報告してくれないので読み出し直しとかも指示できない。思考がぐるぐる回って「そうだ!バッファに512バイト分なければリトライすればいいんだ!!」とひらめいた気がしたけど間違いに気づいて…。
 どう見えるかわからんけど、ロジアナで観測してみるか…これがセクタ読み出しだな…あれ、たまに読み出し間隔が狭まるところがある?これがあると最後のCRCらしきところのデータがなくなっちゃうな、するとこれが原因?!もうちょっとしつこく観測してみても、わりと頻繁に発生しているみたいだし、かなり怪しい。
 間隔が狭まっているところをよく観察してみると、通常の間隔はそのままに、中間に別の読み出しが発生しているように見える。ということは、プログラムの読み出しとは半ば無関係に読み出しをしているということか…なんで?

 SDアクセスの部分のソースを見て考える。ここはAVRのクロックではなくてもっと速いクロックを基準に動作している。どれぐらい速いかというと…24MHz。AVRやZ80のクロックは3.58MHzだから、6倍以上。だから、マイコンから読み出しとかの指示を受けてもそれがSDアクセス回路から見るとかなり長いパルスに見えるので、少し加工してパルスが始まったことを検知してアクセスを開始するようにしている。
 ここで、そのパルスにヒゲが発生したらどうか。3.58MHzでは影響を及ぼさなくても、24MHzなら立派なパルスに見えるかもしれない。だいたいにおいてヒゲが発生するというのは、一瞬だけデコードが成立する動作がある=似た箇所のアクセスがあるということなのだから、SDカードアクセスではない別のアクセスの際に発生するということだ。ならばデコード条件の信号のどれか適切なものを24MHzより遅い(具体的にはAVR用の3.58MHz)で打ち抜けばヒゲは消えるはず。

 ということで対策してみると…消えた!見事にノイズが消えて、絵もきれいし、音もきれい!!これならどこに出しても恥ずかしくないな。

 短かったけど、長かった…。


9月3日〜6日:動画収録とニコニコ動画に投稿

 このために新調した三脚を使い、実機で動かしていることを印象づけるためにMZ-700を含む全景ショットからスタートして、プログラムをロード(動画データロードは長すぎるのでカット)、動画が始まったらモニタに寄ってできるだけ大きく見せる…という流れで提供されている4種の動画を全て収録。
 これをi.Linkケーブル経由でHDDレコーダに転送、さらにVirturlRDでPCに取り込んで、音声を一旦.ac3ファイルとして分離、WAVファイルに変換してTMPGEncにて必要部分をカット処理(4編が1ファイルになっているので)。HDDレコーダに取り込んだものを転送してくるとアスペクト比がむちゃくちゃになるので(横長に変形される…のではない。縦長にされるのだ)毎回どう処理するのか思い出しながらなので時間がかかったが、週末までに投稿完了。

 直前に一般で参加したNico-TECH.高槻ミーティングにて「ニコニコ技術部は自ら名乗って良い」ということが確認できたので、今回は自分でニコ技タグを付加。ふむ、これで自分もニコ技の仲間入りか。

 その後ニュースサイトで取り上げられるなど結構注目度が高く、それにつれて一時的に再生数が鰻登りになったりするなど、投稿者冥利に尽きる展開で面白い体験をさせてもらった。


11月8日:関西オープンフォーラム2008に参加

 旬のうちに、ということで関西オープンフォーラム2008にてニコニコ技術部ブースを設け有志での出展を募っていたので、MZ-700を持ち込んで参加。このためにMZ-700がきっちり入るキャリーバッグを調達したのだ。ってMZ関連で購入したものって多いな。ビデオカメラ買ったのもMZ本がきっかけだったはず。

 Linuxがどうの、Rubyがどうの、CMSがどうの、Androidがどうのとか言われているイベント会場に現れたMZ-700は驚きの声をもって迎えられた。「なぜMZが?」という人はそれがどんなものか知っているわけだから、すかさず動画を見せつけると「ええーっ、すごい!!」と感嘆の声を洩らす。さすがに当時生まれてないとかいうような若い人には感動のポイントが理解してもらえなかったが、その分すばらしい「おっさんホイホイ」となった。来場者、周囲のブースの人、皆が「見とかないと損だよ」とかしばらく場所を外して戻ってくると「ぜひそれ見せてください」とか声をかけられたり、至福の時間であった。


3月12日:オリフェスデモに向けて計画

 オリゲー・フェスタ☆68出展を計画。前回も出展したが、スタッフとしての仕事もあるのでブースに張り付きは無理、しかし事情により誰かに手伝ってもらえるかどうかわからないので、いや手伝ってもらえても面倒な操作とか任せられるかどうかもわからないので、無人でも大丈夫なものにしないといけない。

 現状は電源投入またはMZ-700背面のリセットボタンでSDカードからデータ読み込み、再生プログラムはデータの形式に対応したものをテープから読込むとオートスタートするので、データ読み込みが終わってからでないとプログラムのロードができない。そして一旦再生が始まると、動画データ終端がない(判別している時間が惜しい)ので再生を止められずに強制的にリセットするなどして止めるしかない。
 これをいちいちまじめに繰り返していると時間がかかってしかたないので、動画データは一度読み込んだらSDカードを抜いておき、以降読み込もうと思ってもエラーで何もしなくなるのを利用してデータ固定、再生プログラムはプログラム内にワークエリアを持っていない(か壊しても問題ない)みたいなので、リセット後でもJコマンドで飛べばまた再生される、という工夫をしていたのが関西オープンフォーラム2008での展示。

 この手動再生を自動化するために、FPGAの改造と自動再生プログラムの作成を計画。作業内容はおおよそ次の通り。

 MZ-700では、再生したい動画データを指定して読み込ませ、読み込み終わったら通知してもらって再生プログラムをスタート、データエンドで割り込みがかかり次のデータ読み込み指定、というループを組むようにして、デモさせればよい。これなら無人でもOK。

 それとロード時間も短縮したいところなので、以前挑戦してうまくいかなかったアドレスの工夫にもう一度挑戦して、データ読込み中にリフレッシュが不要なようにできればベスト。


4月5日:ボード改造

 フォーミュラニッポンの生中継を観戦しながら、割り込み線の追加作業を。


4月11日:リフレッシュ改修

 まずは動画データロード時間短縮のためのRASアドレスとCASアドレスの交換から。以前一度試した時(8月24日)はSDカードアクセス手順の問題とFPGA内部回路の配置配線の問題と区別がつかず、戻していたのを再度試そうという話。

 以前試した時の改造はコメントで残してあるので、作業としてはそれをちょっと書き換えるだけ。ACR-CoreのファームはそのままにFPGAのみを書き換え、テスト…問題なし。

 FPGAの環境もそうだがAVR-Coreの開発環境がPCリプレースにより消えているので、再構築。で、同じプログラムをコンパイルしてみると…コードサイズが増えている?!最適化など設定をいじっても、これが最良の状態らしい。GCCのバージョンも上がっているのでそのせいかもしれん…。


4月12日〜13日:新データと割り込み

 たけだPから新方式による動画データが到着!今度はアトリビュートではなくモノクロ線画風の絵になる、つまりはそもそも野球拳などでグラフィック表示に使われていた手法を多少の妥協で拡張した方式、ということになるか。
 早速試してみると…むむ、突然画面が乱れて、音もノイズだらけに。これは音データでないものを音として再生し、絵ではないものを絵に使っているような雰囲気…。もしやデータずれ?

 HuBASICを立ち上げて、前に作ったEMMダンププログラムをロード。反対側のPCで動画データをバイナリエディタで表示させながら、ところどころをダンプして確認…むぅ、ずれてる様子はなし。再生していると絶対ダメになるポイントがあるのだが、それよりも前におかしくなることもあるので、これはプログラムがタイミングをとりきれてないのではないかと推測。

 というようなメッセージをたけだPに送ってみたものの、返事は「前の再生方式と同じですよ」とのこと。それに前のデータとプログラムで再生してみると、なぜか画面も音もノイズだらけになる現象が発生するので、これはボードに入力されている信号にノイズが乗っているということか…だとするとどうする…?

 とりあえずリフレッシュの問題は再生前のことなので、後回しにするとして。

 昨日DRAMのアドレスを入れ替える修正はしたので、まずバスを切り替えながらデータ書込みしているところを最初の頃のようにAVR-Core側がバスを握りっぱなしにするよう修正したファームを組み込み、ダウンロード、そしてテスト。…ふむ、どうやら問題ないようで。アドレス入れ替えに問題はないようだけれど、ロード時間は短くなったのか…?

 次にFPGAの方に割り込みを追加。以前LANボードで試したやつで、モード2割り込みに対応した回路ではあるものの、MZ-700の場合はモード1割り込みで駆動。
 割り込みの発生は、EMMレジスタがある値になるのが条件。ある値とはつまりデータの大きさのことで、具体的には読込んだ最後のアドレスの次のアドレス。これは普通にアクセスしていると自動インクリメントすることから、SDカードから読み込んだデータがEMMに書き終わったら自然とその値がアドレスレジスタに残っているはず。なので、そのタイミングで比較用レジスタに取り込めばOK。
 というようなレジスタも追加しつつ、先日配線した割り込み関連の信号も端子配置も定義して、比較用レジスタに取り込むようファームも修正、合成してテスト…。

 しかしどうも変。動作を示すインジケータとして使っているLEDはふたつあって、うちひとつはファームがSDカードアクセス中を示し、もうひとつはバスがZ80かAVRかどちらを向いているかを示すもの。そのうちバスの向きのLEDについては、リフレッシュ対策として周期的にZ80側に戻すようになってから消えなくなった(正確には消えているんだけれど、速すぎて見えない)わけだが、先刻のファームの修正でそれが元に戻っているはず、なのに変化がない…。それに割り込みベクタレジスタを新設しているにもかかわらず、アクセスしても無反応。
FPGAのコンフィグROMをベリファイしてみても新しいデータと相違ないと出るし…。でもその前のダウンロードと今のとで、チェックサムが同じってのはおかしすぎるよな!

 ということで変なところはないか探してみたら…あ、Impactの設定を作る時にファイル名をUnknownにしていたのか。mcsファイル作成はUnknownで、書込みはbigEMM.mcsで、だったらそりゃ動作は変わらんわな。

 改めて、正しいデータをダウンロードしてテスト…ふむふむ、ロード時間も明らかに短くなったし、動画もどこも化けてないし、割り込みベクタもちゃんとアクセスできるし、問題なさげ。

 次は割り込みをテスト、ということで割り込み処理の飛び先は設定しないまま、割り込み許可して動画スタート。動画が終わったらリセットがかかったようにモニタに戻るはず…あれ、戻らない?
 動画プログラムを確認してみたらなんと先頭に割り込み禁止が。特に禁止しないでも問題ないはず、と割り込み許可に書き換えて再度挑戦…あれ、止まらないなぁ。むーん、これはしっかりデバッグポートとかを仕掛けて、調べないといかんようで。


4月18日:ノイズ対策

 割り込みの前に、アドレスのカウントアップが「すべる」現象の対策から。これはIORQにノイズが乗って1回のアクセスに2回の立ち上がりエッジがあるから、というわけでCPUクロックで一発叩いてきれいにしたはずが…テストしてみると、全体的にノイズが乗ってるみたいだし、途中からデータが読込まれなかったらしく、絵が消えてしまった。

 一発叩くのでは信号とずれるからか、ならば反転クロックで叩けば遅延も半分だ、ということで修正したものの、今度は全く絵が出なくなった…。
 どうするか?この間作りかけて動かなくてデバッグ待ちのアクセス回路(完全クロック同期式、作ってはみたもののまだうまく動いていない)に変えるか…デバッグしきれればいいけど、ここで別方向にハマりたくない…。

 ノイズが乗るとして、起こったり起こらなかったりするのは乗ってるノイズの大きさがたいしたことないから、ということか。ならば、FPGAの端子にプルダウンを設定したら、乗ろうとしたノイズも少しはそちらに吸い込まれるかもしれん。ということでVHDLソースは元に戻して端子設定だけ変えたら…ふむ、うまくいってるような気がする。これでいいならフェアライトビーズでもいいんじゃないだろうか?ま、正式にはレベルコンバータなんだろうけど。


4月19日:割り込み→ノイズ→割り込み

 ノイズの問題が一段落したということで、割り込みに取りかからないと。まずは割り込み発生ポイントを記録するレジスタをZ80側から読めるようにして、他は…まぁ元からステータスレジスタで見えるようにもしてたから、とりあえずはこれでいいか。
 ではテスト…適当なデータを読込ませて、HuBASICからレジスタアクセス。あれ、データエンド(=データサイズ)よりもずいぶん先のアドレスに割り込みポイントが設定されている…。ああ、面倒だったのでFATファイルシステムのバッファひとつ(512バイト)まるごと書込みするようにしてたから、1セクタに満たない半端分は残りのゴミといっしょに書き込まれて512バイトのデータにされていたのか。まぁいいか、動画に対してはちょっとだけだから見る分にはあまり気にならんだろうし。

 EMMレジスタを割り込みポイントの手前に設定して、アドレスを表示させながらデータを読込み…ってあれ、そのポイントにきたら飛んでさらに+1されてしまう?何回やってもそうなるなぁ。
 試しに普通に動画再生をやってみても、ノイズの嵐。まさかこれって、昨日とりあえず解決したと思った症状では?うーん、回路が変わって効果が薄れたとかそういうことなのか…。

 これはやっぱり3.3Vバッファを通して整形するか、ということで若干情報をチェックした後SOARのロジアナ基板からまた部品を取り出し。今回はIORQだけ整形できればいいんで、HC04を。もちろんそのまま使ったんでは信号が反転してしまうので、二段重ねで通すとして。

 情報をチェックする過程で、こんなブログを発見。なんでHC系のCMOSロジックICでレベル変換が出来るか、そして今回みたいにスレッショルドが気になる場合のその値なんかも計算してくれている。ふむ、やっぱり電流制限かけないとやばいのか。
 ということでHC04の入り口に10kΩの抵抗をかませて、改造終了。いざテスト…ありゃりゃ、全然読めてないのか絵が出ない…?前に別のボードでノイズ対策としてシリーズに抵抗を入れた時も完全に動かなくなったので、やっぱりまずいのかな。試しに抵抗を飛ばしてIORQを接続したら問題なく動作。しかも、朝ノイズだらけだった絵と音もFPGAのロジックを変えてないのにトラブルが解消。狙い通りに波形整形してくれたということか。

 ハンダ作業をやってるので、ついでにロータリースイッチの配線も追加。元々4bitのスイッチなのをデータが4つしかなかったので2bit分の配線だけであとは省略していたのだけれど、それが今回追加されたデータで4つを超えるので、この際全部配線しちまおうということに。
 端子がどのbitにあたるのか部品を見てもわからないので、でもテスターで当たるのは面倒、どこかにデータシートがないかと探したけれど、意外に見つからない。確か夏に作ってた時に見てなかったっけ?ということで自分のPDFフォルダを探したら、ちゃんとあった…偉いぞ私…。
 配線していざテスト…あれ、なんか今は点灯しないはずのLEDが点いてるが…ああっ、ここは配線したらいかんのだ。大急ぎで場所を変えて、新しくもらった動画データを入れてテスト…うん、ちゃんとうまくいってるようで。

 データ読み込みに信頼がおけるようになったので、再度割り込みのテスト。またHuBASICを起動して、割り込みポイント手前にEMMアドレスカウンタを設定し、ポイントまで読み出し…ふむ、ステータスレジスタ的には割り込み発生しているみたい。でもHuBASICでは割り込み禁止にでもしているのか、暴走とかも発生しない様子…。
 ならモニタならどうかと、再生プログラムの先頭にあるDI命令をEIに書き換えて実行…止まったり暴走したりとかはないみたいだが…。本当に割り込みが発生しているの?ということでまたオシロを出してきて、観測…あれ、何も反応しない。なんで?

 割り込みステータスレジスタに観測したい内部情報を追加して試しても、割り込み回路は正しく動いている様子が読み取れる。でも暴走もしないしリセットみたいなこともないし、これはやっぱり割り込みが出てないってことかな。でも回路的には出しているつもりっぽいから、FPGAの出力回路の問題?
 割り込み出力は他の割り込みとワイアードORしないといけない都合でオープンドレイン(っぽく振る舞うスリーステート出力)なのだが、まさかLの引き込みが弱いとか?でもさっきのページを見てもHレベル出力の場合に送信側の寄生ダイオードがリミットをかけちゃって5Vにならない、ってのはあってもLレベルは特に問題にしてないようだし。FPGAのデータシートを見ても問題があるように見えないし。

 いや待て待て。内部割り込み受け付け許可信号は、CPUからの割り込みアクノリッジを受けて不許可に切り替わるのだ。さっき見たステータスレジスタの動きは、CPUが割り込みを認識している証なのではないのか?…とふとオシロを見たら、トリガ設定がパルスになってるじゃないか。これか?これなのか?エッジトリガに変えてまたテスト…おお、割り込みにパルスが出てる。なんだ、見方が違ったのか。

 ならば再生プログラムでもう一度挑戦。そもそも初期設定がどうなっているかMZ-700のマニュアルを見て確認してみると…。
 モード1割り込みなので0038hに強制ジャンプするのだが、そこはROMなのでさらに1038hに飛ぶようになっている。そこには初期化の際に時刻割り込みルーチンの飛び先が設定されている。これは確かAM/PM切り替えのロジックのはず。
 ここをモニタのコマンド待ちに書き換えて、テスト…む、何も再生せずに画面真っ暗。オシロでは割り込みが発生したとあるので、ロード時にゴミのように溜まってしまった割り込みが入ったって事か。多分この画面はバックもフォアも黒になっているだけで普通にコマンド待ちに違いない、とJコマンドで0番地に飛んでみたら、ほら復帰した。

 もう一度割り込みの飛び先を設定して挑戦…今度は再生終了直後に暴走。ふむ、これで割り込みの処理さえちゃんと書ければループできそうな気が。
 次はリセットでデータ読込みという今の動きではなく、リセット直後はボタンかZ80側からの指示待ちにして、どちらかが来たらデータ読込み、割り込みポインタ設定…と動くようにすること。もちろんZ80側からの指示ではどのデータを読込むのかも指定できるようにしなければ。


4月22日〜29日:ループデモ完成

 出張にVHDLソースを持ち出して、新幹線の車中で修正、帰宅後ダウンロードしてテスト…あれ、起動直後にロードを始めてしまう…。あ、ボタンの論理が逆か。ボタンを押したことを判別するはずが、押してないことを判別することになってたのな。これは回路を修正して再度トライ。
 今度は起動直後はそのままで、ボタンを押したらデータロード開始。よしよし、ロードが終わったので再度ボタンを押して…あれ、ロードしない。おかしいな、LEDの動きからしてもプログラムは先頭に戻ってるはずなんだが…。

 デバッグ用に残してあったシリアルポートに、チェックポイントごとに文字出力させて動作させてみると、やっぱりロード終了直後にボタンやZ80側からの指示がなくなることをチェックするためのループから抜けてないことが判明。ボタンは機械的なものなのであとはZ80側がセットするフラグしかチェック対象はないのだが、これが勝手にセットされていることを意味してしまう?

 実は割り込み機構を組み込んだ時から、割り込みイネーブルが勝手にセットされている現象に気づいてはいた。消すと消えるので回路としておかしいわけではなさそうなのだが、初期値とも違うし、とりあえずデバッグでは問題になってないからいいか、と先送りにしていたのだ。しかしどうもこちらにも似た現象が発生しているというのなら、対策が必要ということか。しかし原因がわからん…偶然そのアドレスを指している瞬間にまたノイズが出てるとか?IORQのあの対策では足らないとか?

 IORQをレベル変換する前に試した、FPGA端子のプルダウンを解除してみるか。FloorPlannerで修正後、合成・テスト…変わらんな。

 Z80のI/Oアドレスを16ビットフルデコードするわけにもいかず。うーん…。
 …そういえば、Z80側がアクセスするアドレスのうち、AVRもアクセスするものはバス切り替え時にCS信号も切り替えてるけど、AVRには関係ないものはZ80側のままか。これってAVRがアクセスしている間はどうなってんの?
 ああ、IORQがAVRの制御下に入るから、Z80側アドレスアドレスバスはメモリも含めて有効になる可能性があって、たまたま同じアドレスを指していたりなんかした瞬間にAVRもデータロードしていたら意図しないフラグ設定とかしちゃうってことか。なるほどそらまずいわな。

 なら関係ないと思っていたCS信号も切り替えるようにするか。使わないので無効になる固定値で。
 これでどうかな…むむ、デバッグメッセージは意図しない表示だが動作は問題なさそう。メッセージを消して再度ダウンロードして、今度は動画としてテストを…あれ、画面真っ白?
 むーん、何が起こってるの?さっきIORQの端子設定を変えたからかな。もう一回FloorPlannerでチェックしてみるか…あれ、なんか信号が一本配置設定されてないんだが…ってこれIORQじゃないか。そうか、さっきプルダウン設定だけを消したはずが配置そのものを消しちゃったのね。再度配置設定して、テスト…ふむ、今度は再生まで大丈夫なようで。

 HuBASICを起動して、Z80側のポートを叩いてみる。まずファイル名(1文字)を格納するレジスタ…は0。次いでステータスは…あれ、こちらも0。バスがZ80側を向いているはずなんで、128が見えてないとおかしいんだが…。
 じゃあファイル名を入れてみよう、とレジスタに値を入れてみても、やっぱり0。えーと、なんでかなーとファームのソースを見てみたら、切り替えなんかに対応する信号を初期化していなかったというオチ。これまではSDカードのファイルアクセス直前に設定していたんだが、今はその前にロード指示を待つので、先に初期化が必要ということね。

 初期化を入れて再度テスト。なんかLEDが点灯してないんだがいいんかな。今度はレジスタ類がちゃんと見えて、フラグレジスタを叩くとLEDが点灯してロード開始。よしよし。

…。
…。

 終わらん。なんかトラブってんのかな。一度電源を落として、再度BASICをロードして…あ、今度はうまくいった。一度フラグを消して、再度フラグを立ててやるとまたロード。これでソフト操作でデータロードが可能に。さっきロードできなかったのはSDカードのバス初期化に失敗したからかね(その後もたまに発生。このあたりがアマチュア工作の限界か。多分、製品レベルに上げるにはプロトコルアナライザなどで詳細な検証が必要のはず)。

 次はいよいよループ再生プログラム。これまでの武田さんのプログラムを合わせて、割り込みを駆使してループさせるわけだが…。まずは開発環境。
 アセンブラはどこかから落としてくるのではなくて、昔イエローソフトから買ったYC80というZ80/64180用Cコンパイラの、YA80というアセンブラを前のPCから転送してあったので、これを使用。リロケータブルバイナリ対応なんでリンカが必要とか、セグメント対応とか今回の用途にはそこまで凝らなくても…という仕様ではあるけれど。

 MZ-700に持ってくるためにmztファイルにしてからwavファイルへ変換、という手順が必要になるのだが、ヘッダを別に作ってアセンブルのたびに修正して…とかいうのが面倒なのと、ちょっと考えたら簡単そうだったので、アセンブラソースに作り込んでしまうことに。まぁ、プログラムの先頭にデータ列が並んでるだけだけど。ヘッダ情報とプログラムの先頭がわかるようにひとつだけ命令を書いておいてアセンブル…ちょっと調整が必要だったけど生成成功。

 次に武田さんのプログラムの組み込み…mztファイルを逆アセンブルしたりとか例の動画解説ページのソースを持ってくるとかちょっと試したけれど、微妙に違ってる上にこれを作成する手間と、その間に間違いが紛れ込みそうな予感から、プログラムのバイナリを直接埋め込んで再生のたびに必要なプログラムを転送して動かすことに。
 本番は複数のデータをとっかえひっかえするのだけど、とりあえずひとつだけループできればいいのでその分だけプログラム。これでいいのかな…とにかく実験してみるか。

 実行…あれ、「シバラクオマチクダサイ」と表示した文字が化け化け。アセンブルしたバイナリを確かめてみると、なんだこのコードは…。エディタのコード体系を変更すると直る?いや直らないし。これはしかたないので1バイトずつアスキー表から拾うとする。データのロードはやってるので、肝心のプログラムはなんとか動いているか…あれ、ロード終了しても再生が始まらない…。
 うーん…あ、EMMのアドレスレジスタが読み込み後のそのままだから、割り込み許可すると途端に割り込みが入って暴走するというわけか(実はAVRのファームでゼロクリアするようにしているのだが、なぜか値が書き込めない。Z80側でできるのであきらめてしまった…)。ならばアドレスレジスタをゼロクリアする処理を追加して…よし、再生するようになった。

 一度再生して、終わりまできたら割り込み発生でまたデータロード開始。よしよし、いい調子。これでまた再生が始まれば…うわ、絵と音がぐちゃちぐゃ?これは…再ロードの時にアドレスレジスタがEMMの先頭に戻ってないので、データがずれちゃってるのか。こちらにもゼロクリアを追加して…あれ、直らない?あ、入れるところ間違えた。これを直せば…よし、二度目の再生もできた。

 ではもうちょっと回して、ちゃんとループできることを確認しよう…って二度目の割り込みが入らない?あ、割り込みが入った後EI命令実行してなかったか。なら追加して…ってそれでも入らない?

 うーん、これはもしかしてFPGAの割り込み回路がRETIを正しく認識できてないってことか…。認識できていれば内部の割り込み保持をクリアするんだけれど、Z80側からできる割り込み許可を全部やっても割り込みが発生しないと言うことは、回路としては割り込みが入ったままという想像ができてしまう…。
 RETIが正常に認識されていないとするなら、Z80の割り込み処理ルーチンで割り込みを解除してやればいいはず、ということでステータスレジスタの特定のビットに1を立てて書き込むと解除できる仕組みを作り込んで、いざテスト…データロードまでやって暴走しているってことは、割り込み許可直後に割り込まれているってことか?

 これまでの構造では割り込み許可後に飛び先設定とかしていたので、その直前に割り込まれると暴走してしまう。ということでギリギリまで割り込み許可をしないようにしてみたところ、データロードだけが延々と繰り返されるようになってしまった。割り込みを消す処理を入れたのに、割り込み入りっぱなしとはどういうこと?理解できん…。

 現象を目で確かめるべく、HuBASICでレジスタの値を読み出しながら再チェック。起動直後は割り込みなし状態だが、最初のロードが終わって割り込み成立後、割り込みが消えないという現象は確認。ただBASICだと割り込み処理ルーチンに入ったのかどうかよくわからんのよな…。
 とりあえず回路を前の状態に戻して、Z80のプログラムにて割り込みステータスレジスタの内容を2進数で表示させる仕組みを埋め込み、それぞれでどんな状態になっているのかを確認することに。動画データをいちいち読込むのは時間がかかるので、名前を変えた小さなファイルをSDカードに保存して。

 …ファイルが小さすぎて、レジスタ表示の間隔が短くてどう変化しているのかよくわからん…。キー入力を待つように修正すると、見えてきたステータスは割り込みが発生してないと主張…?
 動画再生できるようにプログラムを戻すと、昨夜と同じくデータロードだけでループする現象が…。いや、プログラムもFPGAも2回再生できていた時のとほぼ同じなのだから、なんかひどくなってるってことか…。

 割り込みが入るってことは、割り込み条件が成立しているってことのはずなので、割り込みポイント(EMMアドレスレジスタがどの値になったら割り込みを発生するかの設定値)を表示させてみるか。何かの都合でデータの末尾を設定できなくなっているのかもしれないし。…それはそれでイヤだけど。
 しかしこの手の画面表示(数値を文字に変換して表示とか、さらに2進数に変換して表示とか)、昔は参考書片手に首っ引きだったけど今では命令表を確認するだけであっさりアセンブラで書けちゃうようになってしまったなぁ。このあたりの苦労のレベルが個人的に下がったこともあるので「コンパイラでなくてもいいんじゃ…」とか思うわけだけど。

 で、割り込みポイントを表示させてみると…昔と変わらん。むむむ、ならば割り込み条件が成立するわけないんだが。
 そもそも、割り込みステータスレジスタの割り込み発生フラグが、割り込み許可設定を前提としているのがわかりにくくしている原因ではないかということにやっと気づいた。割り込み許可にしないと割り込みが発生しているかどうか判別できないし、EI命令実行後だったらCPUに割り込みを引き取られてすぐ消えちゃうし。ということで割り込み許可を伴わない、ボードとしては素の割り込み要求フラグを見えるようにして画面にも再び表示させるようにプログラムを修正。
 む、ロード中もロード後も割り込み後も、割り込み要求が出ていない。ってこれはつまり別の所から割り込みがかかってるってこと?うーむ。

 MZ-700の場合、本体内にある割り込み源は8253のみ。モニタのソースリストを見る限り初期化の段階で時計としての8253に何か特別な設定をしているようではないみたい。なら何か動くともあまり思えんのだが…。
 オーナーズマニュアルをよく見てみると、8255の出力が8253からの割り込みをマスクしている模様。ていうかFPGA版MZ-700を作った時に見ていたはずなんだが、すっかり忘れてるな…。
 モニタのソースリストを見ると初期化のところでその割り込みマスクを解除しているので、もし8253から割り込みが入っているとしたら後から改めてマスクすれば割り込みを防げるはず。

 ということで初期化にそれを加えてテスト…ふむ、ちゃんとロード後に再生して、再生後に割り込みがかかるな。で、再ロード時のステータスレジスタの状態を見ると内部のフラグが立ちっぱなしで、RETIが受け付けられてないような感じ…ってこれでやっと昨夜のFPGA改造前に戻ってきたということか。
 割り込みの異常発生とマニュアルでの割り込みクリア改造に因果関係はなかったので、ここでもう一度その仕組みを組み込み。でテストすると…おお、期待通りに再生して、期待通りにループする!いいねぇ、これで完璧なんじゃ?
 RETIが受け付けられないってのは、もしかしたら、この前までIORQにノイズが入って苦労したように、命令フェッチを示すMREQとM1にもノイズが乗っていて、おかしな命令を読込んだような状態になっているんじゃないかと予想。まだレベル変換回路が2つ余ってるけど、改造が面倒なんでこのままいくか。

 では次は、用意している全データを順番のシナリオどおりに読込んで再生するよう改造。データがこれから増えることはないだろうけど、可変長のデータ数に対応できるようにして、表示するメッセージもその格納場所を指定してデータ毎に可変出来るようにして。モニタの文字表示サブルーチンでは色とか出せないので、メッセージ表示ルーチンは自分で作った方がいいんだろうなぁ。
 これでテスト…よしよし、思惑通りに全てのデータを順に読んでは再生。そして何度でもループ。1ループ15分くらいか。なんとかこれで、展示の最低ラインには到達したか。やれやれ。

 あとはメッセージ表示ルーチンをゴリゴリ…。カーソル移動とかカラー設定とか、あとひらがなや英子文字表示のためのアトリビュート設定とか。

 さらに、データロードに1分以上かかったりするので、どれだけ待てばいいかを表示するのが親切だよな、ということで機能追加。
 まずは、割り込みとか止めたりしている状況で時計が動くのかどうかというところから。時計はモニタサブルーチンに時刻設定と現在時刻読み出しがあるので、それを使用。いずれも秒で表現されたバイナリ値を使うのだが、今回はゼロクリアすればいいので細かい計算は必要なし。

 時刻がバイナリ値なので10進数に変換するルーチンと、その結果を表示するルーチンを、合体させるかはともかく作ることになるのだけれど、まずは10進変換はおいといて時刻を表示…あ、あっさり成功。ある程度メッセージも準備しながらなので画面は「あと xxx秒」とか出ているが時計にはダウンカウント機能なんかないので、数字がどんどん増えて行くのは予想通り。他のメッセージの位置とか色とか合わせてちょっと調整しつつ。

 さて、10進変換は以前何かのプログラムで少し考えた方法の実践。ま、実践というのはつまり前は考えただけでコード化しなかったということだが。当時はC言語だったような気がするけど今回はマシン語で。
 まず一番下の桁について、0xA〜0xFだったら6を足す。そうすると0x10〜0x15になるので、一旦これを保存。
 下から二番目の桁は、同様に0xA0,0xB0...0xF0であれば0x60を足すが、それだけではなくて、例えば0x10と10進数の10とでは6の差があるから、その分も足すことになる。桁の数×6を足すのだが、かけ算は面倒なので0x6,0x12,0x18…というBCD的6の倍数をテーブル引きして求める。
 三番目の桁も計算するところだが、プログラムを作りながら背後でデモを回し続けてロード時間を計ってみたところ、2分を超えるものはなかったので、2桁の16進数を変換できれば十分と判断。
 あとは変換で出てきた数値を全部足せば変換のできあがり。出てきた数値はすでにBCDなので、足すたびにDAA命令を使って補正。ちうか個人的にDAA命令使うの初めてかも。

 さらに、表示の際に頭の桁が0だった時これを表示しないように変更して、シナリオに各データのロード所要時間を並べて、プログラムではこの時間から現在時刻を差し引くようにして、いざテスト…んー、それっぽく変換されてるように見えて、数値が変化しない…これって暴走かな…と思ったら再生が開始された。ってことは計算方法の間違いか。それと頭に0があるのに表示されちゃってるし。

 むーん、なんでなんで…?あ、なんかレジスタを取り違えてるところがあるな。なんでこれでいいと思ったんやろ、やっぱり疲れてるんかな…。
 そこを直して再びテスト、ちゃんとダウンカウントするな。で、動かしている間に0表示関係を…あ、絶対ジャンプのところを条件ジャンプにしちゃってるし。しかもこの間違い方はジャンプ命令をスルーしちゃうから、そりゃ動き変わるわな。
 これを直して、これでどうだ…よし、うまくいった。ちょっと色を手直ししたら、まぁこれでいいかな。それぞれのタイトルをどうするか(武田さんがニコニコ動画にアップした時のタイトルをそのまま書いている)はずっと迷っているのだが…。


5月4日:オリフェス

 結局タイトルは変更せず。一式を手持ちするのにI/Oボックスをそれまでデバッグに使っていたMZ-1U03から秋の時までのMZ-1U08に戻したら動作がおかしくなるというトラブルに見舞われるも、コネクタの差し込み不良だと判明して一安心。当日を想定したロングランテストも問題なくクリアし、いざ移動。

 当日は設営直後、ある程度再生するものの突然乱れるというトラブルが発生。外来ノイズか未知のバグか、と焦ったものの、実はI/Oボックス底面のモードスイッチが輸送中か設営時にMZ-1500モードになっていただけのことで、その後は全くのトラブルフリーに。

 やはり非力の代名詞かと思われるようなMZ-700で、本体無改造状態での音声付き動画再生はインパクトが大きい。いつも数人の人だかりができていたし、写真を撮る者、じっと見入る者、皆感心していたようであった。自分は前述の通り主催スタッフなのであまりブースに居着けなかったこともあり、客となかなか談義できなかったのが心残り。

 帰宅してから気づいたのだが、Gizmodo Japanが予告記事として取り上げてくれていて、公式サイトの参加サークルの説明にニコニコ動画のURLを貼り付けておいたものだから、それを片っ端から視聴可能なようにリンクしてくれていた。しかもそれが2chのニュース速報板に拾われてスレッドにされていたので、そこから辿って動画を見に来てくれた人が多数いたようで、GW手前まではようやく9000ビューに届くかというところだったのがその後一ヶ月弱で18000ビュー越え。リピーターか初見かは判断つかないけれど、まさか第二波が来るとは…。

戻る