カテゴリー別アーカイブ: Λ-1

6800FLEX Basic と ASCIIART

Lambda-2022 マシンで FLEX 2.0 が動くようになりました。6800 / 6809 用 DOS である FLEX はマイコン DOS としては比較的初期の製品になりますが、アセンブラをはじめ各種言語が利用できて便利です。

「DOS」といっても物理フロッピーディスクならびにドライブをいまさら使う必要は感じられないので、シリアルサーバ Apple2pi のコードを改変して FLEX ディスクドライブをエミュレートしました。Apple ProDOS が 1 ブロック 512 バイトなのに対して FLEX は 1 セクタ 256 バイトが読み書きの最小単位であるため、Apple2pi のディスクエミュレーションコードの該当部分を変更します。FLEX のセクタ数とトラック数はディスク TOC に書かれたパラメータに応じて可変となるので、その処理も追加しました。6800 用クライアントコードは 6502 クライアントコード(a2pi.s)を参考にして新規に書きました。

FLEX ブートディスクイメージの作り方については Old68fun 様のページの情報が大変参考になりました。

FLEXシステムの作成方法(その3)・・・6800FLEXの場合

さて DOS が起動するとまず BASIC を使いたいところです。最初の手習いは当然、ASCIIART.BAS です。FLEX Basic で ASCIIART 画面をきれいに出力するには FLEX の TTYSET コマンドを使って 80 桁改行、ページャなしに設定する必要があります。

1 MHz 6802 / Flex 2.0 Basic:05:05.37

同じ 1 MHz 6800(6802)で動く Altair680 Basic と比較すると若干高速であることに気が付きます。

1 MHz 6802 / Altair68 Basic:07:35

同一プロセッサ、同一クロック数でこの処理速度の違いは?思って調べると、FLEX Basic はどうも浮動小数点の精度が低めなようです。試しに 10 進での有効桁数を確認しました。

1.00001 が表現できて 1.000001 が表現できないということは10進数有効桁数は7未満です。FLEX Basic マニュアルには「10 進 6 桁精度 (“six decimal digit accuracy”)」と記載されています [1]。

2^16 < 10^5 <  2^17  < 2^19 < 10^6 < 2^20

という比較が成り立つので、FLEX Basic 浮動小数点数の仮数部は 17-19 ビットの範囲のいずれかであるようです。例の「ケチビット」を勘定に入れると仮数部は 16-18 ビットで表現可能でしょう。また指数部については検証を怠りましたがマニュアルによると +/-38(10進)ですから 2 進換算で 7 ビット、これに加えて符号 1 ビットが必要となります。

FLEX Basic はおそらく 24 ビット精度の浮動小数点を使用していると推測されます。Aitair680 Basic その他初期 MS Basic は多くの場合 40 ビットまたは 32 ビット浮動小数点です。24 ビット浮動小数点の FLEX Basic で ASCIIART を実行した場合、計算量が少ない分速くなると言えそうです。

[補注]よく数えたら仮数部が 16-18 ビット、指数部(指数符号を含むオフセット表現)が 8 ビット、符号が 1 ビットとなり全体では最低でも 25 ビット必要になります。8 ビットマシンにしては半端なビット幅なので何か計算違いしている可能性があります。

参照

  • 1. TSC Basic Users Manual, 1979, Technical System Consultants, Inc.

自作 ASCII キーボードを Apple II Plus に接続する

ここしばらく作成している ASCII キーボード LMD-3420 の基本機能は 7 ビット ASCII キーコードをパラレル出力することです。またこれとは別に、キー押し下げイベントを信号立ち上げ(または立ち下げ)として表す 1 ビットの Strobe 出力があります。

Lmbda-3420 キーボード。ALPS AKB-3420(ほぼ)互換

このようなキーボードをコンピュータに接続する場合、CPU からは 7 ビット ASCII コードは通常の I/O ポート入力として読み出せばいいのですが、Strobe 信号は立ち上がりでフラグがセットされるフリップフロップとして保持し、CPU から任意の時点で読みに行けるようにしておく機構が必要です。また、ASCII コードを読み出したときにフラグが自動的にクリアされると便利です。Λ-1 コンピュータでは MC6821 PIA の CA 入力を使用することでキーボードからの Strobe 出力に即した設定が可能です。ASCII コードの 7 ビット出力は PIA の 8 ビットポート PA に接続します[注 1]。

実は Apple II のキーボードインターフェイスも全く同じ構成です[注 2]。違いは ASCII コードが負論理(Λ-1)か、正論理(Apple II)かという点だけです。したがって LMD-3420 のファームウェア(qmk_firmware のカスタムコード)で ASCII コードのビット反転操作を無効にすれば Apple II へ接続できます [注 3]。

Apple II のキーボード端子は 16 ピンの IC ソケットで、下図のピン配列になっています。これにあわせて LMD-3420 キーボード基板にも同様の配列の 16 ピンソケットを用意しました。上の画像でいうと基板上端の右寄りのソケット(ケーブルが取り付けられていない)です。

※ 実際には 1/16 ピン側が Apple II 基板手前となる(出典:
http://www.1000bit.it/support/manuali/apple/R023PINOUTS.TXT)

Apple II キーボード端子と LMD-3420 キーボードを 16 pin DIP 端子のフラットケーブルで接続します。DIP ソケット対応のコネクタ端子は最近あまり見かけませんが、当時はそれなりに使われていました。

DIP ソケットのフラットケーブル

このケーブルは DigiKey で注文するとワンオフで受注生産してくれます。特に高価なものではありません。

キーボードケースとキーキャップ

これまで LMD-3420 キーボードは基板むき出しの状態で使用していましたが、完成を目指してケースと下部構造を追加します。下部構造として、適切な傾斜のついた桁構造で基板とスイッチプレートを下から支持します。左右に 2 本と、中央に小さな桁を 3 個組み合わせた構造を使用しています。左右の 2 本はケース上面の左右端を支える構造にもなります。これらの桁構造は自宅の 3 D プリンタで出力しました。インサートナットを取り付けてねじ止めが容易になるようにします。

桁構造部品の 3D デザイン

また ABS 板を切り出してキーボード底板を作りました。ここへ 3 本の桁構造をねじ止めします。ねじのうち 5 本はゴム足を取り付けるためにも利用します。

キーキャップは SA プロファイルの Aifei 製 Fishing 互換セットに変更しました。LMD-3420 キーボードは一部キー配列が変則的なので既製品のキーキャップセットでは形状・キーレジェンドが完全に適合するものが見つからない部分もありますが、今回使用したキーキャップセットでは少なくともサイズと行が合致するキーキャップがひと通り揃っています。

唯一不足するのは 8u のスペースバーです。こんな長いスペースバーを現代のキーキャップセットに期待するほうが間違っているので、あきらめて自作することにしました。ところが、スタビライザも 8u サイズのものは簡単に見つかりません。そこで 7u スタビライザが使えるように自作スペースバーのスタビライザ用ステムの位置をずらしました。スイッチプレート上のスタビライザ取り付け穴も 7u 相当の形状で設置しています。

スペースバーの 3D デザイン。スタビライザ取り付け位置は 7u 相当

このキーボードの上にケースを取り付けます。ケースは長方形の板からキースイッチ部分の穴をくり抜き、前部・後部を折り曲げた形状になっています。上面は桁構造で決まる斜面に沿って前傾しています。オリジナルの AKB-3420 ケースは金属板を折り曲げ加工しているのだと思いますが、実物を触ったことがないのでよくわかりません。今回は加工後の形状のケース部品を、8u スペースバー部品とともに 3D プリントサービスへ発注しました。ケースには 128×32 ドットの小型 OLED ディスプレイと Raspberry Pi Pico の USB コネクタ部分を外に出すための穴を開けてあります。

ケースの 3D デザイン

ケースのサイズは 36cm x 18cm で主要部分の厚さは 2mm です。サイズに比べて厚みが足りないようで、発注先 JLCPCB の 3D プリント部門から「細い部分でひずみが出るかも」というデザインレビュー警告が来ましたが「とりあえずこのままプリントしてください」と回答しました。到着した実物を確認すると案の定、ケース手前の一番細い部分が若干歪んでおりキーボードスペースバーと干渉しかねない形状になっています。ヒートガンで温風を当てつつ手で逆方向へ曲げることで問題ない程度まで修正しました。

ケース(ひずみ修正済み)と 8u スペースバーを取り付けた状態

レジン製のケースは乳白色の地味な色合いなので、この上にステッカー式のカスタム印刷デザインシートを貼付しました。以前 Λ-1 のフロントパネルに貼ったものと同じ製品です。色もフロントパネルに合わせてあります。

貼付け前のデザインシート。これは同時注文した色違い版
デザインシートを貼ったケース。OLED と USB コネクタの部分に 3D プリント製のカバーを追加しています

Apple II plus キーボード端子に接続

Apple II plus 純正キーボードは小文字入力モードがなくデフォルトで英大文字が入力されます [注 4]。また一部の記号キーが足りず Shift-P で ‘@’、Shift-N で ‘^’、Shift-M で ‘]’ を入力するようになっています。LMD-3420 キーボードではこれらの記号にもそれぞれ ANSI のキーが割り当てられているので、Shift-英文字キーによる記号入力機能は割愛しました。

前述のフラットケーブルで LMD-3420 と Apple II plus キーボードコネクタを接続し、電源投入して問題なく入力できることを確認しました。

なお上の画像では LMD-3420 キーボードが Apple II の幅より大きく見えますがこれは遠近法による錯覚で、実際には LMD-3420 も Apple II ケースも横幅はほぼ同じで 14 インチ(36 センチ)内外です。

ファームウェアの設定を変えると Λ-1 に対応

[1] 8 ビット幅の PIA A ポートに 7 ビット ASCII パラレル信号を接続するので、MSB 1 ビットが余ります。Λ-1 および Chick-Bug の設計ではこの MSB に VDG の書き込み禁止 FS 信号を入力しています。ということは、画面書き換え処理を行うたびに CA1 のキーボードストローブがクリアされるという動作になります。どうやらこれは意図的な設計らしく、Λ-1 システムでは画面書き換えが完了するまで次の文字は入力できないという挙動になります。

[2] オリジナル Apple II と Apple II plus の本体基板だけがパラレルキーボードインターフェイス対応のコネクタを備えています。Apple IIe 以降ではエンコード回路も本体基板に内蔵されるため、キーボードコネクタはもっとピン数の多いものになっています。

[3] ただし実際には左矢印キーの扱いなど一部例外的な処理があるので、キーコードマッピング自体も変更してあります。

[4] 後期リビジョンの Apple II plus では小文字入力も可能です。

Λ-1/Lambda-2022 の拡張(10)ASCII キーボード基板

表題の「ASCII キーボード」は以前の投稿で「パラレルインターフェイスキーボード」と呼んでいたものと同じです。これをプリント基板化しました。リファレンスモデルである ALPS AKB-3420 にあやかって “LMD-3420” と名付けました。完全にまねっこですが、本家の方は廃版になって久しいのでまあいいんじゃないかとうやむやにしておきます。

基板化にあたってシフトロックインジケータと i2c OLED ディスプレイを追加しています。

既存の XVX キーキャップを使用

LMD-3420 のキー物理レイアウトは AKB-3420 に準拠します。右端列の 5 個の独立スイッチを再現したかったためです。独立スイッチはキーマトリクスに含まれずそれぞれ個別に GND に落ちる配線になっており、システム割込みやリセットに使用します。右から二列目の 5 個のキーにもリレジェンダブルキーキャップが使われており外見は右端列キーと同一ですが、この列は通常のキーマトリクスに含まれます。AKB-3420 ではコントロールコードが割り当てられていますが、LMD-3420 では現代のキーボードで標準装備されているバッククォート、バックスラッシュなどの文字種を割り当てています。このあたりは qmk ファームウェアで自由に設定できます。

物理レイアウトこそ AKB-3420 に一致させたものの、論理レイアウトは ANSI 配列に変更してあります。

上:AKB-3420 キー配列、下:LMD-3420 キー配列

AKB-3420 と異なる点がもう一つあり、今回使用したキースイッチは Cherry MX 互換品です。AKB-3420 で使用されていた ALPS SKCC キースイッチは現在ほぼ入手不可なため今回の基板では採用しませんでした。ALPS SKCC は Apple IIe や Apple III にも使われており個人的には親しみ深いスイッチなのですが、まさかこれらのビンテージ機種から部品取りするわけにもいきません。このため今回の基板設計では現役で流通している Cherry MX 対応としました。

qmk ファームウェアに追加したカスタムコードで GPIO Expander PCF8574A を制御し、パラレルインターフェイス端子へ ASCII コードと Strobe 信号を出力します。インターフェイスとして AKB-3420、Λ-1、Apple II、および USB の 4 種類を備えており、それぞれ仕様が異なります。Apple II と AKB-3420/Λ-1 では文字コードの正論理・負論理が異なるのですが、これはファームウェアを書き換えることで切り替えます。なお Apple II インターフェイスは未テストですので、万が一この基板で動かなければリビジョンアップということになります。

LMD-3420 基板。上に乗せてあるのは比較用の SBC サイズ(80mm x 100mm)基板

基板の製造と組み立て

基板製造は JLCPCB に発注しました。このサイズの基板が 5 枚で $26、同時にスイッチプレートも設計して発注しました。しかしフルキーのスイッチプレートをガラスエポキシ板で作ると特殊形状の穴加工が多すぎて追加料金が発生します。さらにこのサイズの基板やプレートだと重さに比例して送料が増え、トータルコストは $90 弱まで膨れ上がりました。まとめて注文するメリットはそれほどないようです。それでもたとえばアクリル製スイッチプレートを別業者に頼んだ場合よりも総額では安価になります。

この基板とキースイッチ、スイッチプレート、MCU(RPi Pico)などを組み合わせてキーボードとして機能するところまで組み立てました。AKB-3420 の元設計だと角度を付けた 2 本の金属製の脚を基板の左右両端に取り付けるのですが、今回の設計では基板、スイッチプレートともガラエポ製であるため左右 2 本の脚だけでは剛性的に不十分で、中央付近に補助的な脚を追加する必要があると思われます(基板上にネジ穴だけは用意してあります)。これら取り付け脚やケースについては 3D プリントで作る予定ですがその作業は次回以降に先送りすることにして、まずは通電テストを目指し、基板むき出しのまま最低限の組み立てを完了させます。

スイッチプレートもほぼ同サイズ

キーキャップ問題

キーキャップの選択は悩みどころで、現在は XVX プロファイルの既製品を流用しているのですが随所にサイズの合わない部分が発生します。特に AKB-3420 のキー配列を再現する場合は 1.5u のキーキャップがすべての行で必要になる点、また当時の常でスペースバーが 8u の長いものである点が問題となります。実用上は現状でもあまり困らないのですが、将来ケースを取り付けた際にきれいに長方形に収まるようにしたいと考えています。以下のキーが不足します。

  • Backspace (R4, 1.5u)
  • ’Q’ (R3, 1.5u)
  • LF (R3, 1u)
  • Ctrl (R2, 1u)
  • Tab (R1, 1.5u)
  • Caps (R1, 1u)
  • Space (conv., 8u)
  • Esc (R1, 1u)

なお行名は下から R1, R1, R2, R3, R4 としてあります。キーキャップの行名は上から R1, R2, … と数える流儀と下から数える流儀があって統一されていないようです。

不足キーキャップはいずれ 3D プリントでカスタム設計することにしますが、上に挙げたキーキャップをすべて作り直すと R1〜R4 までまんべんなく設計する必要があり、作業量を考えると二の足を踏みます。しかし、実は同行・同サイズのキーはキーキャップセット内を探せば割とあるのです。レジェンド刻印のみ異なるキーキャップを再利用すればいいわけです。こういったキーキャップの再利用を検討に含めるとカスタムメイドが必要なキーキャップの数を減らせます。

同行同サイズのキーキャップを代用して可能な限り外形を合わせた状態

レジェンド刻印を無視すれば次のキーが不足するということになります。

  • Backspace: R4, 1.5u
  • R-Shift: R1, 2u(キーキャップセットによる)
  • Space: Convex, 8u

また今回は XVX プロファイルのキーキャップセットを使いましたが、これは必要となる 1.5u、2u のキーキャップがそれなりに揃っているという理由で選択したものです。最終的にいくつかのキーキャップを自作して補充するのであればよりクラシックな SA プロファイルのキーキャップセットを選択するという手もあり、このあたりはまだ決めかねています。

リファレンスモデル ALPS AKB-3420

Λ-1 接続テスト

組み上がったキーボードを 16 ピンフラットケーブル(IDC 端子)を使ってΛ-1 コンピュータに接続します。qmk ファームウェアの設定は以前プログラムしたものがほぼそのまま流用できたのでこの接続テストはハードウェア、ソフトウェアとも大きな修正なく完了しました。キーボード右上端の独立スイッチを使った ATTN キー(インタラプトキー)によるモニタプロンプト呼び出しもできます。なお Λ-1 コンソールは小文字非対応なので CAPS LOCK を常にオンにする必要があります。

Λ-1 に接続してテスト。右の大きなディスプレイは使っていません

今後の計画

基本的な動作を確認できたので、完成に向けて次の作業を進めようと思います。

  • 底面と支柱の設計・プリント
  • 不足キーキャップの設計・検証と発注
  • ケースの設計と発注(外装シートも含む)
  • Apple II 接続テスト

Λ-1/Lambda-2022 の拡張(9)カセットインターフェイス

マイコンシステム Λ-1 は外部記憶装置としてカセットテープレコーダを使います。データ保存にテープレコーダを利用する手法は特に珍しいものではなく、1980 年前後の 8 ビットパソコンでは標準的な記録方式でした。コモドール 8 ビットマシン(PET/CBM/VIC/C64)や MZ-80 のようにデジタル信号専用インターフェイスのカセットデッキもあったようですが、多くは普通の音楽録再用デッキ(ラジカセ含む)の入出力端子に接続することを前提とした設計でした。Λ-1 も市販のカセットデッキを外付けする仕組みです。

カセットデッキ回路は音声信号処理を目的とするので 15 kHz 以上の成分の録音・再生は保証されません。接続方式によっては出力の位相が反転する可能性もあります。これらの条件に適した信号を変調・復調できるインターフェイス回路が必要です。

出力信号のソースは PIA の出力ポートなので 5Vp-p の矩形波です。パルス幅の違いでビット値 0 と 1 を表し、0 が 1400us、1 が 700us のパルス幅となります。なお実際には 1 ビットのデータあたり 1 周期分を出力するのでビット値 0 の出力に 2800us、ビット値 1 の出力に 1400us を要します。

「マイコン手づくり塾」記載の回路を参考にインターフェイスを組みました。回路図は次のとおりです。

PIA に接続する他の回路、つまりキーボード入力ポートや K68-VDG の垂直同期信号入力ポートなどもこの回路図に含まれます。図の中央付近がテープレコーダ録音再生のための変復調回路ですが、面白いのはカセットテープから再生された音声信号をパルス幅測定に適した波形に加工する復調回路です。入力音声信号をクランプ回路でクリップしたあとでコンパレータを通して矩形波に整形するのですが、Λ-1 の設計ではコンパレータとしてオーディオレベルメータ用 IC の三洋 LB1405 を使います。レベルメータ LED を見ながら入力レベルを調節できます。

Lambda-2022 筐体に組み込んだ回路基板は次の画像のとおりです(筐体奥のユニバーサル基板)。

筐体背面パネルにカセットデッキ入出力用の端子を追加しました。次の画像のとおりです。

“DOUT” “DIN” “RMT” というラベルのある部分がカセットデッキ用端子です。通常はポータブルテープレコーダに接続するための 3.5mm/2.5mm 端子(ラベルよりも右側の部分)があれば十分ですが、左側に RCA 端子による入出力も追加してあります。今回はコンポ型のカセットデッキを使うのでこの RCA 端子を使って接続します。ステレオデッキの L チャンネルのみ使用します。

カセットデッキは SONY のエントリレベルモデルを中古で入手しました。今となっては 3 ヘッドの中堅機あたりでも中古価格は大差ないのでしょうが[注 1]、メカや回路がシンプルな方がメンテナンスが容易になり、またデータ信号波形に余計な色がつかなくて良いのではと考えました。当然ドルビー NR は無効にして録音します。

カセットデッキを使うのは久しぶりです。メンテを済ませてから手持ちの新旧テープを聴くなどしばらく寄り道をした後、デッキの録音レベルを調節しながらセーブ・ロードのテストを繰り返しました。ところがエラーがなかなか解消されません。

どうしたものかと書籍「マイコン手づくり塾」を読み返すと、カセットインターフェイス製作の章ではなく別のページの読者 Q&A コラムの中でトラブルシューティングとして説明されていたのが、回路図中 R5 の両端に 0.1uF 程度のスピードアップコンデンサを追加するという手法です。これが効果的だったようで、インターフェイスからデッキへの出力信号が正確なパルス幅を含む波形になりました。

それでもまだロード時にエラーが出るので、今度はデータ入力側にオシロスコープを繋いで設定を詰めていきました。最終的にまあまあ安定したと思われる設定での波形が下図のものです(CH1: デッキからのオーディオ出力信号、CH2: 復調後のデジタル信号波形)。

念のため録音後 24 時間ほどおいて再度テストしましたが同様にパスしました[注 2]。

当時オシロは高価な機器だったため、専門家以外が簡単に使えるものではありませんでした。こういったアナログ絡みの回路をオシロの助けなしに上手く動作させるには長時間のカットアンドトライが必要になったはずです。Λ-1 のカセットインターフェイス回路に LED レベルメータが組み込まれているのも、調整作業が少しでも簡単になるようにという配慮があってのことと思われます。

注:

1. eBay を覗いたらそんな事はありませんでした。3 ヘッドデッキはエントリレベルデッキに比べて少なくとも 3〜4 倍の値付けです。

2. セーブ・ロードの対象はダンプの前半 32 バイトのみなので、後半 32 バイトが変化していても問題はありません。

Λ-1/Lambda-2022 の拡張(8)パラレルインターフェイスキーボードの作成

「マイコン手づくり塾」で Λ-1 に接続して使用するキーボードは ALPS AKB-3420 というパラレルインターフェイス仕様の機種です。7 ビット ASCII コードと Strobe 信号を送出します。

ALPS AKB-3420 はとうの昔に廃番になっており、それどころか現在ではパラレルインターフェイスキーボードというカテゴリ全体が、オークションサイトで探してもたまに見かける程度という希少品種です。

さいわい昨今はキーボード自作部品やツールキットが潤沢に供給されています。自作キーボードの手法でパラレルインターフェイスキーボードを作成しようと思います。

自作キーボードと言いながら、既製品を改造して近道しておりますが…

パラレルインターフェイスキーボードの構成

自作キーボードのファームウェアといえば qmk が定番ですが、qmk ではコンピュータとのインターフェイスとしてサポートされるのは USB のみです。Λ-1 および Chick-Bug モニタで使うキーボードは PIA に接続するパラレルインターフェイスが必要になるので、qmk をそのまま使用することは残念ながら不可能です。

かといってファームウェアをいちから書くのは結構な仕事です。どうしたものかと考えながら qmk_firmware ドキュメントを眺めていたら i2c 経由でパラレルインターフェイスを追加できるかも、と思いつきました。qmk_firmware にはキーマクロ用の C 言語インターフェイスがあるので、キー押し下げイベントに応じて ASCII コードをパラレルポートへ送信する処理が追加できそうです。この方向で試してみます。

また、今回は MCU として Raspberry Pi pico を使います。そもそもパラレル出力などという風変わりなことを試すのに、その上 qmk 標準から外れた RPi pico を使うのでいろいろ予想外の困難が出るかもしれません。段階的に確かめながら作っていくことにします。

RPi pico 版 qmk_firmware のビルドとインストール

Mac Parallels VM の上に Ubuntu 20.04 を新規インストールして専用開発環境を構築します。ホスト Mac 側から VSCode Remote Development で接続して編集、ビルドを行います。

おおよそ次のステップで新しい Ubuntu VM 上に環境を作りました。

  1. Raspberry Pi pico 公式ドキュメントなどを参考に SDK とサンプルコードをセットアップします。サンプルコード pico-examples の blink プログラム(L チカ)が動くところまで確認しておきます(参考)。
  2. qmk 公式ドキュメントを参考に qmk_firmware 環境をセットアップします。
  3. qmk new-keyboard コマンドで新しいキーボードを定義します。mcu として RP2040 を指定します(参考)。

注:2022 年 11 月現在で qmk_firmware の RP2040 対応コードは master ブランチにマージ済みなので、ブランチの切り替えは不要です。

テスト用に作るキーボードはワンキーでも標準的なフルキーでもいいのですが、ともかくキーアサイン定義を RPi pico GPIO に即して書き換えます。GPIO ピン名として “GPnn” という書き方ができます。

キーボードの設定にあたって主に書き換えるのは次のファイルです(キーボード名を ‘lambda2022a’ とした場合)。

  • keyboards/lambda2022a/info.json
  • keyboards/lambda2022a/keymaps/default/keymap.c
  • keyboards/lambda2022a/config.h

この時点で簡単なキー入力テストを行います。実際につなぐのは 1 キー分のスイッチなのでブレッドボード配線で十分です。キーマトリクスの 1 交点を選んでスイッチを GPIO ピンに配線し(1 キーなのでダイオードは不要)、スイッチ押し下げのテストを行います。

使い回しの部品ばかりでリードがよじれていますが動作には問題ありません

下の画面では主に ‘c’ キー交点にスイッチを配線して入力テストを行なっています。途中でブレッドボードの GPIO 配線を差し替えて他のキーに対応する交点にスイッチを組み替えた状態でもテストしています。qmk_firmware を使うとチャタリング回避の調整が不要になるのでその点は安定して使えます(画面中 ‘c’ や ‘b’ が何度も連続して表示されるのはそれだけキーを押したからで、チャタリングではありません)。

せっかくなので C 言語のサンプルキーマクロも動かしました。特定のキーコードの押し下げイベントに対応してカスタム出力が可能であることを確認しました。

GPIO Expander パラレル出力

ここで qmk のほうはいったん置き、GPIO Expander PCF8574 モジュールを RPi pico の i2c ピンにつないでパラレルポートのテストを行います。最も単純な接続方式として PCF8574 を RPi の i2c ピンに直接接続し、電源も RPi 3V3 出力に接続します。こうすると GPIO Expander の出力は RPi pico 動作電圧と同じ 3.3V レベルになります。

デフォルトの i2c SDA/SCL ピン(pin6 と pin7)を使い、pico-examples/i2c/lcd_1602_i2c/ をお手本にして PCF8574 へ 8 ビットデータを出力しました。オシロを見ながら書き込みデータを変えてみると任意の信号を出力できそうなので、ASCII コード(AKB-3420 の仕様に従い負論理 [注 1])を b0-b6 に書いてから b7 ストローブ信号を立ち下げる動作をさせます。これを Λ-1 の PIA に入力します。

上の画像は Λ-1 モニタプログラムのキーボード入力ソースを ACIA シリアルから PIA パラレルインターフェイスキーボードに切り替えた後で文字 ’Q’ を 1.6 秒間隔で受信している状態です。

これで、RPi pico + PCF8574 から 3.3V 出力の ASCII データを送信できることがわかりました。当初は信号が減衰してデータエラーが出る可能性を考慮して I2C 回線に 3.3V – 5V レベルシフタを挟むことも検討しましたが、3.3V レベルのままで 60cm 長のフラットケーブルを介して PIA 入力に信号が届くようなのでレベルシフタは割愛します。

RPi pico + PCF8574 でパラレル出力実験

qmk C マクロでパラレル出力ドライバを書く

前節の実験は pico-examples のサンプルコードを流用して書いたものですが、これを qmk 環境に移植します。

前述の qmk 設定に加え i2c 関連機能を有効にするために、次の各ファイルを変更します。qmk 公式ドキュメントの「Raspberry Pi RP2040」および「I2C Master Driver」のページを参考にしました。

  • keyboards/lambda2022a/halconf.h
  • keyboards/lambda2022a/mcuconf.h
  • keyboards/lambda2022a/rules.mk

qmk_firmware には i2c 制御のライブラリが用意されているはずですが、RP2040 ターゲットのビルドを行ったところライブラリのリンクや i2c の初期化がなかなかうまく行きません。ソースツリーの keyboards/ 以下にある他のキーボード用の i2c コードも参照しましたが、RP2040+OLED の組み合わせによる作例ばかりで i2c バス直接制御の使用例はないようです。

この i2c バス直接制御のための設定方法がわからず数日間悩みましたが、結局 rules.mk ファイルに次の 1 行を追加することで RP2040 ビルドでの i2c 関連のリンク、初期化ともほぼ自動的に行われるようです。

OLED_ENABLE = yes

前節と同じブレッドボード上のワンキー構成キーボードを使って、’q’ キーを押すと Λ-1 のパラレルキーボードインターフェイスに ASCII コード ‘Q’ が送られることを確認しました。同時に USB ポートへも ‘q’ キーの押し下げイベントが送信されています。

最後に、qmk のキーコード(KC_xx)とモディファイアキー状態 get_mods() から ASCII コードへの変換を行います。AKB-3420 相当のパラレル出力データとして必要なのは 7 ビット ASCII コードなのでチェックすべきキーコードの数も限られ、比較的シンプルな変換処理になります。

以上でコントローラの設定とプログラムはあらかたできました。次に物理的なキーボードの選定について検討します。

キーレイアウトと機種の選定

Λ-1 で使用された ALPS AKB-3420 の写真を見ると全キーが長方形に収まっておりなかなか端正なデザインです。今で言う 68 キー配列に近いものがあります。そこで既存の 68 キー配列キーボードをベースにしてパラレルインターフェイスキーボードを作ろうと思います。

(AKB-3420 画像出典:Deskthority WIKI)

最初は基板を起こして AKB-3420 のレイアウトを再現しようと思ったのですが、現代のキーキャップで構成するには若干無理があるため断念しました。パラメトリックキーキャップ設計ツールに習熟すればあるいは可能かもしれません。

当面は一般的な 68 キー配列の市販キーボードのケースや基板を流用します。AKB-3420 は ISO 配列ですが、個人的な好みにより ANSI 配列に変更します。AKB-3420 の最大の特徴は右側 2 列のリレジェンダブルキーキャップなのでここはなるべく再現したいところですが、現代の 68 キー配列ではこの部分は 1 列しかありません。ただ、Λ-1 ではこのエリアを多用しないので 1 列のままでもしのげるのではないかと思います(ATN キー、LF キー、ESC キーが最低限必要。LF、ESC はスペースバー横に配置しても可。ATN キーはマトリクスではなく直接配線が必要)。

68 キー配列ではカーソルキーが右端列の下端にはみ出しますがこれはそのまま残します。といっても Λ-1 / Chick-Bug ではカーソルキーはほぼ無用ですので、将来の拡張用といった位置付けになります。

既製品キーボードから流用するのはケース、スイッチプレートとマトリクス配線です。もともと基板に実装されていた MCU などは配線から除外します。今回 MCU として使用する RPi pico、PCF8574 などを足し合わせると既製品ケースには収まりきらないようなので当面はマトリクス配線をケース外に引っ張り出して結線します。いずれにしてもケースは再設計が必要なようです。

組み立てとテスト

既製品キーボードのマトリクスを調べたところ 15×5 でした。RPi pico ではマトリクスに GPIO ピンを 20 個割り当ててもまだ 6 個余るので、そこへ i2c を結線します。キーボード右上端のキーはパターンカットしてマトリクスから除外し、PIA の CA1(NMI 入力) に接続してプルアップ抵抗も付けます。これが Chick-Bug の Atn キーとして機能します。

この既製品キーボードをベースにしたテスト構成では、RPi pico と PCF8574 はブレッドボードに組んだまま使用しています。改造したキーボード基板から多数の線が出ていますが、この状態で実運用予定の構成と同じ配線になっています。

以前に作成したシリアルコンソールと独立して、パラレルインターフェイスキーボードと K68-VDG によるコンソールが動くようになりました。

***

以上で、パラレルインターフェイス方式の ASCII 出力キーボードを作成しました。ところで、よく考えたらこれは Apple II Plus にそのままつながりそうです。今後折を見て、キーレイアウトをカスタマイズしてテストしようと思います。

  1. AKB-3420 単体での出力は正論理ですが、Λ-1 では AKB-3420 にバッファ回路が追加されその部分でインバータを使用しているため Λ-1 への入力信号は負論理となります。

Λ-1/Lambda-2022 の拡張(7)K68-VDG の接続

Λ-1 システムの目玉機能のひとつは MC6847 VDG を使用したディスプレイインターフェイスです。なにしろカラーモニタディスプレイは当時の市販マイコン(今で言うパソコン)のアイデンティティで、標準的な自作ボードマイコンとは一線を画する機能でした。これさえあればビデオゲームが作れる!まあそう簡単に行くものではなかったのですが、表現力という点でカラーディスプレイは飛躍的な差が付くデバイスでした。

そんな MC6847 VDG ですが Λ-1 でサポートされるのは 32×16 テキストモードだけです。このモードでは VRAM は 512 バイトしか必要としませんし、同じメモリ量で使えるセミグラフィックモードでは 64×32 のまがりなりにもカラーグラフィックスが出力できたのです。グラフィックスといってもテキストモードに間借りして 2×2 ボックスパターンキャラクタを表示させるものですが、8 色カラー出力が可能でした。

当時はメモリのコスト面を考慮するとこのような低解像度の画面設定がベストだったわけですが、現在では大容量 SRAM がたやすく手に入ります。MC6847 がサポートする 8KB VRAM を最大限に使いたいところです。

ここまで考えると Kuni-Net 様設計の K68-VDG が選択肢に入ってきます。K68-VDG は今回作っている Λ-1 マシン(Lambda-2022)で採用した SBC-Bus に対応していますし、MC6847 の各種モードをサポートして VRAM は 8KB x 4 プレーンが利用できます。またビデオ出力が高画質であることも K68-VDG の利点です。

K68-VDG を Λ-1(Lambda-2022)で使うには VRAM アドレスと VDG 設定レジスタ(LS573 8 ビットラッチ)のアドレスを K68-VDG のオリジナル設計から変更する必要があります。

デバイス旧アドレス新アドレス
VRAM$A000-$BFFF$C000-$DFFF
VDG CTL$81xx$F048

このアドレスに沿って動作するためには K68-VDG のデコード回路に手を入れる必要があります。次のように設定します(元回路は K68-VDG リポジトリのこちらを参照)。

  • VRAM アドレス変更:SBC Bus ピン 35 に $C000-$DFFF デコード信号(VRAM#)が出るようにする(I/O 基板で実装済み)
  • VDG CTL アドレス変更:SBC Bus ピン 37 に VRAMCTL# が出るようにする(I/O 基板で実装済み)。また、K68-VDG の LS02(U5)のピン5, 6 と A8 の間の配線をカットし、代わりに A3 を U5 ピン 5, 6 に接続する
  • K68-VDG のアドレスデコーダ(U10、LS138)は実装しない

K68-VDG 基板上の実作業としては U3 のピン 5, 6 部分のみパターンカットとジャンパが必要になります(トレースの都合上 U9 へ A8 を再配線する必要があります)。それから、現在 NC となっている MC6847 の FS#(ピン 37)を I/O 基板上の PIA0 PA7に接続します。これはバスを介さずに行います。

このように若干手を入れる必要がありますが、MC6847 の VRAM をフル実装した K68-VDG の機能が簡単に利用できるのは大きな利点です。これも SBC-Bus を基盤として SBC ユーザの皆様の設計が標準化されているおかげです。

Chick-Bug の再改造

これでハードウェア的には K68-VDG を Lambda-2022 に接続できましたが、Chick-Bug モニタプログラムは現状ではシリアルコンソール専用に改造されています。これを VDG/シリアル両対応に再改造します。方針としては次のようになります。

  1. 以前シリアル用に書き換えたルーチン(disp1c, kbread, etc.)を一旦オリジナルコードに戻す。
  2. シリアル対応版ルーチンを別名(disp1csr、ineee)に変えて移動する。
  3. Chick-Bug ワークエリアに入出力ルーチンスイッチ変数 eeesw を設ける。bit7 … シリアル出力オンオフ、bit6 … VDG 出力オンオフ、bit0 … シリアル入力 (1) / パラレルキーボード入力(0) 切り替え、という設定にする。デフォルトは 0xc1
  4. disp1c ルーチンで eeesw bit7, bit6 をみて、それに応じて出力ルーチンの呼び出しをオンオフする
  5. kbread ルーチンで eeesw bit0 をみて、それに応じて入力ルーチンを切り替える

下の画像に示すように、シリアルコンソールと並行して VDG テキスト画面が表示されました。FS# を監視して VRAM への書き込みを同期することにより、画面のちらつきを抑えることが可能です。ただし FS# 同期、シリアルポートとの並行出力、ソフトウェアスクロールなど処理が増えるため描画速度は低下します。必要に応じて eeesw の設定を変えれば出力先を限定してある程度高速化できます。

Lambda-2022 の実装

現時点で Lambda-2022 内部の実装状況は次の画像のとおりです。

ついに SBC-Bus スロットがいっぱいになってしまいました。画像奥(筐体前面側)から

  1. DMA カード
  2. CPU/SRAM カード
  3. VDG カード
  4. I/O カード

が装着されています。フル装着時の負荷に備えて、このケースにはスイッチング電源を装備してあります。また SBC-Bus の +5V 供給ラインだけでは心もとないのでフロントパネルと I/O 端子には別のケーブルで電源を供給しています。筐体裏側にはビデオコネクタパネルおよびシリアルコネクタパネルを追加してあります。

Λ-1/Lambda-2022 の拡張(6)Chick-Bug 拡張

Chick-Bug の標準機能がだいたい動くようになりました(カセットテープのロード/セーブは未検証)。予想通りフロントパネルの DMA スイッチ類はほとんど使わなくなってきましたがそこは気にせず、Chick-Bug へ次の機能を追加します。

  • S19 読み込み
  • メモリダンプ
  • MB8861 命令の書き換え

S19 ストリームの読み込み

SBC68 シリーズを使ってわかったことですが、シリアルコンソールが近代的なコンピュータに接続されている場合、ユーザプログラムをロードするには S19 ファイルの内容をコンソール画面にコピペする方法が最も手軽です。この機能、つまり MikBug の L コマンドを Chick-Bug に追加します。

基本的なコードは SBC68 版 MikBug とほぼ同じです。コマンド名には ‘O’ を割り当てます(’L’ はカセットテープロードコマンドですでに使用されているため)。ロードが終わったら待機モードに戻ります(他の Chick-Bug コマンドと同じ終わり方)。

ちなみに元祖 MikBug の L コマンドはテレタイプ端末の紙テープリーダを前提としていたようです。’L’ コマンドをテレタイプ端末のキーボードから入力した後、入力ラインをテープリーダに切り替えてテープを走らせ、内容を読み込みます。すると S19 データストリームが 110 baud でテープリーダからコンピュータへ送られるという仕組みです。一度でいいのでこの紙テープ読み込みを SBC シリーズや Λ-1 でやってみたいですね。

メモリダンプ

Chick-Bug 標準機能の M コマンドは 1 バイトずつの表示・確認となり操作が若干煩雑です。ダンププログラムは 64 バイト単位で表示するので操作が楽になります。「マイコン手づくり塾」の Chick-Bug 開発編にユーザプログラムとして掲載されているものを Chick-Bug 自体に組み込んでしまいます。コマンド名は ‘D’ とします。

***

これらのコマンドを追加することでモニタ内各ルーチンのエントリアドレスが変わってしまいます。今までに作成した、モニタサービスルーチンを使ったユーザプログラムは変更が必要になりますが、そもそも Lambda-2022 ではオリジナル Λ-1 から ROM アドレス自体が変わっているので今回の変更の影響は相対的に小さいものです。

MB8870 命令の書き換え

「マイコン手づくり塾」ではモトローラ MC6802 互換の各種チップを総合的に比較検討した結果、富士通 MB8870 が採用されました。MB8870 の最大の特徴は独自命令が追加されていることです。富士通製 MPU では MC6800 互換の MB8861 の頃から同じ独自命令群が採用されていました。Chick-Bug プログラムの中でもこれらの独自命令が使用されているのですが使用箇所はそれほど多くなく、多少の工夫で置き換えられます。MB8870 と MC6802 はピン互換ですから、MB8870 独自命令がなくなるよう書き換えてしまえば MC6802 チップを Lambda-2022 に装着できます。

以下、MB8870 の独自命令と使用箇所をそれぞれについて検討します。

ADX 命令

6 箇所使われており、そのうち 4 箇所は ADX #$03 という固定値加算で、加算値も小さいので inx を 3 行並べるだけで置き換えられます。

もう一つは ADX #$1F となっています。inx を 31 個も並べるというのも不格好でどうしたものかと思っていたところ、前後をよく読むとこの行での X レジスタの値は不変です。次のように書き換えられます。

変更前:
            ldx #ccrm
            stx xopnd1
            adx #$1f
            stx xopnd2


変更後:
            ldx #ccrm
            stx xopnd1
            ldx #ccrm+$1f
            stx xopnd2

最後の一つは変数へ加算しているため、A/B アキュムレータを使った 2 バイト加算に展開せざるを得ません。前後に A/B アキュムレータの退避・復帰を含むためステップ数が増えます。逆に言うと、これが MB8870 ADX 命令の真価を発揮するケースになります。

変更前:
lf          ldx cpoint
            adx #$20
            stx cpoint

変更後:
lf          psha
            pshb
            ldaa cpoint
            ldab cpoint+1
            addb #$20
            adca #0
            staa cpoint
            stab cpoint+1
            pulb
            pula

NIM、OIM 命令

それぞれ一箇所しか使われていません。どちらもカセットインターフェイス出力処理の中です。

bitout   psha
            pshb
            ldx #pdrb1
nim1    nim $fe00     [8]
            decb             [2]
            bne nim1      [4]
            pulb
oim1    oim $0100    [8]
            decb             [2]
            bne oim1      [4]
            pula
            rts

ここでは PIA の DRB レジスタの PB0(カセットデータ出力)のオフとオンを行い、オーディオ出力を一瞬トグルする効果を求めています。周期は bitout ルーチン呼び出し元で指定する AccB の値で決まります。次のように設定されています。

soutlp  lsra
            bcs markot
            ldab #$64
            bsr bitout
            bra nxtbit
markot ldab #$32
            bsr bitout
nxtbit   dec bitctr
            bne soutlp

つまり出力 ‘1’ の半周期分のループは $32 カウント(50)、出力 ‘0’ の半周期分のループは $64 カウント(100)です。具体的な半周期長はループ処理の命令サイクル数で決まりますが、命令サイクル計算に必要なデータは MB8861 命令シートに書いてあります(「マイコン手づくり塾」に掲載されています)。簡単のためループ外の命令サイクルを除外して計算すると出力 ‘1’ の半周期は 14us x $32 = 700us、出力 ’0’ の半周期は 14us x $64 = 1400us となります。

同等の処理を MC6800 命令で再現するには次のように nim、oim を書き換えます。

bitout   psha
            pshb
            ldx #pdrb1
            ldaa 0,X
            anda #$fe
            staa 0,X
nim1    nop               [2]
            nop               [2]
            nop               [2]
            nop               [2]
            decb             [2]
            bne nim1      [4]
            ldaa 0,X
            oraa #$01
            staa 0,X
            pulb
oim1    nop               [2]
            nop               [2]
            nop               [2]
            nop               [2]
            decb             [2]
            bne oim1      [4]
            pula
            rts

nim ないし oim 命令 1 個の代わりに nop を 4 個挿入することでループ内の合計サイクル数が一致するので、タイミングも同じになります。

以上で MB8870 独自命令使用部分をすべて書き換えることができました。一箇所を除いていずれも独自命令を使用する必然性があまりない処理であったように思えます。特にカセットインターフェイス出力の部分は nim/oim を使用するのであればそもそも AccA を退避する必要はありません。書き換え後のように PIA レジスタ操作に AccA を使うのであれば事前退避が必要になるので、ここはもともと MC6802 互換で書かれていたという可能性も考えられます。

注:

現時点ではまだカセットインターフェイス回路を作っておらず、PIA ポートが未接続のまま放置されています。せっかくなので SAVE コマンド出力信号を実測しました。最初に MB8870 拡張命令を使った処理の場合の出力波形です(D0 チャネル)。

たしかにマーク半周期 ~720us、スペース半周期 ~1410us となっています。

次が MC6802 命令で書き換えた後の SAVE 出力波形です。

こちらもマーク半周期 ~700us、スペース半周期 ~1490us とおよそ一致します。どうもデューティ比が正確に 50% ではないようで、ループ外の命令サイクルの影響だと思われます。

Λ-1/Lambda-2022 の拡張(5)Chick-Bug 移植

オリジナル Chick-Bug は Λ-1 に接続されたパラレルインターフェイスのキーボードと VDG ディスプレイをコンソールとして使用しますが、今回作成する Lambda-2022 システムではコンソールとして ACIA シリアル回線を追加しています。またメモリマップも変更がありますので、これらに対応するため Chick-Bug を次のように変更します。

ワークエリア:オリジナル Chick-Bug ではスタックを含むワークエリアが $F700-$F7FF に設定されていました。他の用途と干渉しない RAM 領域 $A600-$A6FF に変更します。

PIA アドレス:オリジナル Chick-Bug の PIA アドレス $EE00..$EE03 を今回作成した I/O ボードの PIA0 アドレス $F008..$F00B に変更します。

VDG アドレス:オリジナル Chick-Bug の VRAM アドレス $F000-$F1FF を $C000-$C1FF に変更します。またシステム初期化時に VDG コントロールレジスタ($F048)に適切な値を設定します。

ACIA 初期化:SBC68 版 MikBug 同様に ACIA を初期化します。システムリセットルーチン restp 内で ACIA 初期化ルーチンを呼び出します。

PIA、ACIA の接続状況は次のようになります。

Desc.DEVI/O RegisterOrig Addr.New Addr.
K/b asciiPIA0PA0-6pdra1$ee00:b0-6$f008
6847 vsyncPIA0PA7pdra1$ee00:bit7$f008
k/b strobePIA0CA1pcra1$ee01:bit7$f009
k/b ATN NMIPIA0CA2pcra1$ee01:bit6$f009
tape mtrPIA0PB1pdrb1$ee02:bit1$f00A
tape outPIA0PB0pdrb1$ee02:bit0$f00A
tape inPIA0PB7pdrb1$ee02:bit7$f00A
tape inPIA0CB1pcrb1$ee03:bit7$f00B
SerialACIACSaciacs$f028
SerialACIADAaciada$f029

Chick-Bug はプロンプト呼び出しのためにハードウェア割り込みスイッチを使いますが、これは元設計通り PIA0 CA2 へ接続します。当面は、前回 PIA のテストに使用したブレッドボード回路をそのまま流用します。

シリアルコンソール対応

冒頭に述べたように、オリジナル Λ-1 のコンソールに加えて ACIA シリアルコンソールをサポートしようと思います。将来的には VDG/パラレルキーボードとシリアル入出力を切り替えるようにしますが、当面はシリアル入出力のみ対応するコードを書きます。次の要領で 機能を変更します。

入力:オリジナル Chick-Bug では PIA0 PA ポートと CA1 に接続されたパラレルインターフェイスキーボードから入力を読み取っていました。これをシリアル入力に置き替えます。

  1. kbread ルーチンの処理をシリアル入力処理に置き換える。
  2. シリアル入力処理は SBC シリーズ版 MicBug の ineee ルーチンを参考にして記述する。

出力:オリジナル Chick-Bug では文字出力は VDG のテキスト画面へ送られますが、シリアルコンソールに同等の内容を出力できるようにします。VDG への文字出力はおもに disp1c で行われますが、画面クリアやスクロールなどの処理で VDG 直接操作があり、これらすべてをシリアルコンソール対応処理に変更します。次のように改造します。

  1. Chick-bug の中で VDG VRAM 操作に関連するルーチン(cpoint、vramt1 を直接使用する処理)を特定する。
  2. 該当する下記のルーチンをシリアル出力(outeee)対応に書き換える。
clear1, chmark, clrhm1, lf, crlf, bs, disp1c, scrolu

初期化の部分を除くと Chick-Bug モニタの他の部分から表示のために呼び出されるのは disp1c だけのようです。将来的に VDG/シリアル出力を切り替える場合は、disp1c 内で切り替え判定をすれば十分です。

シリアルコンソールの処理では HOME、CLEAR などのエスケープコードを使用します。

改変後の Chick-Bug ソース内のアドレス配置は次のとおりです。

$a600-$a66b   :システムワークエリア
$a6ff                :スタックトップ
$f080-$fa74      : Chick-Bug コード

***

以上の要領で移植作業を進めます。Chick-Bug はもともと Λ-1 ハードウェア用に書かれたモニタプログラムなのでこれを改変することを「移植」と言うのも少し変ですが、ともかく上記の方針に沿って書き換えます。

Chick-Bug 動作確認

書き換えた Chick-Bug はシリアルコンソール上での対話ができるようになっています。各コマンドの動作画面は次のとおりです。

‘M’ コマンドはメモリ内容の表示と書き換えです。

’G’ はユーザプログラム実行、’B’ はブレークポイントの設定/確認/解除です。

カセットテープインターフェイスコマンドの確認

カセットテープのロード/セーブ機能の確認はカセットレコーダインターフェイス回路を作ってから行います。

VDG 上の動作画面

本来の出力である VDG 画面はまだ確認できません。今後 VDG 回路を追加したときに確認します。

なお今回使用する予定の K68-VDG では 6847 の反転文字と通常文字を区別しているので、Chick-Bug が印字する通常の ASCII 文字($20-$5F)は後半のみ反転します。VDG 出力時に表示コードを適宜変換する必要があります。

今後の計画

全部できるかどうかわからない予定を再度並べてみます。

  • K68-VDG の接続
  • カセットテープレコーダ回路の作成とテスト
  • パラレルインターフェイスキーボードの作成

Λ-1/Lambda-2022 の拡張(4)新 CPU カードと I/O カードの製作・テスト

注文の基板が到着しました。さっそく 2 枚のカードを製作します。

新 CPU カードの製作とテスト

旧 CPU カードと同じ要領で部品を組み付けます(今回も配線ミスがありジャンパが必要になりました)。最初に CPU カードのみテストします。まず SRAMSEL ピンをプルアップして CPU カード単体で SRAM を常時有効にします。その後、旧 CPU カードと入れ替える形でバススロットに装着します。この時点で Lambda-2022 システムには 64KB フル RAM を実装した新 CPU カードと DMA カードが接続されています。

$0000-$7FFF の 32KB SRAM をテストするために次のプログラムをフロントパネルから入力、実行します。

***
* memtest $0000-$7fff
***
*
* set val to write 


val     equ $55   ; test val
erradr  equ $8100  ; address where test failed
mstart  equ $0000  ; mem test start addr
mend    equ $8000  ; mem test end addr + 1
*
        org mend
start   ldx #mstart-1
        stx erradr  ; if (erradr)=mstart-1, test succeeded; otherwize test failed
        inx
        ldaa #val
loop    staa 0,X
        cmpa 0,X
        beq ok
        stx erradr
        bra endl  ; test failed, end prog
ok      inx
        cpx #mend
        bne loop
endl    bra endl
*
        end

val を $55, $aa, $00, $ff の 4 種に変えてテストします。

$8000-$FFFF の 32KB SRAM のテストプログラムもほぼ同様で、テスト対象領域とテストプログラム領域、およびワークエリアのアドレス値を変更します。

val を $5a, $a5, $0f, $f0f の 4 種に変えてテストします。

動作上ちょっと面白い点として、2 つ目のテストプログラム($8000-$FFFF の SRAM メモリテスト)はリセットベクタ $FFFE-$FFFF まで書き換えてしまいます。ROM のない初期構成の Λ-1 ではいったんプログラムが開始してしまえばリセットベクタは不要になるのでこれでも問題なく動作します。ちなみにここまで Λ-1 用に書いたどのプログラムもスタックポインタの初期化を行っていません。割り込み処理やサブルーチン呼び出しがない場合はスタックポインタの設定も不要です。

メモリテストはやりだすときりがありませんが、以上で 64KB 分の SRAM テスト完了ということにします。SRAMSEL のプルアップを取り除いて CPU カードを再装着します。

I/O カードの製作

I/O カードを製作するには GAL20V8B のプログラミングが必要になります。といっても必要なのは静的なデコーダロジックですから、回路図に書いた論理式をソースファイル(*.PLD)に書き写すだけです。

GAL のデザインツール WINCUPL を使用するには比較的古い OS が必要になります。このために温存してある Win7 VM を引っ張り出して WINCUPL を起動しました。はじめは JED ファイルが生成されずまごつきましたが、どうも PLD ファイルの Device フィールドを無視して WINCUPL のメニューからデバイスを選んでやると正しくコンパイルされるようです。しばらく使っていなかったので手順を忘れていました[1] [2]。JED ファイルを生成したら、TL866 ROM ライタを使って EPROM と同じ要領でプログラムします。

PIC のプログラムも必要です。SBC シリーズ用にクロック生成のための HEX ファイルが用意されているので、これを書き込みます。今回は 38400bps 設定にしました。

I/O + ROM カード(PIA は未装着)

I/O カードも基板設計時の回路に諸々不具合がありパターンカットとジャンパ線で修正しました。修正点は以下のとおりです。

  • 28C64 の WE# を NC から +5V プルアップに変更
  • PIC クロック出力をピン 2 からピン 5 に変更
  • PIA、ACIA の R/W# ピン接続先をバス WR# からバス R/W# に変更

最後の修正はもしかしたら不要だったかもしれません。

新システムハードウェアのテスト

以上で拡張 Λ-1 システムのハードウェア基本部分ができましたが、ROM にはまだなんのプログラムも書き込まれていません。数回前の投稿でソースを準備した Chick-Bug の移植を始めてもいいのですが、まずは MikBug を書き込んでみます。SBC6800 版の MikBug ソース内の ACIA、ワークエリア、コード開始位置のアドレス定義を書き換えて再アセンブルすると Λ-1 で動きます。冒頭付近数行のアドレス値を書き換えるだけです。

*	ADDRESS
ACIACS	EQU	$f028
ACIADA	EQU	$f029
VAR	EQU	  $a600
*
*	OPT	MEMORY
	ORG	$f100

これらのアドレス値は下記のメモリマップにもとづいています。G コマンドの設定アドレスは $a648/$a649 となります。

MikBug の L コマンドを使って S19 データを流し込み、Hello World プログラムを実行しました。シリアルコンソールと L コマンドがこんなに有り難く感じたことはありません。フロントパネルスイッチをパチパチと操作して 1 バイトずつ入力する作業に比べると数段楽です。まあ、そのパチパチ操作のために Λ-1 を作ったのですから本末転倒する感想ではありますが、シリアルコンソールとモニタ ROM が動いた時点でフロントパネル DMA の必要性が失われてしまうのは事実です。

MikBug のコンソールが動いたので ACIA はテスト済みとみなします。次に PIA について 2 つのテストを行います。

PA / PB ポート:L チカ

PIA0 に MC6821 PIA をセットします。PIA0 のレジスタにはアドレス $f008-$f00b でアクセスできますので、全ポートを出力に設定した上で適当なループタイマを挟んで PortA と PortB の両方に $00 と $ff を交互に書き込みます。20 回繰り返したらプログラムを終了します。

「L チカ」と称する以上は適当なドライブ回路を PIA ポートに接続して LED を点滅させるのが筋ですが、面倒なので PIA ポート出力をロジアナで直接測定します。下の画面では D0 が PA0、D4 が PB0 に接続されており残りのチャネルは未接続です。

想定通り PA/PB 出力が 20 回点滅しています。(L チカプログラムはこちら

CA1 ポート:NMI 割り込み

この I/O ボードの PIA0/PIA1 の IRQA ピン(38)は 6802 NMI 割り込み(プルアップ済み)に接続されています。CA レジスタの以下のビットを書き込み・読み出しすることで IRQA を通じて割り込みを発生できます。

bit0 = 1:CA1 による割り込みを有効にします。割り込み信号に反応して IRQA ピンが立ち下がります。
bit1 = 0:CA1 割り込み信号を立ち下がりタイプに設定します。
bit7:読み出し値が 1 の場合、CA1 入力による割り込みが発生しています。PA レジスタを読み出すと値はクリアされます。

CA1 ピンに次の割り込みボタンを付けます。

MikBug の NMI 割り込みハンドラは NIO が示すアドレスへジャンプします。NIO は Lambda-2022 版 MikBug の場合 $a606-$a607 です。

画面下端近くのメッセージ行 “INTERRUPT VIA PIA0 CA” が割り込みハンドラによるものです。(割り込みハンドラプログラムのソースはこちら

***

これらのテストで I/O ハードウェアは問題なしとみなすことにします。次回は Chick-Bug の移植に移ります。

注:

  1. スクリーンショットの PLD コードにあるように Device: gal20v8a; とすると動くようです。
  2. この GAL 書き込みを終えてから code-cupl という VSCode 拡張機能を見つけました。code-cupl の ReadMe によるとコマンドライン用 cupl.exe は Windows 10 上でも動作するようです。ただし ReadMe にかかれている比較的複雑なコマンドラインオプションやライブラリファイルが必須で、さらに exe ファイルの互換モードを設定する必要もあります。

Λ-1/Lambda-2022 の拡張(3)I/O カードの設計

この I/O カードは新規設計となります。次の I/O デバイスおよびメモリを接続します。

  • PIA x 2
  • ACIA x 1
  • 4KB ROM
  • VRAM (デコードのみ)
  • VRAM コントロールレジスタ(デコードのみ)

ACIA は PC とのシリアル通信に使用します。PIA は 1 つに付き PA/PB 2 バイトのポートがあるので 2 個の PIA で合計 4 バイト分 = 32 ポートが使えます。これ以外に割り込み可能ポート CA1/2、CB1/2 が 2 セットで合計 8 ポートあります。PIA には次のようなデバイスを接続できます(全部作成するとは限りません)。かっこ内は(Px ポート数 + Cx ポート数)です。

  • フルキーボード(7+2)
  • カセットインターフェイス(3 + 1)
  • VDG 垂直同期割り込み(0 + 1)
  • 16 進キー/LED コンソール(9 + 0)

I/O カードのもう一つの重要な機能はアドレスデコード回路で、カード上のデバイスに加えて SRAM、VRAM 関連のデコードも行います。詳細を検討するために、まずメモリマップを再掲します。

次のアドレスをデコードする必要があります。

デバイス開始アドレス終了アドレス使用バイト数
VRAM$C000$DFFF8192
PIA0$F008$F00B4 + 4 ghosts
PIA1$F010$F0134 + 4 ghosts
ACIA$F028$F0292 + 6 ghosts
VDGCTL$F048$F0481 + 7 ghosts
ROM$f080$FFFF3968

細かい変更として、前稿掲載のマップに比べて PIA、ACIA 等 I/O デバイスのアドレスが若干移動しています。これは PIA 等のチップで使用できる CS ピンの組み合わせが限定されるためです。変更はあるものの A3-A15 は重複がないようにデコードされるので、I/O 領域内に 8 バイトブロック単位で適切に割り当てられます。

上の表に示した I/O、ROM、VRAM 領域をアクセスしている間は、SRAM イネーブルを無効にします。このイネーブル信号が SRAMSEL で、バス 33 ピンへ出します。同様にして VRAM 領域アクセス時は VRAM#(バス 35 ピン)、VRAM コントロールレジスタアクセス時は VRAMCTL#(バス 37 ピン)をアサートするようにします。IO デバイス(PIA0、PIA1、ACIA)についても同様のイネーブル信号を生成します。これらのアドレスデコードは VMA 有効時のみイネーブルとなるようにします。

多数のアドレス線とイネーブル信号が交錯するので、GAL デバイスを使って一括デコードすることにしました。次の回路図になります。

このカードでは 600mil 幅の IC を多数使う上、I/O ピンヘッダも多いので 95mm x 75mm 基板にギリギリ収まるサイズでした。もしかしたら基板サイズを多少延長したほうが良かったかもしれません(95mm x 95mm など)。

ここまでで新 CPU カードと I/O カードを設計したので、PCB 製造を発注します。基板が到着したら作業を再開します。