2013.8.11
前へ
次へ
ホームページトップへ戻る

復活!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 &ltp16f886.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

前へ
次へ
ホームページトップへ戻る