MC6802シングルボードコンピューター その3 ~TV対応と電大版BASIC~

MC6802

MC6802シングルボードコンピューターに以前作成したK68-VDG(MC6847搭載)ビデオボードが接続できましたので、せっかくだから? Universal MonitorをTV(というかVRAM?)対応してみたり、その上で動くTiny BASICもVRAM対応してTV(RCAコンポジット入力モニター)に映してみたいと思います。

機械語モニターのVRAM対応の前に

Universal Monitor(機械語モニター)のVRAM対応の前に、K68-VDGビデオボードのサンプルプログラムがK68-SBC(MC6802シングルボードコンピュータ)+K68-VDGビデオボードで ちゃんと動くか試してみます。

サンプルプログラムは数年前に作りまして、以下のgithubのフォルダに「全キャラクタ表示」と「エコーバックプログラム」があります。

K68-VDG/sample at master · kuninet/K68-VDG
Contribute to kuninet/K68-VDG development by creating an account on GitHub.

全キャラクタ表示サンプル(asciilist-6800)

全キャラクタ表示サンプルは、VRAMのアドレスの先頭から$00~$FFのキャラクタを並べるだけのでもプログラムです。

上図のように、割と表示がきれいなので好きなのです。

VRAM_TOP        EQU     $A000
VRAM_END        EQU     $A200

VRAMアドレスが上記のVRAM_TOPとかVRAM_ENDに定義されていますので、$A000をVRAMにする場合は変更が必要です。
またコンパイルしなおしのために Makefileもつけてますので、The Macroassembler ASとGNU makeが動く環境で makeして再アセンブリしてください。インテルHexファイルが作成されます。
出来上がってIntelHexファイルを Universal MonitorのLコマンドでロードして G0100で $100番地から実行すると上記のようなキャラクタ一覧が表示できます。

エコーバックプログラム(echoback-6800)

エコーバックプログラムは、シリアル入力でキーボードから入力したデータをK68-VDGビデオボード経由でRCAコンポジットモニター画面へ表示するものです。

プログラムの実際の動きは、シリアル通信で届いた1バイトキャラクタをいい感じでVRAMに配置していくもので、CR($0D)入力で改行したり、最下行まで行ったら自動スクロールしたりという仕込みをしてあったはず。このロジックを応用するとUniversal MonitorをK68-VDG経由でTV対応(w にできる思います。

以前も書きましたが、K68-VDGボードに載っているMC6847というビデオコントローラにはキャラクタジェネレータが内蔵されていまして、VRAMに文字コードをセットすると英字や数字を表示してくれます。上記のように、プログラムを起動してTeraTermのようなシリアル端末から文字を入力すると画面に文字が出力されます。ちなみに、緑背景になってるのがRCAコンポジットモニター替わりのUSBキャプチャケーブル経由の画面です。

ただしデータシートを見ると分かりますが、上記のように6bit x 2面の独特なコード配置となっているため ひと工夫必要です。また英小文字は出ませんので、そこもちょっと一工夫…

;
; キー入力エコー
;
ECHO:
        JSR     CONIN
        CMPA    #ESC
        BEQ     ECHO_END
        JSR     CONOUT
;
; 内部CGにあわせて キャラクターコード変換
;
; 英小文字は大文字変換
        CMPA    #$60
        BGE     SUB20
; 英大文字はそのまま出力
        CMPA    #$40
        BGE     ECHO1
; 特殊記号はリバースキャラへ変更
        CMPA    #$20
        BGE     ADD40
        BRA     ECHO1
SUB20:
        SUBA    #$20
        BRA     ECHO1
ADD40:
        ADDA    #$40
        BRA     ECHO1
ECHO1:
        JSR     VRAM_OUT
        BRA     ECHO

エコーバックプログラムで、届いた文字コードをいろいろと変換してましたが、コメントがなかったためすでに私も何をやったか忘れてました。今後また忘れないようにコメントを追加しておきました。

Universal MonitorのVRAM対応

エコーバックプログラムの文字出力の部分をいい感じで移植すると、Universal Monitorの文字出力をRCAコンポジットモニターに出力できるはずです。

Universal Monitorのコンソールドライバ

Universal Monitorは、いろいろな環境に合わせられるように「コンソールドライバ」が定義できるようになってます。

コンソールドライバ | Electrelic
新たなデバイスを使ってコンソールを接続するためには以下の手順でドライバを作成します。 dev/dev_YYYY.asmを作成 これがドライバ本体です。使用しているアセンブラASには分割アセンブル・リンクの機能が無いのでモニタ本体にINCLU...

SBC6800コンソールドライバからの変更点

SBC6800用シリアルドライバがUniversal Monitorについてきますので、そちらにVRAM対応ルーチンを仕込んでいきたいと思います。コンソールドライバに作りこみするルーチンは以下の通りです。

ルーチン説明今回の対応点
INITデバイス等初期化シリアルLSI MC6850の初期化はそのままにして、VRAMデータのクリアなどを実施します。
CONIN1文字入力★ここは変更ありません。
CONOUT1文字出力シリアルへの出力の後、VRAMへ文字データをセットします。
必要ならスクロール処理も実施します。

変更したソースは以下の通りです
★ちょっと長いです

;;;
;;;	MC6850 (ACIA) & K68-VDG Console Driver
;;; 

INIT:
	LDAA    #$FF
INIT_LOOP1:
	LDAB    #$FF
INIT_LOOP2:
	DECB
	BNE INIT_LOOP2
	DECA
	BNE INIT_LOOP1

	LDAA	#$03		; Master reset
	STAA	ACIAC
	NOP
	NOP
	LDAA	#ACCR_V
	STAA	ACIAC

;
; VRAM関係初期化
;
VRAM_SCREND     EQU     VRAM_END-$20
;
SPC             EQU     $60
ESC             EQU     $1B
;CR              EQU     $0D
CURSOR          EQU     $CF
;BS              EQU     $08
;
CHAR_A          EQU     $40
CHAR_UNS        EQU     $5F
;
CHAR_S_A        EQU     $60
CHAR_END        EQU     $7F
;
VDG_MODE        EQU     %00000000
VDG_CTL_AD      EQU     $8110
;
		STX		WK_X
        LDX     #VRAM_TOP
        STX     WK_VRAM
;
        JSR     VDG_INIT
        JSR     VRAM_CLR
        JSR     DISP_CURSOR
		LDX		WK_X

	RTS
	
CONIN:
	LDAA	ACIAC
	ANDA	#$01
	BEQ	CONIN
	LDAA	ACIAD

	RTS
	
CONST:
	LDAA	ACIAC
	ANDA	#$01

	RTS
	
CONOUT:
	PSHA
CO0:
	LDAA	ACIAC
	ANDA	#$02
	BEQ	CO0
	PULA
	STAA	ACIAD

	STX		WK_X

;
;
; 内部CGにあわせて キャラクターコード変換
;
; 英小文字は大文字変換
        CMPA    #$60
        BGE     SUB20
; 英大文字はそのまま出力
        CMPA    #$40
        BGE     ECHO1
; 特殊記号はリバースキャラへ変更
        CMPA    #$20
        BGE     ADD40
        BRA     ECHO1
SUB20:
        SUBA    #$20
        BRA     ECHO1
ADD40:
        ADDA    #$40
        BRA     ECHO1
ECHO1:
        JSR     VRAM_OUT
;
	LDX		WK_X
	RTS

;
; VRAM SUB
;
;
; MC6747初期化
;
VDG_INIT:
        LDAA    #VDG_MODE
        STAA    VDG_CTL_AD
        RTS
;
; VRAMクリア
;
VRAM_CLR:
        LDX #VRAM_TOP
        LDAA #SPC
VRAM_CLR_LOOP:
        STAA 0,X
        INX
        CPX     #VRAM_END
        BNE     VRAM_CLR_LOOP
        RTS
;
; VRAM出力ルーチン
;
VRAM_OUT:
        CMPA    #CR
        BEQ     VRAM_OUT_END
        CMPA    #LF
        BEQ     VRAM_CR
        CMPA    #BS
        BEQ     BS_RTN
;
        LDX     WK_VRAM
        STAA    0,X
        LDAA    #CURSOR
        STAA    1,X
        INX
        STX     WK_VRAM
        CPX     #VRAM_END       ; 画面右下まできた?
        BNE     VRAM_OUT_END
;
; スクロール処理
;
VRAM_SCR1:
        LDX     #VRAM_TOP
        STX     WK_VRAM
VRAM_SCR:
        LDAA    $20,X
        STAA    0,X
        INX
        CPX     #VRAM_SCREND
        BNE     VRAM_SCR
;
        LDAA    #SPC
LINE_CLR:
        STAA    0,X
        INX
        CPX     #VRAM_END
        BNE     LINE_CLR
        LDX     #VRAM_SCREND
        STX     WK_VRAM
        JSR     DISP_CURSOR
        BRA     VRAM_OUT_END
;
; CR($0D)が押されたら改行処理
;
VRAM_CR:
        JSR     CLR_CURSOR
;
        LDAA    WK_VRAM+1
        ANDA    #$E0
        LDAB    WK_VRAM
        ADDA    #$20
        ADCB    #0
        CMPB    #$A2            ; VRAMはみ出す?
        BEQ     VRAM_SCR1       ; スクロール処理へ
        STAB    WK_VRAM
        STAA    WK_VRAM+1
        JSR     DISP_CURSOR
        BRA     VRAM_OUT_END
;
VRAM_OUT_END:
        RTS
;
; カーソル表示
;
DISP_CURSOR:
        LDAA    #CURSOR
        LDX     WK_VRAM
        STAA    0,X
        RTS
;
; カーソル消去
;
CLR_CURSOR:
        LDAA    #SPC
        LDX     WK_VRAM
        STAA    0,X
        RTS
;
; BS処理
;
BS_RTN:
        CPX     #VRAM_TOP
        BEQ     VRAM_OUT_END
;
        JSR     CLR_CURSOR
        LDX     WK_VRAM
        DEX
        STX     WK_VRAM
        JSR     DISP_CURSOR
        BRA     VRAM_OUT_END

config.incとUniversal Monitor(6800版)本体の変更点

config.incで定数などを定義していますので、今回のVRAM対応版用に定数定義を追加します。USE_DEV_6850_VRAMというスイッチを「1」にしてやります。

VRAMアドレスは変更の可能性が高いかな?と思い、config.incで定義することにしました。それ以外の定数定義はコンソールドライバ側に持っちゃいましたが、こちらに持ってきてもOKです。

;;;
;;; Motorola MC6850 & VRAM
;;;

USE_DEV_6850_VRAM = 1
 	IF USE_DEV_6850_VRAM
 	;; ACIA
ACIAC:	equ	$8018		; Control / Status Register
ACIAD:	equ	$8019		; Data Register
ACCR_V:	EQU	$15		; Control: x16, 8-bit, N, 1
;
VRAM_TOP        EQU     $A000
VRAM_END        EQU     $A200
 	ENDIF

前記のコンソールドライバは dev\dev_6850_VRAM.asmとしてdevフォルダへ配置しまして、それを読み込むunimon_6800.asmにも、ソースの下の方にインクルードされるよう以下のように手を入れました。

	IF USE_DEV_6850_VRAM
	INCLUDE	"dev/dev_6850_VRAM.asm"
	ENDIF

ソースを配置、修正したらThe Macroassembler ASとGNU makeがある環境でmakeするとIntelHex形式のオブジェクトが出来上がります。

このIntel HexファイルをROMライター(TL866など)でEPROMへ焼きましょう。

動かしたら暴走?! ~うまく動きました!

上記に掲載したコンソールドライバールーチンでは修正済みですが、最初つくったときは CONOUTルーチンでインデックスレジスタXを保存せず破壊したためUniversal Monitorに戻った後 暴走してしまいましたw

STX WK_XLDX WK_XのロジックでVRAM出力ルーチンをはさんでインデックスレジスタを保護することで対応しました。起動すると無事 RCAコンポジットモニターにもUniversal Monitorの出力が表示されました。やったー。

上記のスクショでは行頭に「^J」が出てますが、Universal Monitorの文字列出力が CR($0D)、LF($0A)が行末についてくることを当初は考慮せずにCR($0D)で改行処理を実施していたためです。
上記のコンソールドライバでは対応済みです。

電大版Tiny BASICを動かしてみたい

機械語モニター Universal MonitorがRCAコンポジットディスプレー対応できましたので、高校時代からの夢だった「電大版Tiny BASICをRCAコンポジットディスプレーに表示」をやってみたい!と思います。
自分特製のBASICパソコンっぽくて憧れます。

電大版Tiny BASICのソースを取得

電大版Tiny BASICですが、ブルーバックス「マイコンピュータをつかう」とか「続マイコンピュータの作り方つかいかた」などの専門書にダンプリストが掲載されていますので頑張ってウチコミすると動きますが、今回はいろいろと手を入れますし 今後のROM化などを考えるとソースを入手したいところです。
実は電大版Tiny BASICソースリストは、bit誌 1978年8月号に掲載されています。Amazonで復刻されていますのでご興味ある方はぜひぜひ。

【電子復刻版】bit 1978年08月号(通巻114号)
1969年に創刊されたコンピューターサイエンス誌で、2001年に休刊になるまで約500号が発行されています。今回は、このうち月刊誌386冊をイースト株式会社が行っている技術雑誌電子復刻プロジェクトを通じて電子的に復刻しました。インパクトのあ...

けっこう印字が かすれていたりして入力は難儀ですが、わたしも以前頑張ってソースコードを入力しました。このソースを手入力して公開しているページがありますので、今回はそちらからソースコードをいただいてきました。古風平凡さんのページです。

古い MC6800 マイコン(Old MC6800)

TB2KD110.zip が SBC6800で動くように手直しされたソースですので、今回作成したSBC6800互換のMC6802シングルボードコンピューターでの動作確認には最適です。シリアル入出力であれば無修正で動くはず。

上記のように SフォーマットのダンプをTeraTerm経由でMIKBUGへ流し込んで無事BASICが動きました。電大版Tiny BASICのオリジナルはMIKBUGを前提にしてますので、SBC6800データパックにあるACIA対応MIKBUGで動かしました。

アセンブリ環境の整備

ソースを変更してUniversal Monitor対応したりするためにはアセンブリ環境が必要です。アセンブリ環境には以前もご紹介した「Motorola 6800 Assembler」を使ってみたいと思います。

GitHub - JimInCA/motorola-6800-assembler: This is the assembler for the Motorola 6800 family of 8bit microprocessors.
This is the assembler for the Motorola 6800 family of 8bit microprocessors. - JimInCA/motorola-6800-assembler

電大版Tiny BASICのソース書式は古風(?)なMC6800アセンブラに近いはず。
アセンブラはmakeしてビルドする必要がありますが、昨今のWindowsはWSL2でLinuxを動かすことができますのでビルド環境作成も容易です。
またVisual Studio Codeで色分けしたコード閲覧をしたりアセンブルをかけたりできるともっと素敵。そんな環境構築方法がryu10さんのBLOGで紹介されてました。ありがたい!!!

Windows + VSCode で 6800 アセンブラ as0 を使う方法
概要 motorola-6800-assembler (as0) を Windows + VSCode 環境で…

Windows10/11へのWSL2(Ubuntu)の導入だとか、コンパイラgccのセットアップだとかはGoogleさんに聞いていただいてセットアップしていただいたのち、上記のryu10さんのBLOGの手順で「M6800 Assembly」プラグインを入れていただくとas0というMC6800アセンブラで手軽にvscode上でアセンブリできる環境が構築できます。素晴らしい!!!
bash.exeでWSL上のファイルをWindows側から動かせるんですね。すごいです。

ソースの変更点

さてソースを入手出来てアセンブリ環境ができたところで、電大版Tiny BASICのソースへUniversal Monitor(K68-VDG RCAコンポジットディスプレイ(VRAM))対応をしていきたいと思います。

Universal MonitorのVRAM対応ができているので、実際はUniversal Monitorを呼ぶだけでOKなんですが…

CMPAとかLDAAとか…

古風平凡さんのソースは、CMPA命令がCMPA Aとか、LDAA命令がLDA Aのように間に空白がはいったかたちになってました。こちらは古来のMC6800ニーモニックに倣って CMPA ACMPAALDA ALDAAのようにテキストエディタの置換機能で変更する必要があります。
いろいろな命令でこの事象が出てましたので、ちょっと手抜きして △AA(△は半角スペース)とか△BBとかでまとめて置換してしまいました。

RAM拡張の対応とかUniversal Monitorの文字入出力ルーチン対応

今回のMC6802シングルボードコンピュータではRAMを32kBにしてます、また$C000~の領域にRAMもありますのでスタックなどはそちらに逃がしたいと思います

<修正点>

RAMSSS	EQU	$0A00
RAMEEE	EQU	$7FFF
      :
STACK	EQU	$C0FF
SUBSTK	EQU	$C1FF
INEEE	EQU	$FFA0         ; Universal Monitor CONIN
OUTEEE	EQU	$FF90         ; Universal Monitor CONOUT
RESET	EQU	$E000         ; Universal Monitor START

あと動かしてから気づいたのですが、MIKBUGではINEEE(1文字入力ルーチン)でシリアル入力された文字データはすぐOUTEEE(1文字出力ルーチン)へ渡されてエコーバックしています。

<MIKBUGの1文字入力ルーチン>

  288 E1AC              INEEE
  289 E1AC 8DF7                    BSR      SAV
  290 E1AE B68018       IN1        LDAA     ACIACS
  291 E1B1 47                      ASRA
  292 E1B2 24FA                    BCC      IN1         RECEIVE NOT READY
  293 E1B4 B68019                  LDAA     ACIADA      INPUT CHARACTER
  294 E1B7 847F                    ANDA     #$7F        RESET PARITY BIT
  295 E1B9 817F                    CMPA     #$7F
  296 E1BB 27F1                    BEQ      IN1         IF RUBOUT, GET NEXT CHA
  297 E1BD 8D12                    BSR      OUTEEE
  298 E1BF 39                      RTS

UniversalMonitorの1文字入力では入力されるだけでエコーバックされないため電大版Tiny BASICの入力ルーチンに、以下のようにちょっと細工しておきました。いちおうAレジスタをスタックへ退避して保護しつつJSR OUTEEEを呼んでるあたりです。

<エコーバック修正箇所>

INFFF	JSR	INEEE
	CMPA	#$60
	BCS	*+4
	SUBA	#$20
	CMPA	#$25
	BNE	*+4
	LDAA	#$40
	PSHA
	JSR	OUTEEE
	PULA
	RTS

BASICコマンドテーブルの書式変更

「Motorola 6800 Assembler」では1バイトづつデータ定義するFCB命令で文字列を扱うことはできません。古風平凡さんのソースだと、アセンブラの処理の違いだと思いますが以下のように FCB    'LOAと定義されていてこのままでは正しく展開されません。FCC    /LOA/のように命令を変更する必要があります。
※最初これに気づかなくて、BASICが暴走して焦りました。

	FCB	'LOA
    ↓↓↓
	FCC	/LOA/

オリジナルのソースだと FCB 'L,'O,'A,'D+N のように1文字づつシングルクォーテーションが付与されてカンマ区切りで定義されていますので、この形で定義する対応でもOKです。

ここは前回もハマったところでした。

ソースの入力間違い部分修正

古風平凡さんのソースには一部に入力間違いがありましたので、修正しました。ARRAYルーチンとFACTルーチンです。昔自分が打ち込んだソースリストと比較して見つけました。
こちらを直したことでRND関数が正しく動くようになり、STAR TREKゲームが動きました!!

元ソース修正ソース
ARRAY   JSR FACT
    JSR POP
    BITB    #$C0
    BNE ERR11
    SEC
    ROLA
    ROLB
    ADDA    PREND+1
    ADCB    PREND
    CMPB    RAMEND
    BNE *+4
    CMPA    RAMEND*1
    BCC ERR11
    CLC
    RTS
ARRAY   JSR FACT
    JSR POP
    BITB    #$C0
    BNE ERR11
    SEC
    ROLA
    ROLB
    ADDA    PREND+1
    ADCB    PREND
    CMPB    RAMEND
    BNE *+4
    CMPA    RAMEND+1
    BCC ERR11
    CLC
    RTS

元ソース修正ソース
FACT    INX
    BSR GETN
    BCS PUSH
    CMPA    #’#
    BEQ PEEK
    CMPA    #’$
    BEQ HEXA2
    STX PX
    LDX #TABLE3
OPRATE  JSR SEARCH
    LDAA    1,X
    PSHA
    LDAA    0,X
    PSHA
    LDX PX
    RTS
FACT    INX
    BSR GETN
    BCS PUSH
    CMPA    #’#
    BEQ PEEK
    CMPA    #’$
    BEQ HEXA2
    STX PX
    LDX #TABLE3-2
OPRATE  JSR SEARCH
    LDAA    1,X
    PSHA
    LDAA    0,X
    PSHA
    LDX PX
    RTS

電大版TinyBASICの動作確認!

電大版Tiny BASICのアセンブラソースが正しくアセンブリできると、モトローラS形式というダンプリストができあがります。そのデータをTeraTerm経由でUniversalMonitorのLコマンドで流し込んでメモリーへ配置してやると準備OKです。

下記のように、以前入力して動かしたSTAR TREKゲーム(ブルーバックス「マイコンピュータの使い方」巻末掲載)も無事稼働しました!! やったー

BASICソースをTeraTermで流し込みする場合は、1行ごとのwaitを200msぐらいとってあげると安心です。取りこぼしがひどいのです。

今後の予定

高校時代にブルーバックスの「マイコンピュータをつかう」や専門書「マイコンの作り方使い方」などを見ながらMC6800系マイコンを自作してBASICが動いてTVに映るコンピュータを作りたかったと夢想していましたが、だいぶ近づいてきました。

今ならパソコン上のスクリーンエディタやMC6800クロスコンパイラがあったり、TeraTermでシリアル通信できたりするしますが、高校時代だとパソコンすら手元にない環境なので動かすことができたとは、とうてい思えませんが…😊

今回の対応で基本機能は整ってきましたので、今後は「USBかんたんホスト」でUSBキーボードをつないでスタンドアロンコンピュータにしたり、SBC-IOボードをつないで他の機器を制御したりできるようにしてみたいと思います。

コメント