So-net無料ブログ作成
English Version

レトロマイコンZ80ボードの構想(その15)エスケープシーケンスの実験 [Z80]

 前回の「レトロマイコンZ80ボードの構想(その14)CP/MでのWM動作実験」ではWordMasterにANSIエスケープコード用のパッチを入れて動かしましたが、今回はPIC側のCONOUT処理に次のエスケープシーケンスの処理を入れてみました。
  • 画面クリア : ESC+'*'
  • カーソル位置制御 : ESC+'='+nm
    n:Y position,m:X position(position offset:20H)

 picleソース側への追加なので前回記事のような限られた領域にZ80のコードを詰め込むより簡単です。

 試しに ここ から QTITRIS.COM(キャラクタ版テトリス)をダウンロードして動かしてみました。

 下記の操作ログはエスケープシーケンスのサブセット対応(37行目~73行目部分)したpicleのリストを表示後、runコマンドで実行し、CP/Mブート後、QTITRISを起動している様子です。


簡易的なエスケープシーケンス対応実験ログ
:l 1:# CP/M boot test for PIC24FJ64GA004 with picle 2:# Ver 0.03 by skyriver 2018/03/21 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgStart,ProgWrk,_WrkVal,_PicDma; 8:var EscFlg,EscY; 9: 10: 11:proc PicSrv() { 12: var i,fno,rval; 13: 14: while (1) { 15: while ( LATB[-1] & 8 ) {} # wait halt 16: PmpOn(); 17: PmpSetAdr( ProgWrk ); 18: fno = MemRd(); # dummy 19: for ( i=0; i<9; i=i+1 ) { 20: _WrkVal[i] = MemRd(); 21: } 22: fno = _WrkVal[0]; # function No 23: if ( fno = 1 ) { # CONST 24: if ( InpChk_() ) { 25: rval = $ff; 26: } else { 27: rval = 0; 28: } 29: } 30: else if ( fno = 2 ) { # CONIN 31: if ( InpChk_() ) { 32: rval = InpChar_(); 33: } else { 34: rval = InpChar_(); 35: } 36: } 37: else if ( fno = 3 ) { # CONOUT 38: var c; 39: c = _WrkVal[2]; 40: if ( EscFlg = 0 ) { 41: if ( c = $1b ) { 42: EscFlg = 1; 43: } 44: PrnChar_( c ); 45: } 46: else if ( EscFlg = 1 ) { 47: if ( c = '*' ) { # clear screen 48: PrnStr_( "[2J" ); 49: PrnChar_($1b); 50: PrnStr_("[1;1H"); 51: EscFlg = 0; 52: } 53: else if ( c = '=' ) { # move cur 54: EscFlg = 2; 55: } else { 56: PrnChar_( c ); 57: EscFlg = 0; 58: } 59: } 60: else if ( EscFlg = 2 ) { 61: EscY = c - $1f; 62: EscFlg = 3; 63: } 64: else if ( EscFlg = 3 ) { 65: PrnChar_( '[' ); 66: PrnDec_( EscY ); 67: PrnChar_( ';' ); 68: PrnDec_( c - $1f ); 69: PrnChar_( 'H' ); 70: EscFlg = 0; 71: } 72: rval = 0; 73: } 74: else if ( fno = 4 ) { # READ 75: var track; 76: track = _WrkVal + 4; 77: rval = BlkRead( track[0]*64 + _WrkVal[8] ); 78: if ( rval = 0 ) { 79: PmpSetAdr( _PicDma ); 80: for ( i = 0; i < 128; i=i+1 ) { 81: MemWr( _SpiBuf[ i ] ); 82: } 83: } 84: } 85: else if ( fno = 5 ) { # WRITE 86: var track; 87: track = _WrkVal + 4; 88: PmpSetAdr( _PicDma ); 89: i = MemRd(); # dummy 90: for ( i = 0; i < 128; i=i+1 ) { 91: _SpiBuf[ i ] = MemRd(); 92: } 93: rval = BlkWrite( track[0]*64 + _WrkVal[8] ); 94: } else { 95: PrnStr_( "\nFunc err" ); 96: } 97: PmpSetAdr( ProgWrk + 1 ); 98: MemWr( rval ); 99: 100: PmpOff(); 101: LATC[0] = $0000; # reset on 102: BusRelease(); 103: LATC[0] = $0001; # reset off 104: } 105:} 106: 107: 108:proc main() { 109: var i; 110: init(); 111: initPmp(); 112: initSpi(); 113: initSd(); 114: 115: ProgStart = $0100; # Prog start addr 116: ProgWrk = $ff70; # Prog work addr 117: _PicDma = $ff80; 118: _WrkVal = Alloc( 5 ); 119: 120: if ( BlkRead( 0 ) <> 0) { 121: PrnStr_( "NG" ); 122: SetCsOff(); 123: } else { 124: SetCsOff(); 125: PmpOn(); 126: 127: PmpSetAdr( 0 ); 128: MemWr( $c3 ); 129: MemWr( ProgStart ); 130: MemWr( ProgStart / 256 ); 131: 132: PmpSetAdr( ProgStart ); 133: for ( i = 0; i < 128; i=i+1 ) { 134: MemWr( _SpiBuf[ i ] ); 135: } 136: PmpOff(); 137: LATC[0] = $0000; # reset on 138: BusRelease(); 139: LATC[0] = $0001; # reset off 140: PicSrv(); 141: } 142:} :run loading... 64k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>dir A: ASM COM : BIOS ASM : CPM SYS : DDT COM A: DEBLOCK ASM : DISKDEF LIB : DSKMAINT COM : DUMP ASM A: DUMP COM : ED COM : LOAD COM : PIP COM A: READ ME : STAT COM : SUBMIT COM : WM HLP A: XMODE PRN : XSUB COM : D COM : XMODEM PRN A: XMODEM HEX : XMODEM2 ASM : XMODEM COM : DUMP PRN A: XMODEM CFG : XMODEM ASM : DUMP HEX : XMODE HEX A: XMODE REL : XMODE ASM : XMODE COM : XMODE BAK A: WMM COM : M80 COM : L80 COM : QTITRIS COM A: QUATRIS SCO : ESCTEST TXT : STDESC PRN : STDESC HEX A: LINE TXT a>QTITRIS



 テトリスが起動した画面のキャプチャが下の画面です。
 数字キーで操作するので結構難しい(Z80が16MHz動作なので最低速設定にしても早すぎる・・)
 因みにWordStarは他にも表示属性設定等のエスケープシーケンスを使っているのできれいな画面にはなりませんでしたが、PIC側で対応するのは容易だと思います。

 WindowsとCP/M間のファイルのやり取りは前回記事のコメント欄にも書いたようにCP/M側でXMODEMというアプリを使っています(Windows側はTeraTermのXMODEM送受信機能を使用)。
 ファイルのやり取りの際、SDカードを経由する必要がなくなったので便利になりましたが、私の環境では大きなファイルの転送に失敗(オプション指定でZ80のクロック設定しても駄目)することがあるので対策を考え中です。
 PIC側に今回のようなコンソールデータの変換ロジックを入れるとバイナリデータの透過性が保証できなくなる問題が新たに発生します。(転送にはPUN:ディバイスを使えば解決できるけどね)

QTITRIS画面


★2018/03/24 追記
 下記のエスケープシーケンスを対応したことで無事 WordStar が動きました。
  • ESC+'C'+'0' : Reverse off(たぶん・・^^;)
  • ESC+'C'+'1' : Reverse on
  • ESC+'B'+'0' : Bold off
  • ESC+'B'+'1' : Bold on

 ANSIエスケープコードへの変換としては Reverse をそのままReverseに変換したところ、WordStarを終了してもReverseのままになったのでItalic(ESC+'[3m')に変換しています(TeraTermでは画面上は変化なし)。
 BoldはANSIのBold(ESC+'[1m')に変換していますがTeraTermでは文字が黄色になります。(設定で変更可能らしい)

 この頃のディスプレイはまだカラー化していないのでモノクロで識別可能な表示属性になっていますが、今ならエスケープシーケンスを色付きに対応させた方が見易くていいです(当時の状態の再現という観点では好ましくないかも)

 私は普段、秀丸エディタを使っていますが、今でもWordStarライクな操作にカスタマイズしています。
 WordStarを改めて使ってみると、今でもあまり遜色なく使えるエディタであることに驚かされました。

 WordStarのソースコードはアセンブラで13万7000行あり、開発者のRob Barnabyさんはこれを4ヵ月で作ったのだそうです。平均的な生産性で換算すると42人が1年かけて開発する規模だということです。すご~ぃですね。

 WordStarの画面はこんな感じです。

WordStar画面


[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

レトロマイコンZ80ボードの構想(その14)CP/MでのWM動作実験 [Z80]

 前回の記事「レトロマイコンZ80ボードの構想(その13)」で書いたように CP/M が起動できた(まだまだ細かい調整は必要ですが)ので懐かしいソフトを動かしたりして遊んでいましたが、エディタが無いと何かと不便なのでWordMasterを動かしてみることにしました。

 「CP/M Text Editors and Word Processors」からダウンロードできるので簡単に動かせるだろうと思っていましたが意外と難関でした・・・^^;

 ネット上ではエミュレータで動かしている例はありましたが、リアルのCP/MでTeraTerm等を接続してWordMasterを動かしている例は見つからなかった(みんなどうしてるんだろう?)

 ダウンロードしたWordMasterファイルには画面制御のエスケープシーケンスをカスタマイズできるようにアセンブラのサンプルソースが付いています。
 昔、画面表示部分を作ったこともあったので思い出しましたが、当時のエスケープシーケンスは移動先のカーソル位置を表現するのにスペースコード(20H)に位置情報を足したコードで表現していて、カスタマイズ用のサンプルソースも同様でした。

 しかし TeraTerm のVT100モード等ではANSIのエスケープコードが採用されていてカーソル位置情報を10進文字で表現する必要があります。
(ANSIエスケープコードは碧色工房さんのウェブサイト等を参照させていただきました)

 WordMasterに添付されているカスタマイズ用のソースはWordMasterの画面制御部を置き換えるパッチ形式になっていて使用できる領域が小さくて通常の10進変換はとても入れ込めそうにありません・・・


 小さな領域にマシン語コードを埋め込む・・これぞマイコンの醍醐味なのでチャレンジしてみました ^^

 最大の問題はバイナリから十進数への変換です。当然除算処理が必要になってきますが、今回の用途に限って言えば10進2桁までの数字を対象としていいのでこの条件で簡略化した除算処理が下のリストです。

 A-regで渡されたデータを処理し、E-reg に10の桁、A-reg に1の桁が入ります(やっていることは筆算の計算と同様)
 エミュレータではなく、(ワザワザ)実機CP/M上のZSIDで動作確認しています ^^

Binary to Decimal Transfer(Z80 Assembler)
CnvCal: LD E,0 ;2(2) LD BC,05A0H ;3(5) B:loop counter 5*256+10*(1<<4) CnvC1: SLA E ;2(7) CP C ;1(8) JR C,CnvC2 ;2(10) SUB C ;1(11) INC E ;1(12) CnvC2: SRL C ;2(14) DJNZ CnvC1 ;2(16)


 WordMaster内の1文字出力処理である OUTCHR のアドレスを確認したら相対ジャンプ到達範囲内だったので関数末尾の OUTCHRコールは相対ジャンプ化しました。

 ESC+'[' の出力をサブルーチン化する等して細切れの使用可能領域に断片的にコードを埋め込み、とうとう完成と思ったところ、ESC+'[2J'での画面クリアではカーソルがホームに戻らないので画面が乱れることが判明・・・orz

 もうこれ以上の処理は入らないと諦めかけたましたが、メモリダンプを見たところ、パッチ領域の直前がメッセージのアスキーデータ領域であることに気づき、メッセージの最後の部分の領域を若干拝借してコードを埋め込みました。 ^^;;

 hexファイルのパッチ適用操作は下記の操作ログを参照してください。(シリアルNoをつぶして悪さしているみたいだけどそうじゃないよ)

WordMasterへのパッチ適用作業工程
b>dir B: ANSI HEX : ANSI MAC : BEE ASM : H89 ASM B: HAZ ASM : LSI ASM : SOL ASM : WM COM B: WM HLP : WMH89 COM : WM-SOROC COM b>a:ddt wm.com DDT VERS 2.2 NEXT PC 2700 0100 -d 0100 C3 69 02 C3 60 02 20 43 4F 50 59 52 49 47 48 54 .i..`. COPYRIGHT 0110 20 28 43 29 20 31 39 37 38 20 20 4D 49 43 52 4F (C) 1978 MICRO 0120 50 52 4F 20 49 4E 54 45 52 4E 41 54 49 4F 4E 41 PRO INTERNATIONA 0130 4C 20 43 4F 52 50 4F 52 41 54 49 4F 4E 20 20 20 L CORPORATION 0140 20 20 20 0D 0A 00 0D 4D 69 63 72 6F 50 72 6F 20 ....MicroPro 0150 57 4F 52 44 4D 41 53 54 45 52 20 72 65 6C 65 61 WORDMASTER relea 0160 73 65 20 31 2E 30 37 41 20 73 65 72 69 61 6C 20 se 1.07A serial 0170 23 20 57 4D 36 33 34 34 56 35 20 20 20 0D 0A 00 # WM6344V5 ... 0180 00 00 00 00 00 00 3E 1B CD EF 01 3E 2A CD EF 01 ......>....>*... 0190 3E 1A CD EF 01 C9 3E 1B CD EF 01 3E 3D CD EF 01 >.....>....>=... 01A0 3E 20 85 CD EF 01 3E 20 84 CD EF 01 C9 00 00 00 > ....> ........ 01B0 00 00 00 00 00 00 00 B8 29 18 50 00 00 00 00 00 ........).P..... -iansi.hex -r NEXT PC 2700 0000 -d100 0100 C3 69 02 C3 60 02 20 43 4F 50 59 52 49 47 48 54 .i..`. COPYRIGHT 0110 20 28 43 29 20 31 39 37 38 20 20 4D 49 43 52 4F (C) 1978 MICRO 0120 50 52 4F 20 49 4E 54 45 52 4E 41 54 49 4F 4E 41 PRO INTERNATIONA 0130 4C 20 43 4F 52 50 4F 52 41 54 49 4F 4E 20 20 20 L CORPORATION 0140 20 20 20 0D 0A 00 0D 4D 69 63 72 6F 50 72 6F 20 ....MicroPro 0150 57 4F 52 44 4D 41 53 54 45 52 20 72 65 6C 65 61 WORDMASTER relea 0160 73 65 20 31 2E 30 37 41 20 73 65 72 69 61 6C 20 se 1.07A serial 0170 23 20 57 4D 36 0D 0A 00 CD EF 01 21 00 00 18 16 # WM6......!.... 0180 CD 8C 01 3E 32 CD EF 01 3E 4A 18 EC 3E 1B CD EF ...>2...>J..>... 0190 01 3E 5B 18 5A 00 CD 8C 01 7D CD AA 01 3E 3B CD .>[.Z....}...>;. 01A0 EF 01 7C CD AA 01 3E 48 18 45 3C CD C4 01 47 83 ..|...>H.E<...G. 01B0 CD EF 01 7A 80 18 38 B8 29 20 50 00 00 FF 00 00 ...z..8.) P..... -g0 b>save 38 wmm.com


 WordMasterのカーソルが最上位行での上スクロール時の再描画ぶりを久々に見れて懐かしい・・^^
 無事WordMasterが動作したことを記念してキャプチャを貼っておきます。
 また、カスタマイズしたパッチソース(macro-80用)とヘキサファイルは下記からダウンロードしてください。
 スクリーンの行数を24から32に変更しています(32行の画面じゃないと上スクロール時に画面が乱れます)

※2018/03/18 コメントに書いたように単純ループ式に変更しました。
WordMaster ANSI用パッチ


WordMaster画面



[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(10) 
共通テーマ:趣味・カルチャー

レトロマイコンZ80ボードの構想(その13)CP/M80 boot成功 [Z80]

 前回の記事でRESETでのHALT抜け方式でBIOS内コンソール関連の機能確認が出来たのでREAD/WRITEを追加しBIOSを仕上げました。

 また、「レトロマイコンZ80ボードの構想(その9)CP/M80 BIOS」の記事の最後の方でbootはPIC内のフラッシュメモリから展開するようなことを書きましたが、PIC側のI/O不足対策により、PIC側からアクセスできる外部メモリの範囲は 0x0000 - 0x07ff, 0xf800 - 0xffff になったのでPIC内フラッシュからの展開はやめて先頭セクタにIPLを入れたCP/M本来の形式にしました。

 IPLはこんな感じです。

PicCPM用のIPL(Z80アセンブラ)
; CP/M IPL for PicCPM(PIC24FJ64GA004) ; Ver 0.01 2018/03/14 by skyriver 0040 MaxSec EQU 64 ;sectors pre track 0037 SysSec EQU 55 ;number of system sectors 0040 MSIZE EQU 64 B000 BIAS EQU (MSIZE-20) * 1024 E400 CCP EQU 3400H+BIAS ;base of cpm ccp FA00 BIOS EQU CCP+1600H ;base of bios 000D CR EQU 13 000A LF EQU 10 FF70 PICWRK EQU 0FF70H ; PIC service work area FF80 PICDMA EQU 0FF80h ; DMA for PIC 0080 SECSIZE EQU 128 ; sector size 0000 FC_SYSTEM EQU 0 ; EXIT CP/M 0001 FC_CONST EQU 1 ; CONST 0002 FC_CONIN EQU 2 ; CONIN 0003 FC_CONOUT EQU 3 ; CONOUT 0004 FC_READ EQU 4 ; READ SD Card 0005 FC_WRITE EQU 5 ; WRITE SD Card 0006 FC_PIC EQU 6 ; RETURN TO PIC ; ++++ work area for PIC Interface FF70 FuncNo EQU PICWRK ; ds 1 : function No FF71 RetVal EQU PICWRK + 1 ; ds 1 : return value FF72 CoData EQU PICWRK + 2 ; ds 1 : conout data FF73 SelDk EQU PICWRK + 3 ; ds 1 FF74 Track EQU PICWRK + 4 ; ds 2 FF76 DmaAdr EQU PICWRK + 6 ; ds 2 FF78 Sector EQU PICWRK + 8 ; ds 1 0000' ASEG .Z80 ORG 0100H ; IPL for the CP/M with a PIC. 0100 31 0080 LD SP,0080H 0103 3E E9 LD A,0E9H ; JP (HP) ope-code 0105 32 0000 LD (0000H),A 0108 21 015E LD HL,IplMsg 010B CD 014A CALL PrnMsg 010E 3E 04 LD A,FC_READ 0110 32 FF70 LD (FuncNo),A 0113 AF XOR A 0114 32 FF73 LD (SelDk),A 0117 5F LD E,A ; DE : track No 0118 57 LD D,A 0119 21 E400 LD HL,CCP 011C 01 3701 LD BC,SysSec*256 + 1;B:sector counter, C:sector No 011F ED 53 FF74 LoopTr: LD (Track),DE 0123 79 Loop: LD A,C 0124 32 FF78 LD (Sector),A 0127 C5 PUSH BC 0128 D5 PUSH DE 0129 E5 PUSH HL 012A 21 012E LD HL,NextHalt 012D 76 HALT 012E NextHalt: 012E E1 POP HL 012F 11 FF80 LD DE,PICDMA 0132 EB EX DE,HL 0133 01 0080 LD BC,SECSIZE 0136 ED B0 LDIR 0138 EB EX DE,HL 0139 D1 POP DE 013A C1 POP BC 013B 05 DEC B 013C CA FA00 JP Z,BIOS 013F 0C INC C 0140 79 LD A,C 0141 FE 40 CP MaxSec 0143 38 DE JR C,Loop 0145 0E 00 LD C,0 0147 13 INC DE 0148 18 D5 JR LoopTr 014A PrnMsg: 014A 3E 03 LD A,FC_CONOUT 014C 32 FF70 LD (FuncNo),A 014F PrnM00: 014F 7E LD A,(HL); 0150 23 INC HL 0151 B7 OR A 0152 C8 RET Z 0153 32 FF72 LD (CoData),A 0156 EB EX DE,HL 0157 21 015B LD HL,PrnM10 015A 76 HALT 015B EB PrnM10: EX DE,HL 015C 18 F1 JR PrnM00 015E IplMsg: 015E 0D 0A DB CR,LF 0160 6C 6F 61 64 DB 'loading...' 0164 69 6E 67 2E 0168 2E 2E 016A 00 DB 0 END
★2018/03/15 追記 iplの版数が古かったので差し換えました^^;


 前回の記事のBIOS試験の延長でIPLを読込み起動してみたところ、多少のゴニョゴニョした作業はあったものの CP/M の初起動に成功しました。(^^)/

 picle言語で色々確認後、最終的にはC言語に置き換えようかと思っていましたが、picle言語だけでCP/M起動までできてしまいました。^^

 初起動の様子が下の表示です。IPL試験用のpicleのリスト表示後、runコマンドで実行しています。IPLのロード状態確認のためにメモリダンプ表示後、Z80にリセットをかけてIPLを実行させています。
 ディバッグ用の表示のコメントアウトがあったり、少し生々しい状態で今後整理が必要ですがCP/M 初ブート記念として貼っておきます。

IPL試験・・CP/Mが起動した(picle言語)
:l 1:# CP/M boot test for PIC24FJ64GA004 with picle 2:# Ver 0.02 by skyriver 2018/03/14 3: 4:use LibCpm; 5:use LibSpi; 6: 7:var ProgStart,ProgWrk,_WrkVal,_PicDma; 8: 9:proc initSd() { 10: var dmy,ans,i; 11: 12: ProgStart = $0100; # Prog start addr 13: ProgWrk = $ff70; # Prog work addr 14: _PicDma = $ff80; 15: _WrkVal = Alloc( 5 ); 16: 17: SetCsOff(); 18: for ( i=0; i<10; i=i+1 ) { 19: SpiSnd( $ff ); 20: } 21: TmWait( ByteTimer * 2 ); 22: SetCsOn(); 23: SpiSnd( $40 ); # CMD0 24: SpiSnd( 0 ); 25: SpiSnd( 0 ); 26: SpiSnd( 0 ); 27: SpiSnd( 0 ); 28: SpiSnd( $95 ); 29: 30: ans = SpiRcvAns(); 31: SetCsOff(); 32: 33: if ( ans <> 1 ) { 34: PrnVal( "Cmd0Res:", ans ); 35: } else { 36: SetCsOn(); 37: SpiSnd( $ff ); # __ improve error 38: SpiSnd( $48 ); # CMD8 39: SpiSnd( 0 ); 40: SpiSnd( 0 ); 41: SpiSnd( 1 ); 42: SpiSnd( $aa ); 43: SpiSnd( $87 ); 44: ans = SpiRcvAns(); 45: SpiRcvN( 4 ); # 16M:00 00 01 aa 46: SetCsOff(); 47: if ( ans <> 1 ) { 48: PrnVal( "CMD8 err:", ans ); 49: } else { 50: if ( (_SpiBuf[2] <> $01) | (_SpiBuf[3] <> $aa ) ) { 51: PrnStr_("SDC not v2" ); 52: } else { 53: SdhcFlg = 1; 54: do { 55: SetCsOn(); 56: SpiSnd( $77 ); # CMD55 57: SpiSnd( 0 ); 58: SpiSnd( 0 ); 59: SpiSnd( 0 ); 60: SpiSnd( 0 ); 61: SpiSnd( $65 ); 62: ans = SpiRcvAns(); 63: if ( ans = 1 ) { 64: SpiSnd( $69 ); # ACMD41 65: SpiSnd( $40 ); 66: SpiSnd( $ff ); 67: SpiSnd( $80 ); 68: SpiSnd( $00 ); 69: SpiSnd( $17 ); 70: ans = SpiRcvAns(); 71: } 72: SetCsOff(); 73: } while ( ans <> 0 ); 74: SetCsOn(); 75: SpiSnd( $7a ); # CMD58 76: SpiSnd( 0 ); 77: SpiSnd( 0 ); 78: SpiSnd( 0 ); 79: SpiSnd( 0 ); 80: SpiSnd( $fd ); 81: ans = SpiRcvAns(); 82: SpiRcvN( 4 ); # 16MB:c0 ff 80 00 83: SetCsOff(); 84: SPISTAT[0] = $0000; 85:# SPISTAT[1] = $7e; # SPI1CON1 prescale1:1,prescale1:1 = 1:1 4M NG 86:# SPISTAT[1] = $7a; # SPI1CON1 prescale2:1,prescale4:1 = 8:1 2M NG 87: SPISTAT[1] = $7d; # SPI1CON1 prescale1:1,prescale16:1 = 16:1 1M OK 88: SPISTAT[0] = $8000; 89: if ( ans <> 0 ) { 90: PrnVal( "CMD58 err:", ans ); 91: } 92: } 93: } 94: } 95: SetCsOff(); 96:} 97: 98: 99:proc PicSrv() { 100: var i,fno,rval; 101: 102: while (1) { 103: while ( LATB[-1] & 8 ) {} # wait halt 104: PmpOn(); 105: PmpSetAdr( ProgWrk ); 106: fno = MemRd(); # dummy 107: for ( i=0; i<9; i=i+1 ) { 108: _WrkVal[i] = MemRd(); 109: } 110: fno = _WrkVal[0]; # function No 111: if ( fno = 1 ) { # CONST 112: if ( InpChk_() ) { 113: rval = $ff; 114: } else { 115: rval = 0; 116: } 117: } 118: else if ( fno = 2 ) { # CONIN 119: if ( InpChk_() ) { 120: rval = InpChar_(); 121: if ( rval = $1b ) { # if ESC then end 122: exit(); 123: } 124: } else { 125:# PrnChar_('x'); # __ for debug 126: rval = InpChar_(); 127: } 128: } 129: else if ( fno = 3 ) { # CONOUT 130: PrnChar_( _WrkVal[2] ); 131: rval = 0; 132: } 133: else if ( fno = 4 ) { # READ 134: var track; 135: track = _WrkVal + 4; 136: rval = BlkRead( track[0]*64 + _WrkVal[8] ); 137:#PrnVal( "\nTk:",track[0]); 138:#PrnVal( " Sec:", _WrkVal[8] ); 139: if ( rval = 0 ) { 140: PmpSetAdr( _PicDma ); 141: for ( i = 0; i < 128; i=i+1 ) { 142: MemWr( _SpiBuf[ i ] ); 143: } 144:#dump(_PicDma); 145:#if ( _WrkVal[8] = $37 ) { 146:# dump( $fa00 ); 147:#} 148: } 149: } 150: else if ( fno = 5 ) { # WRITE 151: var track; 152: track = _WrkVal + 4; 153: PmpSetAdr( _PicDma ); 154: i = MemRd(); # dummy 155: for ( i = 0; i < 128; i=i+1 ) { 156: _SpiBuf[ i ] = MemRd(); 157: } 158: rval = BlkWrite( track[0]*64 + _WrkVal[8] ); 159: } else { 160: PrnStr_( "\nFunc err" ); 161: } 162: PmpSetAdr( ProgWrk + 1 ); 163: MemWr( rval ); 164: 165: PmpOff(); 166: LATC[0] = $0000; # reset on 167: BusRelease(); 168: LATC[0] = $0001; # reset off 169: } 170:} 171: 172: 173:proc main() { 174: var i; 175: init(); 176: initPmp(); 177: initSpi(); 178: initSd(); 179: 180: if ( BlkRead( 0 ) <> 0) { 181: PrnStr_( "NG" ); 182: SetCsOff(); 183: } else { 184: SetCsOff(); 185: PmpOn(); 186: 187: PmpSetAdr( 0 ); 188: MemWr( $c3 ); 189: MemWr( ProgStart ); 190: MemWr( ProgStart / 256 ); 191: 192: PmpSetAdr( ProgStart ); 193: for ( i = 0; i< 128; i=i+1 ) { 194: MemWr( _SpiBuf[ i ] ); 195: } 196: dump( 0 ); 197: dump( ProgStart ); 198: LATC[0] = $0000; # reset on 199: BusRelease(); 200: LATC[0] = $0001; # reset off 201: PicSrv(); 202: } 203:} :run 0000 : C3 00 01 00 02 C3 06 EC 68 00 68 00 68 00 68 00 0010 : 68 00 68 00 68 00 68 00 68 00 68 00 68 00 68 00 0020 : 68 00 68 00 68 00 68 00 68 00 68 00 68 00 2D 00 0030 : 68 00 2D 00 68 00 86 00 C3 86 D8 00 86 00 2D 00 0040 : 68 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 0050 : 43 00 43 00 43 00 43 00 43 00 43 00 00 53 54 41 0060 : 54 20 20 20 20 43 4F 4D D1 22 04 0C 00 20 20 20 0070 : 20 20 20 20 20 20 20 20 00 00 00 00 00 00 E6 FA 0100 : 31 80 00 3E E9 32 00 00 21 5E 01 CD 4A 01 3E 04 0110 : 32 70 FF AF 32 73 FF 5F 57 21 00 E4 01 01 37 ED 0120 : 53 74 FF 79 32 78 FF C5 D5 E5 21 2E 01 76 E1 11 0130 : 80 FF EB 01 80 00 ED B0 EB D1 C1 05 CA 00 FA 0C 0140 : 79 FE 40 38 DE 0E 00 13 18 D5 3E 03 32 70 FF 7E 0150 : 23 B7 C8 32 72 FF EB 21 5B 01 76 EB 18 F1 0D 0A 0160 : 6C 6F 61 64 69 6E 67 2E 2E 2E 00 E5 E5 E5 E5 E5 0170 : E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 E5 loading... 64k CP/M Version 2.2 COPYRIGHT (C) 1979, DIGITAL RESEARCH a>dir A: ASM COM : BIOS ASM : CPM SYS : DDT COM A: DEBLOCK ASM : DISKDEF LIB : DSKMAINT COM : BCLOAD A: DUMP ASM : DUMP COM : ED COM : LOAD COM A: PIP COM : READ ME : STAT COM : SUBMIT COM A: XSUB COM a>ddt DDT VERS 2.2 -d 0100 01 BC 0F C3 3D 01 43 4F 50 59 52 49 47 48 54 20 ....=.COPYRIGHT 0110 28 43 29 20 31 39 38 30 2C 20 44 49 47 49 54 41 (C) 1980, DIGITA 0120 4C 20 52 45 53 45 41 52 43 48 20 20 20 20 20 20 L RESEARCH 0130 44 44 54 20 56 45 52 53 20 32 2E 32 24 31 00 02 DDT VERS 2.2$1.. 0140 C5 C5 11 30 01 0E 09 CD 05 00 C1 21 07 00 7E 3D ...0.......!..~= 0150 90 57 1E 00 D5 21 00 02 78 B1 CA 65 01 0B 7E 12 .W...!..x..e..~. 0160 13 23 C3 58 01 D1 C1 E5 62 78 B1 CA 87 01 0B 7B .#.X....bx.....{ 0170 E6 07 C2 7A 01 E3 7E 23 E3 6F 7D 17 6F D2 83 01 ...z..~#.o}.o... 0180 1A 84 12 13 C3 69 01 D1 2E 00 E9 0E 10 CD 05 00 .....i.......... 0190 32 5F 1E C9 21 66 1E 70 2B 71 2A 65 1E EB 0E 11 2_..!f.p+q*e.... 01A0 CD 05 00 32 5F 1E C9 11 00 00 0E 12 CD 05 00 32 ...2_..........2 01B0 5F 1E C9 21 68 1E 70 2B 71 2A 67 1E EB 0E 13 CD _..!h.p+q*g..... -^C a>


 ついでにブレッドボードの写真も貼っておきます(写真で見るとメッチャ汚い・・冷静に見たら肉眼で見ても汚いw)。
 使用しているICは Z84C0020PEC(Z80 20MHz:40-Pin DIP)、HM628128ALP-7(128Kbytes SRAM:32-Pin DIP)、PIC24FJ64GA004(44-Pin TQFP) の3個でTTL等は使っていません。右下の緑の基板はSDカードホルダ基板です。
 SDカードはSDHCタイプの16GBのものを使っています。

PicCPM実験用Z80ブレッドボード



[TOP] [ 前へ ] 連載記事 [ 次へ ]
nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

レトロマイコンZ80ボードの構想(その12)CP/M80 BIOS検討4 [Z80]

 前回の記事「レトロマイコンZ80ボードの構想(その11)CP/M80 BIOS検討3」でBUSACK/信号のチェックは省略可能なことが判り、Z80と接続する信号はほぼ決まったのでPICとZ80とのソフトインターフェースについて動作検証してみました。

 PIC側で使用するI/O数を削減するため、Z80からのサービスコール時のHALTの脱出は NMI(またはINT)ではなく、RESETを使用することにします。

 NMIを使う場合は66HのコードをRETNコードに書き換えてからHALTします。RESETの場合は0000Hから実行が開始するので0000HのコードをJP XXXXに書き換えてもいいのですが、処理簡略化(かつ高速化)のためにJP (HL):0E9H に書き換えます。

 NMI方式と比較し、スタック操作がなく、書き換えが1バイト(NMI方式は2バイト)なので若干ですが処理が簡易かつ高速になります(NMIのための制御出力が不要であることが最大のメリット)。
 ディメリットとしてはRESETにより割込み用FFと割り込みモードがクリアされるという点がありますが、今回のように割込みを使わない場合は問題ありません。

 Z80がPIC側のサービスを受ける際の手順の概要としては次のようになります(下記のサンプルソースでは「PIC_SRV」部分)
  1. ワークエリアにサービスIDとサービス処理に必要なパラメータを設定
  2. 0000Hのコード(多くの場合、0C3H(=JP XXXX)))を保存
  3. HLレジスタにHALTの次のアドレスを設定
  4. 0000Hに0E9H(=JP (HL))を設定
  5. HALT実行
  6. 0000Hを元のコードに戻す
  7. ワークエリアからPICが設定した処理結果を参照

 PIC側の処理手順は次のようになります(下記のサンプルソースでは「 PicSrv()」部分)
  1. Z80がHALT状態になるまで待つ
  2. BUSREQ/をアクティブ(アサート)にしBUSの制御権を得る
  3. サービスIDとパラメータに従い処理し、結果をワークエリアに保存する
  4. RESETをアクティブにする
  5. BUSREQ/をインアクティブ(ディアサート)にする
  6. RESETをインアクティブにする


 動作検証としてCP/MのBIOSにもあるコンソール入出力関連の処理を実験した際の信号サンプルが下のキャプチャです。
 キーセンスの繰り返し処理の部分を1周期分抜き出したものです。

 Z80側はキー入力状態をチェックする短いループ処理であるということもありますが、PIC側の処理時間(BUSREQ/がLOWの期間)がZ80の3倍弱程度(PIC側の7割程度が外部メモリアクセスの処理)になっています。

 Z80は16MHz、PICは32MHzで動作しています。PIC側はPMPを使っているものの内部のメモリに展開しながらの外部メモリアクセスなので時間がかかっていますが、PIC側もアセンブラで書けば外部メモリアクセス部を数倍程度高速化できると思います。

Z80からPICへのサービス要求処理時の信号サンプル


 Z80側のソースは次のとおりです。
 「Start」と表示後、キー入力状態をチェックし、キー入力があった場合には入力データを読込み16進で表示します。

RESETによるBIOS処理実験(Z80:アセンブラ)
; PIC service call test for CP/M BIOS ; Ver 0.01 2018/03/10 by skyriver 000D CR EQU 13 000A LF EQU 10 FF00 PICSRV EQU 0FF00h ; AP area FFF0 PICWRK EQU 0FFF0H ; PIC service work area 0080 SECSIZE EQU 128 ; sector size 0000 FC_SYSLOAD EQU 0 ; EXIT CP/M 0001 FC_CONST EQU 1 ; CONST 0002 FC_CONIN EQU 2 ; CONIN 0003 FC_CONOUT EQU 3 ; CONOUT 0004 FC_READ EQU 4 ; READ SD Card 0005 FC_WRITE EQU 5 ; WRITE SD Card 0006 FC_PIC EQU 6 ; PIC control ; ++++ work area for PIC Interface FFF0 FuncNo equ PICWRK ; ds 1 : function No FFF1 RetVal EQU PICWRK + 1 ; ds 1 : return value FFF2 FCData equ PICWRK + 2 ; ds 1 : conout data FFF3 SelDk equ PICWRK + 3 ; ds 1 FFF4 Track equ PICWRK + 4 ; ds 2 FFF6 DmaAdr equ PICWRK + 6 ; ds 2 FFF8 Sector equ PICWRK + 8 ; ds 1 0000' ASEG ORG 0100H .PHASE PICSRV .Z80 FF00 31 0100 TEST: LD SP,0100h FF03 21 FF27 LD HL,MSG FF06 CD FF1D CALL PRNMSG FF09 CD FF54 LOOP: CALL CONST FF0C B7 OR A FF0D 28 FA JR Z,LOOP FF0F 21 FF31 LD HL,MSGP FF12 CD FF1D CALL PRNMSG FF15 CD FF58 CALL CONIN FF18 CD FF3A CALL PRNHEX FF1B 18 EC JR LOOP FF1D 7E PRNMSG: LD A,(HL) FF1E B7 OR A FF1F C8 RET Z FF20 4F LD C,A FF21 CD FF5C CALL CONOUT FF24 23 INC HL FF25 18 F6 JR PRNMSG FF27 0D 0A 53 74 MSG: DB CR,LF,'Start',CR,LF,0 FF2B 61 72 74 0D FF2F 0A 00 FF31 20 50 75 73 MSGP: DB ' Pushed:',0 FF35 68 65 64 3A FF39 00 FF3A PRNHEX: FF3A 47 LD B,A FF3B CB 3F SRL A FF3D CB 3F SRL A FF3F CB 3F SRL A FF41 CB 3F SRL A FF43 CD FF47 CALL PRNHNIB FF46 78 LD A,B FF47 PRNHNIB: FF47 E6 0F AND 00FH FF49 C6 30 ADD A,'0' FF4B FE 3A CP '9'+1 FF4D 38 02 JR C,PRNHNIB2 FF4F C6 07 ADD A,'A' - '0' - 10 FF51 PRNHNIB2: FF51 4F LD C,A FF52 18 08 JR CONOUT ; ; check console key data ; A -> 0ffh:data exist 00h:none FF54 CONST: FF54 3E 01 LD A,FC_CONST FF56 18 0C JR PIC_SRV ; ; input console ; A -> key data FF58 CONIN: FF58 3E 02 LD A,FC_CONIN FF5A 18 08 JR PIC_SRV ; ; out console ; C <- data FF5C CONOUT: FF5C 79 LD A,C FF5D 32 FFF2 LD (FCData),A FF60 3E 03 LD A,FC_CONOUT FF62 18 00 JR PIC_SRV ; ; PIC Service Function ; A <- service no ; A -> return value FF64 PIC_SRV: FF64 C5 PUSH BC FF65 E5 PUSH HL FF66 32 FFF0 LD (FuncNo),A FF69 3A 0000 LD A,(0000h) FF6C 47 LD B,A FF6D 21 FF76 LD HL,NEXT_HALT FF70 3E E9 LD A,0E9H ; ope-code : JP (HL) FF72 32 0000 LD (0000H),A FF75 76 HALT FF76 NEXT_HALT: FF76 78 LD A,B FF77 32 0000 LD (0000H),A FF7A 3A FFF1 LD A,(RetVal) FF7D E1 POP HL FF7E C1 POP BC FF7F C9 RET END


 PIC側では上記のZ80のアセンブル結果のバイナリファイルを MemWr() での書込み処理に変換するツールを作り、picleソース内に取り込んでいます。
 PIC側でのリスト表示と実行結果を下記に示します。
 末尾にある「pushed」の部分は '1'、'2'、'3'のキー入力をした結果です。

RESETによるBIOS処理実験(PIC側:picle言語)
:l 1:# Test Reset I/F to Z80 by skyriver 2018/03/10 2: 3:use LibCpm; 4: 5:var ProgStart,ProgWrk,_WrkVal; 6: 7: 8:proc InitProg() { 9: ProgStart = $ff00; # Prog start addr 10: ProgWrk = $fff0; # Prog work addr 11: _WrkVal = Array_(ArIdx); 12: ArIdx = ArIdx + 5; 13: 14: PmpOn(); 15: 16: PmpSetAdr( 0 ); 17: MemWr( $c3 ); 18: MemWr( $00 ); 19: MemWr( $ff ); 20: 21: PmpSetAdr( ProgStart ); 22: 23: MemWr( $31 ); MemWr( $00 ); MemWr( $01 ); MemWr( $21 ); MemWr( $27 ); 24: MemWr( $ff ); MemWr( $cd ); MemWr( $1d ); MemWr( $ff ); MemWr( $cd ); 25: MemWr( $54 ); MemWr( $ff ); MemWr( $b7 ); MemWr( $28 ); MemWr( $fa ); 26: MemWr( $21 ); MemWr( $31 ); MemWr( $ff ); MemWr( $cd ); MemWr( $1d ); 27: MemWr( $ff ); MemWr( $cd ); MemWr( $58 ); MemWr( $ff ); MemWr( $cd ); 28: MemWr( $3a ); MemWr( $ff ); MemWr( $18 ); MemWr( $ec ); MemWr( $7e ); 29: MemWr( $b7 ); MemWr( $c8 ); MemWr( $4f ); MemWr( $cd ); MemWr( $5c ); 30: MemWr( $ff ); MemWr( $23 ); MemWr( $18 ); MemWr( $f6 ); MemWr( $0d ); 31: MemWr( $0a ); MemWr( $53 ); MemWr( $74 ); MemWr( $61 ); MemWr( $72 ); 32: MemWr( $74 ); MemWr( $0d ); MemWr( $0a ); MemWr( $00 ); MemWr( $20 ); 33: MemWr( $50 ); MemWr( $75 ); MemWr( $73 ); MemWr( $68 ); MemWr( $65 ); 34: MemWr( $64 ); MemWr( $3a ); MemWr( $00 ); MemWr( $47 ); MemWr( $cb ); 35: MemWr( $3f ); MemWr( $cb ); MemWr( $3f ); MemWr( $cb ); MemWr( $3f ); 36: MemWr( $cb ); MemWr( $3f ); MemWr( $cd ); MemWr( $47 ); MemWr( $ff ); 37: MemWr( $78 ); MemWr( $e6 ); MemWr( $0f ); MemWr( $c6 ); MemWr( $30 ); 38: MemWr( $fe ); MemWr( $3a ); MemWr( $38 ); MemWr( $02 ); MemWr( $c6 ); 39: MemWr( $07 ); MemWr( $4f ); MemWr( $18 ); MemWr( $08 ); MemWr( $3e ); 40: MemWr( $01 ); MemWr( $18 ); MemWr( $0c ); MemWr( $3e ); MemWr( $02 ); 41: MemWr( $18 ); MemWr( $08 ); MemWr( $79 ); MemWr( $32 ); MemWr( $f2 ); 42: MemWr( $ff ); MemWr( $3e ); MemWr( $03 ); MemWr( $18 ); MemWr( $00 ); 43: MemWr( $c5 ); MemWr( $e5 ); MemWr( $32 ); MemWr( $f0 ); MemWr( $ff ); 44: MemWr( $3a ); MemWr( $00 ); MemWr( $00 ); MemWr( $47 ); MemWr( $3e ); 45: MemWr( $e9 ); MemWr( $32 ); MemWr( $00 ); MemWr( $00 ); MemWr( $21 ); 46: MemWr( $76 ); MemWr( $ff ); MemWr( $76 ); MemWr( $78 ); MemWr( $32 ); 47: MemWr( $00 ); MemWr( $00 ); MemWr( $3a ); MemWr( $f1 ); MemWr( $ff ); 48: MemWr( $e1 ); MemWr( $c1 ); MemWr( $c9 ); 49:} 50: 51: 52:proc PicSrv() { 53: var i,fno,rval; 54: 55: while (1) { 56: while ( LATB[-1] & 8 ) {} # wait halt 57: PmpOn(); 58: PmpSetAdr( ProgWrk ); 59: fno = MemRd(); # dummy 60: for ( i=0; i<9; i=i+1 ) { 61: _WrkVal[i] = MemRd(); 62: } 63: fno = _WrkVal[0]; # function No 64: if ( fno = 1 ) { # CONST 65: if ( InpChk_() ) { 66: rval = $ff; 67: } else { 68: rval = 0; 69: } 70: } 71: else if ( fno = 2 ) { # CONIN 72: if ( InpChk_() ) { 73: rval = InpChar_(); 74: if ( rval = $1b ) { # if ESC then end 75: exit(); 76: } 77: } else { 78: PrnChar_('x'); # __ for debug 79: rval = InpChar_(); 80: } 81: } 82: else if ( fno = 3 ) { # CONOUT 83: PrnChar_( _WrkVal[2] ); 84: rval = 0; 85: } else { 86: PrnStr_( "\nFunc err" ); 87: } 88: PmpSetAdr( ProgWrk + 1 ); 89: MemWr( rval ); 90: 91: PmpOff(); 92: LATC[0] = $0000; # reset on 93: BusRelease(); 94: LATC[0] = $0001; # reset off 95: } 96:} 97: 98: 99:proc main() { 100: init(); 101: initPmp(); 102: InitProg(); 103: 104: dump( 0 ); 105: dump( ProgStart ); # dump & PmpOff 106: LATC[0] = $0000; # reset on 107: BusRelease(); 108: LATC[0] = $0001; # reset off 109: 110: PicSrv(); 111:} :run 0000 : C3 00 FF 43 00 43 00 43 00 43 00 43 00 43 00 43 0010 : 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 43 0020 : 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 43 0030 : 00 43 00 43 00 43 00 2D B0 00 64 3A 20 43 C6 2E 0040 : DB 43 00 43 00 43 00 43 00 43 00 43 00 43 00 43 0050 : 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 43 0060 : 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 43 0070 : 00 43 00 43 00 43 00 43 00 43 00 43 00 43 00 43 FF00 : 31 00 01 21 27 FF CD 1D FF CD 54 FF B7 28 FA 21 FF10 : 31 FF CD 1D FF CD 58 FF CD 3A FF 18 EC 7E B7 C8 FF20 : 4F CD 5C FF 23 18 F6 0D 0A 53 74 61 72 74 0D 0A FF30 : 00 20 50 75 73 68 65 64 3A 00 47 CB 3F CB 3F CB FF40 : 3F CB 3F CD 47 FF 78 E6 0F C6 30 FE 3A 38 02 C6 FF50 : 07 4F 18 08 3E 01 18 0C 3E 02 18 08 79 32 F2 FF FF60 : 3E 03 18 00 C5 E5 32 F0 FF 3A 00 00 47 3E E9 32 FF70 : 00 00 21 76 FF 76 78 32 00 00 3A F1 FF E1 C1 C9 Start Pushed:31 Pushed:32 Pushed:33



[TOP] [ 前へ ] 連載記事 [ 次へ ]
nice!(1)  コメント(0) 
共通テーマ:趣味・カルチャー

レトロマイコンZ80ボードの構想(その11)CP/M80 BIOS検討3 [Z80]

 前回の記事「レトロマイコンZ80ボードの構想(その10)CP/M80 BIOS検討2」で書いたようにPIC側で使用するI/O数を節約するため BUSACK/ のチェックを省略できるか確認してみました。

 まずは Z80 の仕様を確認するため、本棚から「保存版・Z80の徹底研究」の特集記事が掲載されているトラ技を引っ張り出してきました ^^

トラ技 Z80保存版


 このトラ技には「サッポロシティ・スタンダードのすべて」の特別企画も掲載されていて思わず読みふけってしまいましたw
 広告付きで保存しているので MZ-80C の広告も載っています ^^

 「応用CP/M」等の本もずっと持っていたのですが数年前に捨ててしまったので今はありません ^^;(CP/Mを動かそうとする日が来るとは思ってもいなかった・・)

 BUSREQ/の話に戻るとBUSREQ/は各マシンサイクルの最後のステート(ここでいうステートはクロック1周期分)の立上りでサンプリングされ次のマシンサイクルでbusを開放すると記載されています。

 今回は HALT 状態の時にBUSREQ/をアクティブにするので最悪ケースはサンプリング直後にBUSREQ/を出した場合で5ステート分待てば問題ないはずです(HALT命令は4ステート)。

 但し、前回の実験でHALT状態では次の命令のフェッチを繰り返しているのでHALTの次にはNOP(これも4ステート)を置いておくことにします。

★2018/03/02 追記 {
 気になったのでHALTの次のコードの影響を確認してみました。具体的には

076h HALT ; 1 マシンサイクル、4 ステート
0f9h LD SP,HL ; 1 マシンサイクル、6 ステート

HALT命令を実行しHALT状態になった後、「LD SP,HL」のフェッチを行いますが、4 ステートでマシンサイクルを完了していました。マニュアルに書いてあった「HALT状態では内部でNOPを実行している」とはこのこと(M1サイクルもNOPと同じ)のようです。
 従ってHALTの後にNOPは不要ということになります。HALTの次のコードを実行していないのだから当然といえば当然ですね。
}

 Z80は16MHzで動かしているので5クロックは0.3125usになります。

 実際にBUSREQ/からBUSACK/までの時間を10回程、測定した結果が下表です。(ロジアナは100MHzサンプリングなので解像度は10ns)
 また、測定時のロジアナ画面のサンプルも貼っておきます。

表 BUSREQ/ -> BUSACK 応答時間測定結果
No. 1 2 3 4 5 6 7 8 9 10 Max
Time[us] 0.20 0.14 0.20 0.26 0.27 0.14 0.26 0.21 0.21 0.21 0.27


BUSREQ/ -> BUSACK/ 応答波形サンプル


 PIC24FJ64GA004のピンアサインも数ヶ所見直しました。
  • SDカード状態信号読込み
    BUSACK/の入力が不要になったのでSDカードの装着状態の入力に変更

  • SDカード用SDI
    SDカードからの出力信号なのでアドレス線とぶつかるのはまずい。抵抗を入れたりして調整可能だと思うけど不安定要素は少なくしたいのでNMI出力を廃止してSDカード用に変更

  • OneBitLoader
     PMD6と兼用にしていたが、データ線はZ80が出力状態にもなるのでローダー動作が不安定。とりあえずUARTのTXと兼用にした。ブートローダーを1線式ではなく、2線式にすればそのままUARTの通信を利用したローダーに変更可能(でも作業としては後回し)

ピンアサイン表(変更版)

★2018/05/05 変更 ピンアサイン表をアップデート
★2018/07/01 変更 ピンアサイン表をアップデート(OBL部更新)

 あれ・・BIOS検討という副題なのにBIOS検討まで進まなかった・・・^^;


[TOP] [ 前へ ] 連載記事 [ 次へ ]
nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー