ちょっとTea Time!? CPM80の「MZ80化」を構想する!の巻き(本編)。 2025.9.6
ことはじめ
昔々、京都の寺町といえば大きな電気街でした。場所は四条寺町の寺町通の南側の約2ブロック。
二宮無線、谷山無線、ヒエン堂やその他一杯。電子パーツを扱う店も結構ありました。
嗚呼、懐かしの寺町電器街 - Kyoto Love. Kyoto 伝えたい京都、知りたい京都。
寺町へは中学生のときは、家から自転車でよくいきました。
(小学生のときは、一人で学校区からでることはできませんでしたから)。
距離的にも15分くらいかなあ〜。
駐輪場はないので、いつもはヒエン堂の横の道に止めていました。
当時はマイコンの黎明期。TK-80BS(TK80にBASIC基板が接続)や
MZ80(SHARPのマイコン)などのBASICが使えるものが置いてあり、
興味深く触っていました。当時のBASICの雑誌には
10 LET A=2
と代入にLETがつかわれていました。
それらに忠実に
10 LET A=2
20 LET B=3
30 LET C=A+B
40 PRINT C
50 END
などと、打ってみて実行して、モニターに結果が表示されると嬉しかったりしたことを覚えています。
これらのことが、マイコンに興味をもった原体験です。
MZ80のように、CRTとキーボード、そしてカセットテープ(記録装置)
が一体となったようなマイコンは憧れをもつには十分です。
それらのマイコンは当時の価格でも10万円は軽く超えるものでしたから、
お小遣いを貯めて買うようなレベルのものではありません。
ちなみに、MZ80やその後継機のMZ2000などを詳しく記述したHPがありました。
機能は低いが、夢が詰まっているという、記述に共感しました。
Nibbles lab: http://cwaweb.bai.ne.jp/~ohishi/index.htm シャープ博物館
引用:MZ-80K
こういった記事を読んでいて、無性に一体型の(昔風の)パソコンを作ってみたくなりました。
私の原体験が疼きます(笑。
最後に作ったCPM80をベースに改造
最後に作ったCPM80は「高速」を意識して、基本的な機能を充実させました。
ただし、あくまでもCPU部分のみであり、WindowsのTeraTermというターミナルと接続して動かしています。
今回は、この基板をベースにモニターやキーボードも取り付けようと思います。
最後に作ったCPM80。Z8S18033(Z80相当,最大33MHz品)を60MHzオーバクロックで動作させ、
3MBのハードウエア転送のメモリーディススク内蔵。制御PIC(最大64MHz)も80MHzオーバクロック動作。
現状の構成です。CPU周辺しかありません。
キーボードについては、先日にUSB接続のメカニカルキーボードを改造して、UART(RS232)出力が可能にしました。
モニターについて、7インチのWVGA(800x480)の動作を確認しているので、それらを接続するようにする予定です。
モニターはZ80からもアクセスできるように(但し亀のように遅いだろうけど)、Z80のバスに接続します。
ただし、Z80だけからのコントロールでは、速度の問題がのこるので、アクセラレターとしてRP2040マイコンも
バスに接続して、画面表示の手伝いをさせるように考えます。
考えている構想です。WVGAはZ80のバスに接続しますが、アクセラレータとしてRP2040マイコンも接続します。
まずはバックプレーンを準備しよう!
基板が複数枚追加できるようにバックプレーンを作成です。
前につくった、バックプレーンを使います。ユニバーサル基板の裏側に配置したので、
穴ピッチの関係からコネクタは3個のみになります。まあ、3個あれば色々と遊べるでしょう。
CPM80と同じサイズの秋月のユニバーサル基板にカードエッジのコネクタを取り付けです。
穴ピッチの関係から3個だけです。
基板の裏面側にバックプレーン基板をとりつけています。
CPM80基板を下側にして、バックプレーン基板を追加です。
次は、RP2040アクセラレータとWVGA接続基板を作ろう!
Z80のI/Oに接続するだけなので、本来はそれほどややこしくないはずなのですが、
RO2040とWVGAが3.3Vロジックに対して、Z80が5Vロジックなので、どうしてもレベル変換を入れる必要があります。
そのため、すこし部品点数が多くなりそうです。
RP2040からもZ80のバスをアクセスするようにしているので、画面表示だけじゃなくてZ80のお手伝いもできるかもです。
浮動小数点の計算なんかを手伝わせられたら面白いかなあ〜。
回路図のPDFファイル。
夜な夜な作成です。
ポリウレタン被覆銅線をつかって配線しています。
とりあえず、配線は完了。あとで、配線チェックしなくっちゃ!
現実逃避? 2025.9.7
配線チェックって、もの凄く面倒な作業なので、おもわず現実逃避してしまいました。
まだ、動いてもいないのに、あたらしいI/O基板を作成です。
PSG(音源)ICのAY-3-8910Aを4個搭載した、基板を作成です。
音源用の基板です。PSGを4個搭載しています。
半田面です。配線はあまり多くはありません。
スピーカアンプはDAISOの300円スピーカについていた基板のICを活用です。
残しておいてよかったあ〜。
スピーカアンプとしてLTK8002を使いました。
psg_card.pdf へのリンク
まずは準備体操 2025.9.8
RP2040アクセラレター基板の配線チェックです。
すこし電源周りで抜けていたところがありましたが、確認完了です。
RP2040アクセラレータ基板の配線チェックが終わりました。
まあ、配線チェックが完了したからといって、動作するとは限りません。
回路自体が間違っている可能性もありすからね。
さて、この基板をCPM80に差し込んで動かそうとすると
RP2040基板のプログラム作成(VT100シミュレータ機能など)
CPM80のBIOS改造
PICの制御ソフト変更
などなど、多くの作業が必要です。
一気におこなうと、どこかでトラブルとどこが原因かわからなくなってしまうので、
地道に調査から始めます。まあ、準備体操みたいなものです。
VT100のコマンドは?
CPM80のターミナル機能をもたせるにはVT100をシミュレーションしなくてはなりません。
単に垂れ流しで表示するだけならまだしも、最低でもスクリーンエディタであるWORDMASTERを動かせる環境にはしたいものです。
となると、VT100のエスケープシーケンスを実装しなくてはいけません。
しかし、このエスケープシーケンスが、また無茶苦茶多いです。
ANSI/VT100 Terminal Control
こんなもの、まともに実装する気になりません。
そこで、現状のCPM80基板のシリアルポートの信号を横取りして、
WORDMASTERでどのようなエスケープシーケンスが使われているかを調べてみました。
シリアルポートの信号を横取りして、どのようなコードがでているかを調べてみました。
意外と少ない?
色々と動かしてみましたが、どうやら使っているエスケープシーケンスは3つ程度のようです。
ESC[n;mH カーソル位置をn,mに移動する
ESC[2J 全画面クリアーしてカーソルはホーム位置へ
ESC[K カーソルから行末までを削除
と、この程度です。これなら実装は簡単そうです。
WORDMASTERで使われているエスケープシーケンスの種類は少なそう。
あ、面倒だなあ〜。
カーソルの移動といえば、一言で済みますが、カーソルにある位置の文字を反転させるのが面倒です。
というのも、WVGAは書き込みONLYにしているので、書き込まれた内容を読み出すことはできません。
それができれば、カーソル位置の文字画像を読み出して、反転させたものを再度書き込めばいいだけですが、
それができません。
キャラクターベース(80x24)のバッファーでよいので、何の文字を書き込んでいるかのイメージを持たせないと
いけない感じです。となると、スクロールなどしたときに、そちらも更新しなければなりません。
ああ、結構面倒だなあ〜。
まあ、ぼちぼち進めましょう。
作ってみると、意外とあっさり 2025.9.9
プログラム作成が面倒そうだなあ〜と思っていましたが、
風呂に入りながら、プログラム構造について頭の中にめぐらせ、
なんとなくあっさり出来そうなので、一気に書いてみました。
エスケープシーケンスは必要最小限のみです。
で、正常に動いているかどうかを確かめながら、
具体的にはWORDMASTERでファイル編集をしたときに、
PC上のTeraTermの表示と、WVGAの表示が一致しているかを確認しながら、デバッグです。
こちらはWORDMASTERを動かした場合のPC上(VT100)の表示です。
こちらはWORDMASTERを動かした場合のWVGAの表示です。上と、一致しています。
うん!大丈夫そうだなあ〜。
キーボードの改造は終わっていることだから、それとまとめてVT100ターミナルを一つ作っておくのもいいかもです。
ちょっと長くなるかもしれないので、番外編にまとめましょう。
#しかし、ネットは便利です。PICOのUARTの受信割り込みって、どうやればいいか知らなかったのですが、
#ネットでくぐればでてきました。そっくり使わせてもらいました。
RaspberryPiPicoのUARTでエコーバック #RaspberryPiPico - Qiita
ソースサンプル
作業再開 2025.9.13
キーボードの準備もできたことだし、作業再開です。
まずは、本体用のWVGAモニターの固定台を作成です。
アクリルの端材を使ってCNCで切り出しです。
最近、ようやくアクリルの切削条件がわかりかけて来た気がします。
いままでは、よく切れるようにと4枚刃で高速回転としていましたが、
直ぐにアクリルが溶融して刃先にこびり付いて、切削不可にになります。
そのため、切削油なので冷却していましたが、まわりが油でべとべとです。
その代わり、切断面は綺麗です。
できるだけ刃先の温度を上げないようにと、低速で回すとアクリルのこびり付きも
ありません。そしてエンドミルも樹脂用のものを使用です。
切削面は4枚刃のものに比べると、すこし粗いですが接着するには支障のないレベルです。
さてさて、アクリル板の切り出しが終わりました。接着も完了です。
さっそく支持台にWVGAを取り付けです。
キーボードとの接続に既存のUSB-Cコネクタをつかいましたが、ちょっと出っ張るのがやはり
すこし気になりますが、まあ完成してから色々と調整していきましょう!
アクリルの切削に、シングルエッジエンドの工具を使います。
回転数は6000rpmくらいがいいようです。
WVGAパネルの支持台ができました。
パネルが取りつくと、こんな感じです。
なにも考えずに、USBコネクタ接続としたものだから、ちょっと出っ張ります。
モニタとキーボードをぴったりと引っ付けるのは現時点では難しそうです。
完成してから、修正していきましょう。
そろそろWVGA接続基板を動かしましょう?あれ?
WVGAの取り付けが終わったので、そろそろ、先につくったRP2040アクセラレータ&WVGA接続基板の
動作確認に移行しましょう。WVGAとの接続には40PINのケーブルが必要ですが、
普通のフラットケーブルでは硬いので、個別に製作です。
作るのは面倒そうに見えますが、何かの箱にグルグルと巻きつけたポリエステル被覆銅線を、
一か所でぶち切れば同じ長さの銅線が揃います。それの予備半田をしておけば、
割りとストレスなく作ることができます。
40Pinのストレート接続コネクタを作成です。
違うところでストレスがあ〜
いざ、接続しようとしてピンを確認したところ、なにか違和感を感じます。
あ、接続基板側のピン配置の偶数と奇数間違えているぞ!!!
あ〜、これを事前に知っていたら、接続ケーブルを作るときに入れ替えたのになあ〜。
なんか、違うとことでストレスがかかります(笑。
2つの基板をストレートケーブルで接続しようとしましたが、接続基板(下側)のピン配置を間違えていました。
まあ、こういったことも長い半田付け人生ではあるものでしょう〜。
ということで、偶数と奇数ピンの入れ替えアダプタを作成です。
ちょうど、基板間を結合するための小型のバックプレーンが作ってあったので、
これを切り出して、変換コネクタを作成です。
そして、ようやく接続基板とWVGAの接続ができました。
基板間の接続のために作ってあった小型のバックプレーンです。これが役に立ちました。
偶数と奇数ピンの入れ替え変換基板を作成です。
ようやく、接続基板とWVGAが接続できました。
動作確認開始
いままではRP2040のGPIOをWVGAに直結で動かしていましたが、今回はZ80のバス経由での動作になります。
そのため、レベル変換のゲートを2回通ることになり信号の遅延が懸念されます。
さらには、アドレスデコーダでのCS(Chip Select)信号なども新たに加わります。
まずは、Z80のバスとは切り離して状態での動作確認です。
ただ、これで動いたとしても、Z80のバスにつなげると信号線の負荷が増えるので遅延が発生して、
動かなくなるかもしれまんが、そのときはその時で考えましょう。
RP2040とWVGAとはバス経由で信号を送るので、
信号遅延の影響が懸念材料です。
なお実際には、RP2040が勝手にバスを使うことはできないので、
コントロールセンターのPICからバス使用のリクエストを受けとってから
動くことになります..
RP2040からWVGAにアクセスするためには、PICからのバス利用の許可が必要ですので、
そのためのタイミングです。この部分は結構オーバヘッドがでそうですが、まあZ80が動くよりかは
随分速いでしょう..
まずは、バスを切り離しているので、基板内で常にバス利用可の状態をつくりだして、
WVGAの動作確認からです.。
おや?動いた?
ソフトを作成し、恐る恐る電源ONです。
WVGAに文字が表示されました。
あれ?動いた?
絶対に回路の1つや2つ、ソフトに3つや4つの間違いがあるかと思いましたが、
なぜか一発で動いてしまいました。
こりゃあ、順風満帆というか、あとあと怖いというか(罠が待っている?)。
まずは単体での動作が確認できました。
次は、Z80のバスに接続して動かしていきましょう。
その前に、ホスト(CPM80基板)もすこし手を加える必要があります。
思ったより変更必要だなあ〜 2025.9.14
新しく追加する基板もバスを占有することがあることから、
ホスト側すなわちCPM80基板の修正が必要です。
というのも、現状ではZ80からのBUSAKの信号でバスの占有が2区分に分かれていました。
なんせ、外からバス制御されるなんて想定していませんでしたから。
BUSASK=L PICがバス使用
BUSASK=H Z80がバス使用
これを、3区分になるように変更です。具体的には、こんな感じ。
BUSASKの信号 (HレベルでZ80がバス使用) |
|||
L | H | ||
C2信号 (LでPICがバス使用) |
L | PICがバスを 使っている状態 |
選択不可 (バスが衝突する) |
H | PIC,Z80もバスを 使っていない状態 ※RP2040が使える状態 |
Z80がバスを 使っている状態 |
上記になるように改造を行います。気をつけないといけないのは、表のようにソフト側でBUSASK信号
(PICのC3)がHレベル、すなわちZ80がバスを使っているときにPICのC2(PICのバス使用)
をLにすると、バスの衝突が発生します。そのため、BUSREQを有効にしたのち、
BUSASKがLレベルになったのを検知してから、C2をHレベルに変更しなければいけません。
ちょっとややこしいです。
改造する箇所は下図の通り。ちなみに全体の元の回路は→FAST-Z80..pdf
これを下記の部分を変更です。
今回の改造箇所です。ORゲート(IC18-3)が余っていたので助かりました。
修正後の回路です。z80_fast_mod.pdf
すこし残念なのは、従来はPICのA6,7を使って水晶発振で動かしています。
20MHzを4倍PLLの80MHzとして、オーバクロック状態です。
PICのピン数を追加で2個確保する必要があったため内部発振の64MHzに変更しました。
PICの処理速度が80%になってしまいます。SDカードの読み込み速度が遅くなるだろうなあ〜。
まずは、動作確認
PICおよびRP2040マイコン側のソフトを修正して、
CPM80の端末として動作できるようになりました。
これで、MZ80化計画はかなり前進です。
RP2040アクセラレータ&WVAG接続基板deCPM80が動き出しました。
頻繁に、バスの占有がPICやRP2040、Z80と入れ替わりますが、とくに問題はなさそうです。
ただ、現状では、ソフトの構造が歪なので、まだまだ修正が必要です。
まあ、のんびり進めましょう!
やはり遅いなあ〜 2025.9.16
一応、CPM80(Z80)からのグラフィックを直接アクセスできるかどうか確認です。
全画面に一定の色を描くプログラムです。C言語で組みました。
動かしてみると、一面を埋めるのに10秒前後かかります。
まあ、フルカラー(24Bit)で1点あたり3回の書き込みが必要です。
そのため800x480x3=約1.2M回のout関数の実行です。
10秒だとすると1回あたりのout関数の実行時間は8.7usかあ〜。
やはりかなりかかります。
RP2040にやらせたら、1/100以下でできるだろうなあ〜。
やはり、グラフィックを扱うにはRP2040で動くライブラリが必須な感じです。
CPM80のC言語のプログラムでは、画面を埋めるのに10秒前後かかります。
一応ハードは完成?
ソフトをすこし修正して、いきなりCPM80が立ち上がるようにしました。
これで、MZ80化のハードとしてはほぼ完成です。独立したシステムになりました。
これで完全に独立したシステムになりました。MZ80化のためのハードはほぼ完成です。
独立化のデメリットを対策しなくっちゃ!
独立したのはいいのだけど、大きなデメリットが発生です。
従来はPCと接続していたので、PCから、あるいはPCへのデータ転送がTera Term
を介して
簡単にできていましたが、それができなくなりました。
折角PC上で動くZ80ネイティブのCクロスコンパイラも入手したのに、これからのデータが受けとれません。
また音源基板もつくったのに、楽曲データの転送も考える必要があります。
なんらかの、データ通信手段を持たせたいところです。
さて、どうしようかなあ〜。
【備忘録】グラフィックライブラリ
z80だけではグラフィックのアクセスは時間がかかりすぎるので、biosコールを利用して
グラフィック処理をRP2040にまかせることにします。
biosコールの4番目はCONSOUTで、コンソールに一文字送出するルーチンで、
bios(4,'A')
とすれば、Aの文字がモニターに表示されます。文字のコードは基本的には128未満なので、
128以上の文字コードが入れば、グラフィック関連の処理を行うようにしました。
パラメータの引き渡しは、CPM80上の未使用RAMエリアを使います。
0xff30以降は使用していないので、0xff80以降の128バイトをパラメータの引き渡しとしました。
とりあえず、組み込もうとしているグラフィック関連の機能は下表の通りです。
関数 | コード 10進 | 16進 | 引数1 0xff80 uint16 |
引数2 0xff82 uint16 |
引数3 0xff84 uint16 |
引数4 0xff86 uint16 |
引数5 0xff88 uint16 |
引数6 0xff8a uint16 |
引数7 0xff8c uint16 |
引数8 0xff8e uint16 |
void gfcset(r,g,b) uint8_t r,g,b 描画の色を設定する。 |
128 | 0x80 | r | g | b | |||||
void gbcset(r,g,b) uint8_t r,g,b 文字表示の背景色を設定する。 |
129 | 0x81 | r | g | b | |||||
void gcsize(c) uint8_t c 文字サイズを設定する 0:5x7 1:8x8 2:10x20 3:16x16 4:24x24 5:32x32 6:48x48 |
130 | 0x82 | c | |||||||
void gclear() 画面全面を背景色でクリア |
144 | 0x90 | ||||||||
void gline(x1y1,x2,y2) uint16_t x1,x2,y1,y2; (x1,y1)-(x2,y2)へ線を描く |
145 | 0x91 | x1 | y1 | x2 | y2 | ||||
void glinex(x1y1,length) uint16_t x1,x2,length; (x1,y1)からx方向に長さlengthの線を描く |
146 | 0x92 | x1 | y1 | length | |||||
void gliney(x1y1,length) uint16_t x1,x2,length; (x1,y1)からy方向に長さlengthの線を描く |
147 | 0x93 | x1 | y1 | length | |||||
void gbox(x1y1,x2,y2) uint16_t x1,x2,y1,y2; 対角(x1,y1)-(x2,y2)の箱を描く |
148 | 0x94 | x1 | y1 | x2 | y2 | ||||
void gboxf(x1y1,x2,y2) uint16_t x1,x2,y1,y2; 対角(x1,y1)-(x2,y2)の箱を塗る |
149 | 0x95 | x1 | y1 | x2 | y2 | ||||
void gpset(x1,y1) uint16_t x1y1; 座標位置(x1,y1)に点を描く |
150 | 0x96 | x1 | y1 | ||||||
void gputc(x,y,c) 座標位置(x1,y1)に文字cを描く |
151 | 0x97 | x | y | c | |||||
void gputs(x,y,s) iuint16_t x,y; uint8_t *s; 座標位置(x1,y1)から文字列sを描く. s[n]=0で文字列終了 |
152 | 0x98 | x | y | s[0] | s[1] | s[2] | -- | s[n-1] |
|
uint16_t randint() 16bitの乱数 |
160 | 0xa0 | 戻り値 |
|||||||
float gsqrt(float a) 平方根 sqrt |
161 | 0xa1 | a 戻り値 |
|||||||
float gsin(float a) 三角関数 sin |
162 | 0xa2 | a 戻り値 |
|||||||
float gcos(float a) 三角関数 sin |
163 | 0xa3 | a 戻り値 |
|||||||
float gtran(float a) 三角関数 sin |
164 | 0xa4 | a 戻り値 |
|||||||
float gmul(float a,float b) 乗算 a x b |
165 | 0xa5 | a 戻り値 |
b | ||||||
float gdiv(float a,float b) 除算 a x b |
166 |
0xa6 |
a 戻り値 |
b | ||||||
void psg_init() 音源初期化 |
176 | 0xb0 | ||||||||
void psg_mute() 全音源無音化 |
177 | 0xb1 | ||||||||
void psgnon(note,vol) uint8_t note; /* 0 to 127 */ uint8_t vol: /* 0 to 127 */ PSG note ON |
178 | 0xb2 | note | vol | ||||||
void psgnoff(note) uint8_t note; /* 0 to 127 */ PSG note off |
179 | 0xb3 | note | |||||||
void gpcputc(char c) PCへ通信(1文字送信) |
184 | 0xb8 | c | |||||||
uint8_t gpcclr() PC受信バッファークリアー |
185 | 0xb9 | ||||||||
uint8_t gpcrhit() PC受信バッファー確認 0:受信なし 1:受信あり |
186 | 0xba | ||||||||
uint8_t gpcgetc() PC受信(一文字受信) |
187 |
0xbb | c | |||||||
C言語で描いて、このくらいの速度での描画になりました。
もっと速くなるかな?
PSG基板も稼働開始 2025.9.21
WVGA接続基板の配線チェックが面倒で、現実逃避でつくった音源(PSG)基板も動作させましょう。
まずは、.発振器が動作するようにPICを搭載です。
一連のコードをSi5351Aに書き込むだけですが、使用したPICがPIC12F615とかなり容量も小さい(1kW)
ものなので、それだけでもROMを37%も使っています。
でも、このSi5351モジュールって便利だなあ〜。PICとのセットで色々な周波数がだせます。
それに安価です。まあ、安価なせいか100pm以上の誤差があるので、基準発振器として使うのは
ちと辛いです。
1.78977MHzで発振するようにプログラムを書いたPICを搭載です。
PSGを動作させる関数の内容は、ほとんどRP2040基板に任せることにしました。
主に使う関数は下記の2つ。
psg_init()
初期化です。なにをするかというと、音階毎の周波数設定テーブルを作成しています。
計算には浮動小数点演算が必要なのと、テーブルも256バイト必要なのでRP2040側に持たせました。
psg_non(char note,char vol)
note on関数です。音階(note)と鳴らすボリューム(vol)を設定します。
PSGを動かすには、結構I/Oのアクセスが多いのと、最大12音源のON/OFFの管理をしなくては
いけません。すなわち、空いている音源チャンネルを探して、そこに設定データを送りますので、
結構なプログラムステップになります。時間がかかりそうなのでRP2040に任せることにしました。
音が鳴るようになったのだから、なにか簡単なゲームでも作りたいなあ〜。
レトロゲームだとブロック崩しかなあ〜。そのためにはボリュームが使えるように
AD変換器も必要だなあ。
問題先送り? 2025.9.24
キーボードのケーブルが邪魔で、キーボードをモニターに接近出来ない対策として、
キーボードの接続コネクタを基板前面に加えて、側面にも配置してみました。
これで、キーボードをモニターに近接できましたが、ケーブルが横にはみ出し、
またこれが邪魔です。
ああ、問題を先送りにしているだけだなあ〜。
基板の側面にもキーボード用のコネクタを追加です。
キーボードとモニターを近接できるようになりましたが、ケーブルが相変わらず邪魔だなあ〜。
PCとの通信機能を追加しよう! 2025.9.25
ちょっとしたサンプルプログラムをネットで探してきても、それをCPM80に転送する手段がありません。
以前はTera TermをつかってPCと接続していたので、エディタの起動中にファイル転送してやれば
よかったのですが、いまは独立したシステムになっています。
たとえば、下記のような表示ができるサンプルプログラムを動かしたくなっても、
いちいちキーを叩かなければなりません。これは、苦痛以外のなにものでもないなあ〜。
HI-TECH Cを使ってみた #CP/M - Qiita
ということで、PCとの接続手段を追加です。
RP2040のUARTのGPIO16,17)の別の用途につかっていましたが、
空きのGPIOに付け替えて、UARTを使えるようにしました。
PCとのUART通信にはUSB-RS232の変換モジュールを使います。
ただ、これはPCと接続されていないと送信端子のレベルがLOWレベルになるので、
無接続にしておくと、スタートビット、ストップビットが常に有効になってしまうので、
RP2040がゴミデータを拾い続けてしまいます。
そのため、USB接続がない場合は、RP2040の入力を強制的にHIGHレベルになるように
すこしロジックを追加しています。
転送速度は115200baud固定にしました。最大で約10kbyte/secの通信速度になります。
CPM80で扱うデータなんて、大きくても60kB程度なので数秒で転送が終わります。
CPM80側では受信データの終わりの検知は、一定時間データが送られてこなければ、
データ受信終了とするようにしました。
元の回路図。UARTUART端子のGP16,17は別の用途に使っていました。
GP16,17を空いている端子移して、UARTを使えるようにしました。
これで、テキストデータに加えてバイナリーデータもDLできるようになりました。
ついでに、テキストデータのULもできるようにしました。バイナリーデータのULについては、
Teara Termが対応できないようなので、保留です。まあ、使いませんが。
基板スロットを増やそう! 2025.9.26
現在のところベース基板には基板が3枚まで挿せるようになっていますが、すでに2枚刺さっています。
1枚はWVGAの接続基板(RP2040実装)。もう1枚はPSG(音源基板)です。
プログラムを弄っていていると、速度計測などで、やっぱり時計の機能も欲しくなってきます。
それと、ゲームをするためのADを含むI/O基板も欲しいかなあ〜。
そのため、あと少なくとも2〜3枚は挿せるようにしたいので、現状のスロットでは足りません。
ということで、増設です。増設といいながら、追加自体は難しいので、新規に作成です。
5スロットを実装するためにはバックプレーンをベース基板の上側に配置する必要があります。
となると、CPM80基板とベース基板の間隔が連結基板にマッチしません。そこで、
基板の接続コネクタをベース基板の裏側に取りつけることにしました。
こうすることで、偶数と奇数ピンが入れ替わりますが、連結基板のピン間隔も偶奇数が入れ替わる
間隔になりますので、ちょうど元に戻ります。
いまは3スロットですが、足りなくなりそうな予感です。
バックプレーン基板を上側に配置することで、スロットを5個に増やしました。新規作成です。
CPM基板との接続ピンは基板の裏側に取りつけました。
基板間隔と接続基板とのピッチを合わせるための策でです。
そのため、偶数ピンと奇数ピンが入れ替わります。
CPM基板との接続基板です。
コネクタの取り付けピッチを7x100milと奇数間隔にすることで、
接続基板でピンの偶数と奇数を入れ替えるようにします。
これで、5枚まで基板を挿せるようになりました。
1枚だけだとフラフラしますが、何枚か基板を連結しておくと固定力UPです。
Hi-TECH Cの憂鬱 2025.10.1
本機でMIDI演奏ができるようにと、PICO用に組んだファイルの移植作業をおこないましたが、
トラブル続発。コンパイラーが通ってもリンカーが通らない。コンパイラのエラーなら文法ミスを
指摘してくれるけど、リンカーの未定義の関数などのエラーならまだしも、内部エラーなんか教えて
もらっても、なにをどうすればいいかわからない。
最初にわかたのは、アンダーバーをつかうとエラーが出やすいことから、アンダーバーは
すべて削除。つぎに関数や変数の文字数はすべて8文字以下に変更。プログラムがだんだん
みににくくなっていきます。
それでも、コンパイラーは通るけど、リンカーが通らない。
もう諦めました。
リンカーの内部エラーなんか、わけわかりません。どうしよう〜。
(2025.10.2)
当初はMIDIファイルの中身を解析しながら演奏させる予定でしたが、もっと単純なプログラムに
変更です。PC側でデータを解析して、単に「(時間2バイト)+(音程1バイト)+(音量1バイト)」
の羅列となるデータを再構成させて、CPM80側では、単純にそれをPSGに書き込むだけにすることに。
割と簡単なプログラムですが、それでもリンカーから内部エラーがでてきます。
もう、何が原因かわかりません。
で、一部関数や変数の文字が8文字になっているものがあったので、試しに7文字まで減らしてみました。
そうすると、リンカーが無事終了です。プログラムも動き出しました。
え?Hi-TECH Cの関数や変数も文字数はMAX7文字なの?
なにか、信じられないような気がするのだけどなあ〜。
それならば、文字数が多い変数では最初の7文字なんか重複しているものがいっぱいあるから、
文句でも言いそうな気がするけれどなあ〜。
その後、色々と試してみると、
関数は7文字まで、変数はすこし長くても大丈夫そうというような感じです。
また関数にはアンダーバーは使用しないほうが良さげです。
変数にはアンダーバー使えるかは未確認ですが、大丈夫なような。
古いコンパイラーって、結構制約多いなあ〜。
(つづく)