SBC68系バスへSBC80系ボードをつなぐ

6502

先日作成した6502CPUマイコンですが、SBC6303ルーズキットSBC6800 Adapterと同じSBC68系バスを装備してみました。
KZ80シリーズで使っているSBC80系バスへ変換するボードがあると、外部駆動できるボードの幅が広がりそう。

SBC68系バスとSBC80系バスの違い

SBC68系バスは以下のようなピン配置となっています。KZ80などのSBC80系バスとピン数はいっしょですが、電源の位置や制御信号が違っています。

SBC6303ルーズキット技術資料

SBC6800 AdapterだとP10〜P17端子のあたりにCPUボードの74138でデコードしたアドレス信号線が出ていたりしますので若干違います。

信号線の変換回路

KZ80用外部ボードではZ80のI/Oアドレス($00〜$FF)をデコードする仕組みはありますが、SBC68系ではメモリーマップドI/OですのでアドレスバスA15〜A8をデコードする追加してあげる必要があります。また、リセット端子もSBC68系バスでは負論理、SBC80系バスでは正論理で反転する必要があります。

アドレスバスA15〜A13のデコードは74HCT138に任せまして、#RD/#WR信号とあわせて74HC139で#IOR/#IOW信号を生成しました。
74HC139の余った部分で#RESET信号をRES信号へ反転させるようにしました。CLK端子にはE(φ2)信号を入れてみました。

KZ80-IOB(I/Oボード)の8255はNG

以前 アドレスデコーダ74HC139に#IOREQを入れて試したときもNGだったのですが、I/Oボード(KZ80-IOB)の8255をつないで試したところNGでした。

実は上記のTweetをしたときには、#WRと#RDの配線が逆だったり、RESの配線端子がずれていたりとヘッポコな状態でした。配線を直してもNGでしたが…(X_X)

FM音源ボードで挑戦

続いて、以前SBC6303でも稼働実績があるFM音源LSI YM2151で試してみることにしました。Arduinoでも演奏できた事例もありますので、ちょっと期待して…

つないだだけでは音楽演奏はできませんので、以前作ったZ80SBC6303のVGMデータ演奏プログラムを見ながら移植します、どちらのプログラムも元は上記のArduino用VGM Playerです。

6502のニーモニックの資料を参照しながら作ったプログラムは以下になります。いつものThe Macroassembler ASでアセンブリできます。

;
; YM2151 PLAY
;  Universal Minitor for 6502 & SBC68toSBC80 Adapter
;

	CPU	6502

TARGET:	EQU	"6502"

;
;;; Functions
low	function	x,(x & 255)
high	function	x,(x >> 8)
;
;
MUSIC       EQU     $1000
OPM_ADDR    EQU     $8040
OPM_DATA    EQU     $8041

;
        org $0200
MAIN:
        LDA     #low(MUSIC)
        STA     MUSIC_PTR
        LDA     #high(MUSIC)
        STA     MUSIC_PTR+1
LOOP:
        LDY     #0
        LDA     (MUSIC_PTR),Y
        CMP     #$54
        BEQ     PLAY
        CMP     #$61
        BEQ     WAIT1_S
        CMP     #$62
        BEQ     WAIT2_S
        CMP     #$63
        BEQ     WAIT3_S
        CMP     #$64
        BEQ     WAIT3_S
        CMP     #$66
        BEQ     END_RTN
;
        CMP     #$70
        BEQ     WAIT4_S
        JMP     CHK_WAIT_S
;
NEXT:
        JSR     ADD_PTR
        JMP     LOOP
;
END_RTN:
        BRK
;
; SUB ROUTINE JUMP
;
PLAY:
        JMP     PLAY_S
;
ADD_PTR:
        LDA     #1
        CLC
        ADC     MUSIC_PTR
        STA     MUSIC_PTR
        LDA     #0
        ADC     MUSIC_PTR+1
        STA     MUSIC_PTR+1
        RTS
WAIT1_S:
        INY
        LDA     (MUSIC_PTR),Y
        STA     WAIT_CNT
        INY
        LDA     (MUSIC_PTR),Y
        STA     WAIT_CNT+1
        JSR     WAIT
        JSR     ADD_PTR
        JSR     ADD_PTR
        JMP     NEXT
;
WAIT2_S:
        LDA     #low(735)
        STA     WAIT_CNT
        LDA     #high(735)
        STA     WAIT_CNT+1
        JSR     WAIT
        JMP     NEXT
;
WAIT3_S:
        LDA     #low(882)
        STA     WAIT_CNT
        LDA     #high(882)
        STA     WAIT_CNT+1
        JSR    WAIT
        JMP     NEXT
;
CHK_WAIT_S:
        CMP     #$80
        BCS     WAIT4_EXIT
WAIT4_S:
        AND     #$0F
        CLC
        ADC     #1
        STA     WAIT_CNT
        LDA     #0
        STA     WAIT_CNT+1
        JSR    WAIT
WAIT4_EXIT:
        JMP     NEXT
;
WAIT:
        JSR     WAIT_1MS
        SEC
        LDA     WAIT_CNT
        SBC     #1
        STA     WAIT_CNT
        LDA     WAIT_CNT+1
        SBC     #0
        STA     WAIT_CNT+1
;
        LDA     WAIT_CNT
        CMP     WAIT_CNT+1
        BNE     WAIT
WAIT_EXIT:
        RTS
WAIT_1MS:
        LDA     #$E0
        STA     WAIT_1MS_CNT
WAIT_1MS_LOOP:
        DEC     WAIT_1MS_CNT
        NOP
        NOP
        BNE     WAIT_1MS_LOOP
        RTS
;
;
PLAY_S:
        INY
        LDA     (MUSIC_PTR),Y
        STA     WK_ADDR
        INY
        LDA     (MUSIC_PTR),Y
        STA     WK_DATA
;
WRITE_OPM
        LDA     OPM_DATA
        CMP     #$80
        BEQ     WRITE_OPM
;
        LDA     WK_ADDR
        STA     OPM_ADDR
        NOP
        NOP        
        NOP
        NOP     
        LDA     WK_DATA
        STA     OPM_DATA
        JSR     ADD_PTR
        JSR     ADD_PTR
        JMP     NEXT
;
; Work Area
;
        org  $30
MUSIC_PTR RMB 2
WK_ADDR  RMB 1
WK_DATA  RMB 1
WAIT_CNT RMB 2
WAIT_1MS_CNT RMB 1
SUB_PTR  FDB    SUB_PTR_TBL
;
        END

そんなに長いプログラムではないものの、6502CPUのニーモニックに慣れていないもので半日ぐらいウンウン言ってました。コーディングしてみて気がついた点としては…

  • アキュームレーターのインクリメント命令が無い
  • インデックスレジスタのインクリメント命令(INY)が255を超えてもキャリーフラグが立たない
  • 加算命令、減算命令にキャリー付きしかないので、加算前はキャリークリア、減算前はキャリーセットが吉
  • M6800 CPUも同じですが、条件分岐ジャンプが相対ジャンプなのですぐ127バイトの壁を超えて飛べなくなってしまう
  • やっぱり間接アドレス用に16bitレジスタが1つは欲しいw メモリーの16bitデータの加算命令があればなぁとか…

ボードの回路データや、上記のプログラム等はgithubにUPしました。

GitHub - kuninet/SBC68to80CNV
Contribute to kuninet/SBC68to80CNV development by creating an account on GitHub.

サンプル音楽を演奏、鳴った!!

KZ80-YM2151FM音源ボードのリポジトリにも添付しているサンプルVGMデータで鳴らしてみました。無事音楽が鳴りました!! やった〜。

これで、SBC68系からSBC80系バスへの変換ボードの回路が良さげな感じということがわかりましたので、今後 他のKZ80シリーズとして作ったボードを接続してみたいと思います。

コメント

  1. 久代浩司 より:

    初めまして。クシロと申します。
    現在こちらではZ80A CPU搭載の教育用マイコンボードに、自作の通信回路(D8251AFC MAX232CPE 74HC4060AP 74HCT04AP Xtal:4.9152MHz)を乗っけて通信の実験中ですが思うようにいかず苦戦中です。CPU CLK は4MHz、自作回路のモード設定は、非同期・ストップビット1・偶数パリティ・パリティチェック無し・8ビット長・9600ボーの(6EH)、コマンド命令は(37H)として
    電源投入時、8251への0書き込み3回、内部レジスタクリア(40H)を実施。増設IOボードがありますので、そちらのLEDポート出力にてステータスは見れているとは思うのですが、
    うまくいきません(苦笑)。
    どうか、良いお知恵をお授け頂きたく、よろしくお願いします。

    (自作の回路図、マイコンボードの回路図はあります)

    • kuninet より:

      久代さん、こんにちは
      わたしはMAX232をちゃんと搭載した232Cシリアルボードは作ったことがないのですが….
      いつも、FTDI型のシリアル-USB変換でつなぐことで、マイコン側はTTLレベルのシリアルというのがもっぱらです。^^);;;

      電脳伝説さんのSBC8080用のプログラムの一部のソースを参考にさせていただいて、以下のような自分のマシン語モニター用のドライバーは書いたことがあります。シーケンスは一緒ですね。

      https://github.com/kuninet/Z80mon/blob/master/device/KZ80_8251.asm

      8251をつかってSBC8080バスにつながるようにつくったI/Oボードの回路図がこちらです。
      HC4060で4段階のクロックを作って 76800bps〜9600bpsまで切り替えができるようにしてみました。回路は似ているかもですね。
      https://github.com/kuninet/Z80_IOB/blob/master/image/Z80-8251-PPI.jpg

  2. 久代浩司 より:

    kuninetさん おはようございます。突然の見苦しい、厚かましい内容のコメントを致しまして、誠に申し訳ございません。また、それにもかかわらず、お返事までいただきまして、大変ありがたとうございました。ご提示いただきました内容、確認してみます。この度は、ありがとうございました。また、何か別件でお願いするかもです。(苦笑)

    • kuninet より:

      久代さん、こんにちは
      わたしも、いろいろな先達の方々の事例やプログラムソースを参考に、なんとか動かしている感じなので。^^)
      稼動すると良いですね。
      なんかこう、私の場合だと 大丈夫と思い込んでいたところでいつもハマります。