Super AKI-80 を使ってみる(3)
Super AKI-80 で BASIC を動かす
I/O エミュレーション
CH32V203 との接続では A0-A7 までしかつながっていないので、現時点では 256 バイトのプログラムしか書き込むことができませんでした。 ここでは、それ以上のプログラムを Z80 側に転送できるようにします。
DMA の処理が終了したのちの CH32V203 を Z80 の I/O デバイスとして振舞うようにして、続きのコードを読めるようにします。 ここでは仮に Z80 の IO ポート番号 $40 でやり取りできるようにします。
CH32V203 側の処理は単純で、Z80 バスを監視して IO アクセスが来たら反応するようにします。 Z80 では IO アクセスには自動的に 1Wait 挿入されるので、10MHz 動作時に 3 clocks = 300nsec の余裕があります。
しかし、CH32V203 の GPIO 入力には 144MHz 時でも 70ns ほどかかるので、 そのままでは対応できません。
そこで IO アクセスの際には自動で WAIT 状態になるようにして、明示的に WAIT を解除するようにします。 (参考文献) なお、Super AKI-80 の WAIT のプルアップ抵抗は外してあります。
内蔵ペリフェラルへのアクセスでも反応してしまうので、CH32V203 へのアクセスでないときにも WAIT を解除する処理が入っています。 また、モード2 割り込みの際にも反応してしまうので、これにも対応する必要があります。
前回と比べて以下の信号線が追加で配線されています。
WAIT 1K の抵抗を介して IORQ とも接続されています。
M1
BASIC を動かす
電脳伝説さんの移植した MBASIC を動かします。
起動するときに DMA で、ブートローダを SRAM に書き込みます。
org 0
BOOTLOAD equ $4000 ; Bootloader store area
PORT equ $40 ; I/O port for load code from CH32V203
;; move boot loader to another area
start:
di
ld sp,$8000
ld hl,$0
ld de,BOOTLOAD
ld bc,$100
ldir
jp BOOTLOAD+blstart
;; bootloader code
blstart:
;; send I/O to reload trigger
ld a,$00
out (PORT),a
;; get code size
in a,(PORT)
ld c,a
in a,(PORT)
ld b,a
;;
ld hl,0
loop:
in a,(PORT)
ld (hl),a
inc hl
dec bc
ld a,b
or c
jr nz,loop
;;
jp 0
書き込まれたブートローダは BASIC と配置が被るので、一旦じゃまにならない位置に転送します。
次に CH32V203 の IO エミュレーションを使って、BASIC のコードを転送して BASIC の先頭にジャンプします。
BASIC 側には特に変更なくバイナリをそのまま使用しました。
おわりに
CH32V203 を使って、完全オール RAM の Z80 システムを作成することができました。 IO アクセスのエミュレーションができるようになったので、 SPI フラッシュや SD カードを使った外部記憶装置のエミュレーションにもチャレンジしてみたいと思います。