復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります!
[第455回]
●「金麦」が届きました!
Y様から「金麦」が届きました。
Y様からは「E−80試作機が完成したお祝いに金麦を送ります」というメールをいただいておりました。
いやあ。
これは、これは。
とってもうれしいです。
実は連日の猛暑で我が家のストックが尽きかけておりましたので、近日中に購入しなければと思っていた矢先のことでした。
ですので、なおのこと有難いです。
Y様。一等うれしいプレゼントを有難うございました。
ええ。
もちろん
昨夜はさっそく金麦で乾杯いたしました。
●前回のプログラムには誤りがありました
前回のIPL(Initial Program Loader)が間違っています、というメールをいただきました。
アドレス0006 015D00 LD BC,$005D
では全部を転送できません、とのご指摘です。
うっかりしておりました。
ご指摘の通りです。
実はプログラムを修正してIPL本体が少し大きくなったのに、上の部分の値を直すのを忘れてしまいました。
このことには実際にPICにデータとして書き込む段階で、値がおかしいことに気がついてPICのほうは正しい値を書いたのですが、前回お見せしたリストはPICに書き込むために作っただけのものでしたから、直さないままでした。
これはやっぱり直しておかないといけませんね。
さっそく訂正いたしました。
●PIC16F886のプログラム
こちらがPIC16F886のプログラムです。
PIC16F886はMIDIの処理もしているのですが、今回の説明としてはその部分があると煩雑になりますから、MIDIの処理をしているところは省いてあります。
下のリストでは最後が途中で終わってしまっていますが、その続きはMIDIの処理をしているところです。
loadersetが前回お見せしたプログラムをRAMに書き込んでいるところですが、ややこしいことをしています。
それが[第453回]で説明しましたディップスイッチの値をRAMに書き込んでいるところです。
プログラムの処理に影響しない、前半部分が終わった後(アドレス000E)に書き込んでいます。
;;; for E-80 ;;; IPL & MIDI ;2012/12/15 ;2013/1/14 1/15 1/16 1/17 1/18 1/19 1/20 1/22 1/26 1/28 ;5/31 6/4 8/2 ; #include <p16f886.inc> __CONFIG _CONFIG1,_WDT_ON& _EC_OSC & _PWRTE_ON & _MCLRE_ON & _LVP_OFF __CONFIG _CONFIG2 ; ;EXT CLOCK 10MHz ;WDT period is normally 18ms ; ; cf=0 zf=2 f=1 w=0 ; ; rbfcnt equ 20 rbftop equ 21 rbfend equ 22 errmk equ 23 datawk equ 24 dcntr equ 25 tcntr equ 26 tcntr2 equ 27 tcntr3 equ 28 acntr equ 29 ; rbf equ 30;end=6f ; savew equ 70;=f0 in bank1 savests equ 71;=f1 in bank1 ; org 00 goto start ; org 04 goto int ; org 05 start clrf STATUS;bk0 movlw 0af;bit4,bit6=0 ,bit4 is also cpureset movwf PORTA;cpu()z8s180)reset pulse >6clock,3us movlw 60;bk3 movwf STATUS clrf ANSEL clrf ANSELH bcf STATUS,6;bk1 movlw 0c;ra2,ra3=in movwf TRISA clrf TRISB clrf TRISC ;baud rate set movlw 4;31250bps movwf SPBRG movlw 20 movwf TXSTA movwf PIE1;read int enable bcf STATUS,5 ;bank 0 movlw 90 movwf RCSTA clrf errmk clrf rbfcnt movlw rbf movwf rbftop movwf rbfend ;intset movlw 0c0 movwf INTCON ; ;initial loader go or nogo check movf PORTA,w andlw 0c btfsc STATUS,zf goto runcpu ; ;initial loader program set & run cpu ; ;movlw 78;=120 movlw 0e;=14 movwf dcntr clrf acntr clrf PORTC ; loaderset clrwdt movf acntr,w call table call loadersub decfsz dcntr,f goto loaderset movf PORTA,w andlw 0c;dipsw iorlw 30;30,34,38,3c call loadersub movlw 6a;=106 movwf dcntr loaderset2 clrwdt movf acntr,w call table call loadersub decfsz dcntr,f goto loaderset2 goto runcpu ; loadersub movwf PORTB;DATA set bcf PORTA,5;memwr nop bsf PORTA,5 incf acntr,f movf acntr,w andlw 3f movwf PORTC;A0-A5 set btfsc acntr,6 bsf PORTA,6;A6 set return ; ; z80 loader program table table addwf PCL,f ; retlw 21 retlw 0F retlw 00; LD HL,DTTOP retlw 11 retlw 80 retlw 0FF; LD DE,LDRTOP retlw 01 retlw 6a retlw 00; LD BC,$005D retlw 0ED retlw 0B0; LDIR retlw 0C3 retlw 80 retlw 0FF; JP LDRTOP ; retlw 00;dipswdata=000E ; ;dttop=000F retlw 31 retlw 00 retlw 00; LDRTOP:LD SP,$0000 retlw 3E retlw 88; LD A,88 retlw 0D3 retlw 0FB; OUT (FB),A retlw 3E retlw 0FF; LD A,FF retlw 0D3 retlw 0FA; OUT (FA),A retlw 3E; refresh off retlw 30 retlw 0ED retlw 39 retlw 36 retlw 0ED; memory wait off retlw 39 retlw 32 retlw 3E; memory bank set retlw 80 retlw 0ED retlw 39 retlw 3A retlw 0CD retlw 0C3 retlw 0FF; CALL LDSUB retlw 6F; LD L,A retlw 0CD retlw 0C3 retlw 0FF; CALL LDSUB retlw 67; LD H,A;HL=load top address retlw 0CD; retlw 0C3 retlw 0FF; CALL LDSUB retlw 5F; LD E,A retlw 0CD retlw 0C3; retlw 0FF; CALL LDSUB retlw 57; LD D,A;DE=load end address retlw 0CD retlw 0C3 retlw 0FF; CALL LDSUB retlw 4F; LD C,A retlw 0CD retlw 0C3 retlw 0FF; CALL LDSUB retlw 47; LD B,A;BC=JP address after loaded retlw 0C5; PUSH BC retlw 13; INC DE retlw 0EB; EX DE,HL retlw 0B7; OR A retlw 0ED retlw 52; SBC HL,DE retlw 0EB; EX DE,HL;DE=load bytes ; retlw 0CD retlw 0C3 retlw 0FF; LOOP:CALL LDSUB retlw 77;LD (HL),A retlw 23;INC HL retlw 1B;DEC DE retlw 7A; LD A,D retlw 0B3; OR E retlw 20 retlw 0F6; JR NZ,LOOP retlw 0E1; POP HL retlw 0E9; JP (HL) ; ;load subroutine retlw 3E retlw 04; LDSUB:LD A,04;bit2=L,bit3=H,bit0-4 are INVERT retlw 0D3 retlw 0FE; OUT (FE),A retlw 0DB retlw 0FE; LP1:IN A,(FE) retlw 0E6 retlw 0C0; AND C0 retlw 28 retlw 12; JR Z,LP3;no data retlw 0FE retlw 80; CP 80 retlw 20 retlw 0F6; JR NZ,LP1 retlw 0DB retlw 0FC; IN A,(FC) retlw 0F5; PUSH AF retlw 0AF; XOR A retlw 0D3 retlw 0FE; OUT (FE),A retlw 0DB retlw 0FE; LP2:IN A,(FE) retlw 0E6 retlw 40; AND 40 retlw 28 retlw 0FA; JR Z,LP2 retlw 0F1; POP AF retlw 0C9; RET retlw 0AF; LP3:XOR A;bit2=H,bit3=H retlw 0D3 retlw 0FE; OUT (FE),A retlw 0DB retlw 0FE; LP4:IN A,(FE) retlw 0E6 retlw 40; AND 40 retlw 28 retlw 0FA; JR Z,LP4 retlw 18 retlw 0D9; JR LDSUB ; runcpu bsf STATUS,5;bk1 movlw 0bf;RC6=out;others=in movwf TRISC movlw 4c;ra6,ra3,ra2=in movwf TRISA movlw 0ff movwf TRISB bcf STATUS,5;bk0 movwf PORTA;run cpu |
PICプログラムでは定数データはこのプログラムのようにretlwを使って記述するのが定番です。
table以下がデータテーブルであるとともにサブルーチンでもあります。
サブルーチンの先頭でプログラムカウンタ(下位レジスタ)にWの値を加算するところがミソです。
retlwはWレジスタに定数を入れてリターンする命令です。
メインプログラムの側でWレジスタをインクリメントしながらtableをcallすると、そのたびにテーブルの値が順にWレジスタに入ってメインプログラムに戻ってきます。
ということはtableをcallするとWの値は破壊されてしまいますから、実はテーブルを参照するためのカウンタは別に設けておいて(acntr)、そちらをインクリメントしながらtableをcallする直前にWレジスタにmovします。
こういうところがPICのマシン語プログラムの嫌われるところなのですが、まあもともとマシン語なんてものはそういうものなのですから、慣れてしまえばそれほど苦にはなりません。
acntrをインクリメントしているところはloadersubにあります。
なおWは8ビットレジスタですから最大255個のデータまでしか扱うことができません。
それより大きいデータは同じ方法で複数個のテーブルに分けて扱います。
ワンボードマイコンでCP/Mを![第455回]
2013.8.11upload
前へ
次へ
ホームページトップへ戻る