2021年5月26日水曜日

FM-7/77にGOTEKを接続する(その2 新基板の場合)

 またGOTEKを入手してみたのですが... 基板が新しくなっていた

今までにFM-7, FM77AV, FM77AV40SXにGOTEKを装着してきました。そのうちのFM-7用はPC用の外付けFDDのケースと電源を利用して、GOTEKと2DDのFDDを装着して使用していました。ところが、その電源が不調で5Vのはずが8Vも出力されることがあり、そのためにUSBメモリが破損してしまい、さらにGOTEKも不調になったような気配を感じたので、新たにGOTEKを2台追加購入してみました。

今まではFM77に合うようにと黒色を購入していたのですが、今回はグレーにしてみました。購入時にチェックした点は、7セグが3桁であることと背部のピンヘッダの穴が9ピンであることの2点です。今回で8台目の購入となり、最初はAmazonで購入していましたが、今は選択の幅の広いebayで購入しています。(どちらにしろ中国から送られてきますので...)


基板がかなり変更されていた!

以前よりも短い期間で送られてきたのは良いのですが、7セグをOLED液晶ディスプレイに交換し、ロータリーエンコーダを追加するためにケースを開けて基板を見てびっくりしました。何と、ロータリーエンコーダの接続ピンがないのです。さらにCPUが変更されており、パターンも細かいところで異なっています。(下図画像参照)


左:旧基板、右:新基板



左のものは既にOLED、ロータリーエンコーダや圧電ブザーが取り付けてあります。基板を比較すると結構異なっているのが分かるかと思います。CPUは従来のものがSTM32F105であるのに対して今回のものはAT32F415で、ピン数も異なっています。


ロータリーエンコーダの接続先は分かりにくかった


OLED液晶ディスプレイの接続先は旧基板とそれ程異なっていなかったので、テスターで調べながら接続することができました。また、エンコーダのプッシュボタンも同様でした。
しかし、エンコーダのCLKとDTピンは基板に該当のピンがありませんので、新旧基板を見比べながらあちこちに接続してみましたがうまく行きませんでした。困った挙句、ウエブで「GOTEK Rotary encoder」という語で検索をかけてみました。その結果、「Gotek Floppy Emulator:New 2021 Flash Floppy and Mods Procedure!」というユーチューブの動画を見つけました。
この画像によると、新しいGOTEKはCPUがAT32F415になり、それに伴って基板も変更されているそうです。おかげでCLKとDTの結線先も分かりました。


新基板の結線図


OLED液晶ディスプレイとロータリーエンコーダを装着した様子です。ハンダ付けは裏面で行っています。フロッピーのアクセス音がなくても不自由はなかったので圧電ブザーは装着していません。


新基板の完成した状態



なお、OLED液晶ディスプレイは相性があるようですが、私の場合は全て下記画像のものを使用しており、特に不具合はありません。ロータリーエンコーダはプッシュスイッチ付きであればどれでも良いようです。


使用したロータリーエンコーダとOLED液晶ディスプレイ


OLED液晶ディスプレイの画面は小さいのですが、サイズはちょうどですし文字は見やすいです。


動作チェックの様子



使用感ですが、もちろん今までのものと変わった点はありませんが、ロータリーエンコーダでディスクイメージを選べるのはとにかく便利で重宝しています。
(蛇足ですが、現在使用中のGOTEKが電源故障のために不調になったのではないかと疑っていましたが、どうも杞憂だったようで現在は普通に使えています。)

新基板の情報があまり多くないようですので、多少なりとも参考になればということでアップしました。

2021年5月20日木曜日

W65C816も動作する6502基板を製作してみました

 6502基板を新たに製作し、W65C816をネイティブモードで動作させてみました


首を長くして待っていた基板がようやく届きました。

今回製作したものはFM-7/77用拡張I/O基板、FM77AV用Z80カード韋駄天、6502/65816基板の3種です。
拡張I/O基板は過去2回作り直していますが、今回のものはMAX232CとFT-232モジュールを外し、空いたスペースに2.45MHzの発振回路を追加することでFM-7の50P拡張コネクタに対応したものです。また、Z80カード韋駄天は第1作が動作するかどうかを確認するためだけに手間をかけずに製作したため、電源ラインが細いことやシルク印刷を省略していることなどが不満で、ちゃんとしたものに作り替えたいというものです。

今回報告する6502/65816基板ですが、以前報告しましたように、ほうめいさんから頂いたドータボードPLDR6502を自作6802ボードに搭載してW65C02を動作させることができましたし、その後、CPUをW65C816に交換してエミュレーションモードで動作することを確認していました。
しかし、動作したとなると6802ボードに間借りしたものでは如何にもW65C816がかわいそうということで、専用の基板を作ることにしました。


6502/65816基板


6502を使用した他の(市販)機器との互換性などを考慮する必要は全くありませんので、今までに製作した6802ボードや6809ボードと基本部分を同様にしましたが、データアクセス用のACIA(63B50)を減らしてその代わりに拡張コネクタを追加しました。

回路図

上位の32KBは必要に応じてRAM/ROMのどちらも使用できるようにしてあります。
データシートを見ると、ピン3のABORTBとピン36のBEをプルアップしてやればよいようですので、ピン36は常にプルアップし、ピン3はジャンパ―ピンで切り替えられるようにしてあります。

製作してみました。
右端の未配線の部分は拡張用のコネクタの取り付け部ですが、まだ取り付けていません。

完成したボード

基板ですがいつものようにポカがあり、LEDのアノードマークのAがカソード側に表示されていましたが、その他には特に不具合もなくあっさりと動作しました。

画像では、前回のドータボードで動作していたCPU, モニタROM, BASICROMをそのまま装着していますが、これで動作しています。

このLEDはピン35のE出力に接続してありW65C816がネイティブモードに入った時に点灯するようにしてあるのですが、リセット後にWozモニタで下記のようなコードを実行することで、ネイティブモードとエミュレーションモードを切り替えることができるようです。


モード切り替えコード


モード切り替え実行の様子


1000番地から実行すると画像のようにLEDが点灯し、1008番地から実行すると消灯することからモードの切り替えはできているようですが、6502については使用経験が全くないので、これ以上のことは今のところ私には分かりません。



LEDが点灯しています

6800や6809を長く使い続けてきた私の感覚では、6800ですら使いにくいCPUですのに、さらにレジスタも少ない6502ではプログラムを制作しようという気には全くなれませんが、大昔とはいえ、6502でAppleIIを創り上げたウォズニアックさんやVisiCalcのような実用ソフトを制作した方々には本当に頭が下がります。今は開発環境としてはとても恵まれていると思いますが、それに見合った結果が出せているのかと思うと...

65816なら6502よりもプログラムを作りやすいのではないかと思いますので、しばらくはこのボードでW65C816のプログラミングの練習をしてみようかと思っています。


2021年5月19日水曜日

6800用のGAMEインタプリタとコンパイラを6809に移植

 6800用のGAMEインタプリタだけでなく、コンパイラも移植してみました


動機

発注してあるプリント基板が未だに届かないので最近はソフトばかりいじっていますが、前回は6800用のTL1コンパイラを6809に移植することができましたので、その勢いで、今度はGAMEインタプリタとコンパイラの移植に挑戦してみました。

GAMEインタプリタの6809への移植は、既に1981年に藤原誠さんによる「GAME09インタプリタ」や、1984年の萩平哲さんによる「GAME-FMインタプリタ・コンパイラ」があり、いずれも実行速度や機能面で非常に優れたもので、私もインストールして使わせてもらっていました。しかし、いずれもソースは公開されておらずバイナリコードだけです。

移植するコンパイラは

今回移植しようと考えたものは、2019年5月8日のブログ「6802基板でGAME68コンパイラを走らせる」で紹介した「GAME68コンパイラ」で、松島義明さんがGAME自身で記述されたものです。

GAME自身で記述されているということは、コンパイラとしての論理構造は6800でも6809でも変わらず、コード生成の部分だけが異なっているということになります。

そして、生成されるコードは6800のバイナリであるわけですが、前回のTL1でも述べましたように、6809と6800のバイナリにはそれほど大きな違いはないので、異なっているものだけを書き換えるだけで済むのではないかと考えました。(安直ですね。)


コンパイラのランタイムルーチンを見ると


まず最初にランタイムルーチンを調べてみました。

GAMEインタプリタ内のルーチンを利用していることもあって、わずか300バイト足らずの小さなものですが、逆アセンブルしてみたところ、6809と異なっている命令はNOPとLDXのみでしたので、簡単に書き換えることができました。

しかし、インタプリタ内のルーチンを使用しているということは、実行時には6809版のインタプリタが必要ということになりますので、コンパイラより先にインタプリタの移植が必要だということになります...


インタプリタの移植が必要だった

ということで、まずインタプリタの移植に取り組むことになりました。

6800用インタプリタもTL1と同様にアセンブラソースが公開されていますので、TL1の時と同じようにスタック命令に注意しながら書き換えることで、それ程苦労せずに動作させることができました。(私の場合はハードもソフトも速さにはそれ程こだわらず、正常に動作すれば良しというスタンスですので、最適化などはほとんど行っていません。)


インタプリタの移植が済んだので

インタプリタの移植が済んで、コンパイラのランタイムルーチンが呼んでいるルーチンのアドレスが確定しましたので、GAME68自身で記述されているコンパイラの関係するアドレスを書き換えたものを作り、簡単なプログラムで生成されたコードを調べてみました。

すると、Xレジスタ関連の命令とPSH,PUL命令を書き換えただけで動くプログラムもあるではありませんか。

この結果に気を良くして、コンパイラのソースを読んでみた限りでは、コンパイラで生成される命令の中で、6800と6809とでコードが異なるものとしてはLDX, STX, INX, TAB, TBA, PSHA, PSHB, PULA, PULBの9種がありましたが、これらはバイト数が異なるものの、置き換えにはそれ程困難はなさそうです。しかし、それらに加えて一部にLDS, STSというスタック関係の命令も使われているようですので、これらについては注意が必要です。

[5月23日追記]訂正:LDS, STS命令は使われていませんでした。


GAME09コンパイラ(らしきもの)を作ってみた

とりあえず、スタック関係の命令はそのままにしておいて(GAMEのどの命令で使われるのかまだ分からないので...)その他の命令だけを置き換えたものを作成してみました。


動作環境の詳細

使用した6809ボードは前回と同じ6809/6802DualCPUボードです。


6809/6802 Dual CPUボード

メモリマップです。


メモリマップ

ソースプログラムの格納領域は、TL1コンパイラの場合と合わせて $3000 からにしています。

オリジナルのランタイムルーチンは $2100~$22BA ですが、その先頭に生成オブジェクトへのジャンプ命令(3バイト)を追加し、JMP $2100で実行できるようにしています。

それぞれのプログラムの読み込みですが、あらかじめMOT形式に変換しておいて、自作モニタの LコマンドやASSIST09の LOADコマンドでロードしています。

そのMOT形式への変換プログラムですが、前回のTL1コンパイラのソースの場合はエディタで行番号を付けずに作成したものを変換しましたが、GAMEのソースの場合は行番号が付いていますので、それをバイナリに変換して新たに格納アドレスを付加するように機能拡張しました。また、付加する行番号や格納するアドレスを指定できるようにもしました。


CvtTxtTl1Src.exe


コンパイルの実行手順

次のような手順でコンパイルを実行します。

1.モニタでGAME9インタプリタをロードする

       L GAME9EX

        拡張機能付きのGAME9が$0100からにロードされる

2.インタプリタを起動する(コールドスタートで)

        G 100

3.モニタに移動する

        >=$F800

4.ソースプログラムをロードする

        L (source file)

        ソースプログラムが $3000 からにロードされる

5.GAME9コンパイラとランタイムルーチンをロードする

        L GAME9CS

        ランタイムルーチンが$2100からに、コンパイラが $4000 からにロードされる

6.GAME9インタプリタに戻る(ホットスタートで)

        G 103

7.コンパイラをアクティブにする

        =$4000 (先頭アドレスのセット)

        ==          (末尾アドレスをサーチ)

8.コンパイルを実行する

        #=1


実行例

実行した例を示します。オリジナルではワークエリアなどいくつかの問い合わせに答えてからコンパイルが始まりますが、ソースプログラムの格納エリアなどを決め打ちしましたので、#=1ですぐにコンパイルが始まります。

実行例

コンパイルの終了後、GAME上で >=$2100 とすると生成されたオブジェクトが実行されます。


終わりに

まだ全ての6800命令を6809命令に書き換えてはいないのですが、いくつかのプログラムをコンパイルして正常に動作することを確認しました。

以前「GAME68コンパイラ」のブログを書いた際に、コンパイラの作者の松島義明さんから掲載の許可をいただいていますので、今回の6809へ書き換えたものも公開しても良いと思います。

今の時代にGAMEやTL1を使おうという奇特な方がおられるとは思えませんが、もしご希望があるようでしたら、書き換えられずにそのままになっているスタック関係の命令の書き換えが終了しましたら公開する予定です。変換プログラム CvtTxtTl1Src.exe についても同様です。

以上、私の単なる思い付きでやってみたことで、実用性はほとんどありませんが、巷間、6800と6809とはバイナリレベルの互換性が無いので云々という評価がありますが、全く異なっているわけではないので、違っている部分にだけ注意を払えばこんなこともできるというサンプルになれば幸いです。(と言っても、今どき、6800はおろか6809のプログラムですら化石時代の遺物みたいなものでしょうが...)


2021年5月9日日曜日

6809ボードマイコンにTL/1コンパイラを移植する


 今更ですが自作の6809SBCに、いにしえの6800用TL/1コンパイラを移植しました

TL/1コンパイラは1980年に大西博さんが制作された6800用のコンパイラで、その特徴は変数のサイズが1バイト(8ビット!)であることで、サイズも4kB余りとコンパクトなワンパスコンパイラです。大西さんがその前に制作されたGAME言語と同様、ソースが公開されていたので様々なパソコンに移植されました。私もFM-7に移植されたTL1-FM版を入力して使用していましたが、FM77に移行してからは使用することが少なくなりました。

いつかは自分なりの言語を作りたいと思っていて、あれこれ考えているのですが(考えているだけで全然進んでいない...)、1バイト変数なら比較的簡単に作れるのではないかと思い、まず6800用のTL/1を6809に移植することでコンパイラ作成に関する具体的な知識を得ようと思って始めましたが、何と一ヶ月近くもかかってしまいました。

多少なりともどなたかの参考になればと思い、ここに顛末を記しておきます。


移植の手順ですが次のように行いました。

(1)ソースプログラムの6800の命令コードを6809の命令コードに置き換える。

多くの命令は単純に置き換えることができますが、スタックの使い方が6800と6809とでは異なるので注意が必要です。特に、スタックを演算等に使用している部分は新たに書き換える必要があります。また、CPX命令($8C, $9C)を演算ではなく次命令のスキップに使用しているケースもあります。

(2)コンパイラの生成コードを6800用から6809用に置き換える。

6800と6809とではバイナリレベルでの互換性はないと言われているのですが、同じ命令コードのものが結構多くあります。異なっているものでも、LDX($DE→$9E)のようにすぐわかるものは良いのですが、同じような機能であるにもかかわらず、一部異なっているという命令があるので厄介です。(下に記述)


移植した6809ボードです。これは2018年10月15日のブログ「6809/6802両用基板が完成しました」で紹介したボードで、6809と6802をスイッチで切り替えることができます。切り替えた際、メモリはクリアされないので一方のCPUで作成したデータを他方のCPUで利用することができます。また、ACIAを2個搭載しており、一方はコンソール用で他方はデータ入出力用で、どちらも38400Baudで動作しています。



移植した6809/6802 DualBoard


具体的には、次のような手順で進めました。

準備として、オリジナルのTL/1ではGAMEで作成したソースファイルが$3000からにストアされているものとしてコンパイルしますが、毎回GAMEを起動するのは面倒ですし、行番号を付けるのも煩わしいので、Windows上のエディタでソースを作り、それをGAME形式に変換したうえでmot形式に変換するソフトCvtTxtTl1Src.exeを作成しました。機能としては、行番号の付加、その行番号のバイナリ変換、行末コードの$00への変換、ファイル末への$FFの付加、そしてmot形式への変換です。

下図のように、ファイルをドラッグ&ドロップするだけで変換結果が得られます。



CvtTxtTl1Src




作業手順


(1)自作6809SBCに搭載しているモニタのLコマンドでmot形式のソースを$3000からに読み込む。

(2)mot形式に変換した試作コンパイラを$1000からに読み込む。

(3)モニタのGコマンドで$1000から実行し、オブジェクトを生成する。

(4)生成途中でエラーが出たら、コンパイラのソースをチェックして関係ありそうな箇所を修正する。修正後(2)から繰り返す。

(5)無事にオブジェクトが生成されたら、Gコマンドで$2000から実行してみる。エラーが出たり、結果がおかしかったりしたらソースを修正して(2)から繰り返す。

(6)意図した通りの実行結果が得られたら完成。


このような手順で、変数への代入、制御構造の確認、関数や手続きのデータの受け渡しなどを順に確認していきましたが、最後まで手間取ったのは関数や手続きで2個以上のローカル変数があると動作がおかしくなるというバグでした。

使用した6809SBCは6802と6809のDualボードですので、正常に動作することが分かっている6800TL/1でオブジェクトを作成し、それと6809TL/1で作成したものとを比較しながらチェックを繰り返しましたが、例えばオリジナルのTL/1の記事中の8-QUEENのオブジェクトなどは6802と6809とで全く同等のものが作成されるようになったにもかかわらず、6802では正常に動作するのに対して6809ではハングアップしてしまいます。もちろん、ランタイムルーチンが正常に動作していることは確認してあります。

こんな状態が1~2週間ほど続き、いい加減倦んできて諦めようかと思ったりもしましたが、私のSBCには自作のモニタの他に6802にはMIKBUG2、6809にはASSIST09を搭載してありますので、TL/1の入出力をASSIST09に合うように書き換えてASSIST09に移行し、そのトレース命令を用いて、1命令実行するごとにワークエリアとオブジェクトのエリアをダンプしてチェックするという面倒な作業を繰り返すことで、ようやくバグの原因をつかむことができました。

バグの原因は、STA n,Xというインデックス命令でした。6800ではnは8ビット範囲であるのに対して、6809ではnが0~7Fの範囲では5ビット命令となるのです。TL/1ではSTA n,Xのnを動作中に書き換えるというコードを多用していますが、例えばnを0から1ずつ増やしていくと15までは正値ですが、その次は負値の-16になってしまうのです。

6809ではアキュムレータオフセット命令がありますので、

  6800での命令        →  6809での命令

  (2命令で計5バイト)       (1命令で2バイト)

  STB xxxx  (xxxxはnのアドレス)   STA B,X

  STA n,X

という計5バイトの命令を2バイト命令に置き換えることができ、これでバグを解消できました。

まだ全ての組み込み関数などのチェックを終えているわけではありませんが、現在の所は動作におかしな点は見つかっていません。

それにしても、オブジェクトコードを動作中に書き換えることでコンパクトなコードを生成できているわけですが、一方、この点でROM化できないという批判的評価があったことを思い返すと、6809特有の命令に置き換えることで図らずもこの点が解消されたのは嬉しいことでもあります。さらに、$2000からのランタイムルーチンを含めて、生成コードをポジション独立にすることができればOS-9上で動作させることも夢ではなくなるかもしれません。


この移植作業を通して、制御構造などに対するオブジェクトの生成法の理解が進みました。

しかし、ASSIST09のトレース命令はとても強力なツールですね。できれば私のモニタにも実装したいものです。

最終目標は、6809SBCにOS-9Level1をインプリメントして、その上でTL/1などの言語を走らせることですが、ほんの少しですが先に進めたような気がします。

確か、大西博さんは大学の先生で文系の方だったと思いますが、GAMEやTL/1の発想というか独創性には本当に感心します。


いつも参照している下記の2冊

・MC6809-MC6809E マイクロプロセッサ プログラミング マニュアル(Motorola)

・6809アセンブリプログラミング(末永朝雄著、サイエンス社)

に加えて、この本が大変参考になりました。特にオブジェクトの生成法の解説がTL/1の理解に役立ちました。

・Z80CPU対応 新言語オリジナルコンパイラ作成の技法(大貫広幸著、MIA社)