Blame | Last modification | View Log | Download | RSS feed
;----------------------------------------------------------
; MACRO.INC
; PROGETTO: B1601
;
; Bit registro di stato / macro
;----------------------------------------------------------
; il file puo' essere incluso solo all'interno di GLOBAL.INC
.IFNDEF _GLOBAL_INC_
.EXIT "ERROR: This file cannot be included."
.ENDIF
; flag registro di stato CPU
PNFLAG .EQU 10000000B ; Negative flag
PVFLAG .EQU 01000000B ; Overflow flag
PMFLAG .EQU 00100000B ; Acc/Mem 8 bit flag
PXFLAG .EQU 00010000B ; Index 8 bit flag
PDFLAG .EQU 00001000B ; Decimal flag
PIFLAG .EQU 00000100B ; IRQ disable flag
PZFLAG .EQU 00000010B ; Zero flag
PCFLAG .EQU 00000001B ; Carry flag
PFALL .EQU PNFLAG+PVFLAG+PZFLAG+PCFLAG
.MNLIST
; attiva MEM/ACC 16 bit
ACC16: .MACRO
.MLIST
rep #PMFLAG
.LONGA on
.MNLIST
.ENDM
; attiva MEM/ACC 16 bit + CLC
ACC16CLC: .MACRO
.MLIST
rep #(PMFLAG.OR.PCFLAG)
.LONGA on
.MNLIST
.ENDM
; attiva MEM/ACC 16 bit + CLC + CLV
ACC16CV: .MACRO
.MLIST
rep #(PMFLAG.OR.PCFLAG.OR.PVFLAG)
.LONGA on
.MNLIST
.ENDM
; attiva MEM/ACC 8 bit
ACC08: .MACRO
.MLIST
sep #PMFLAG
.LONGA off
.MNLIST
.ENDM
ACC08SEC: .MACRO
.MLIST
sep #(PMFLAG.OR.PCFLAG)
.LONGA off
.MNLIST
.ENDM
; attiva INDEX 16 bit
INDEX16: .MACRO
.MLIST
rep #PXFLAG
.LONGI on
.MNLIST
.ENDM
; attiva INDEX 16 bit+CLC
INDEX16CLC: .MACRO
.MLIST
rep #(PXFLAG.OR.PCFLAG)
.LONGI on
.MNLIST
.ENDM
; attiva INDEX 16 bit+CLC+CLV
INDEX16CV: .MACRO
.MLIST
rep #(PXFLAG.OR.PCFLAG.OR.PVFLAG)
.LONGI on
.MNLIST
.ENDM
; attiva INDEX 8 bit
INDEX08: .MACRO
.MLIST
sep #PXFLAG
.LONGI off
.MNLIST
.ENDM
; attiva INDEX 8 bit
INDEX08VF: .MACRO
.MLIST
sep #(PXFLAG.OR.PVFLAG)
.LONGI off
.MNLIST
.ENDM
; attiva MEM/ACC/INDEX 16 bit
CPU16: .MACRO
.MLIST
rep #(PMFLAG.OR.PXFLAG)
.LONGA on
.LONGI on
.MNLIST
.ENDM
; attiva MEM/ACC/INDEX 16 bit + CLC
CPU16CLC: .MACRO
.MLIST
rep #(PMFLAG.OR.PXFLAG.OR.PCFLAG)
.LONGA on
.LONGI on
.MNLIST
.ENDM
; attiva MEM/ACC/INDEX 8 bit
CPU08: .MACRO
.MLIST
sep #(PMFLAG.OR.PXFLAG)
.LONGA off
.LONGI off
.MNLIST
.ENDM
; attiva MEM/ACC/INDEX 8 bit + SEC
CPU08SEC: .MACRO
.MLIST
sep #(PMFLAG.OR.PXFLAG.OR.PCFLAG)
.LONGA off
.LONGI off
.MNLIST
.ENDM
; attiva MEM/ACC/INDEX 8 bit + VF
CPU08VF: .MACRO
.MLIST
sep #(PMFLAG.OR.PXFLAG.OR.PVFLAG)
.LONGA off
.LONGI off
.MNLIST
.ENDM
LONG_OFF .MACRO
.MLIST
.LONGA off
.LONGI off
.MNLIST
.ENDM
LONG_ON .MACRO
.MLIST
.LONGA on
.LONGI on
.MNLIST
.ENDM
;----------------------------------------------------------
; MACRO DEFINIZIONE VARIABILI
;----------------------------------------------------------
; definisce un long-pointer (24 bit)
LP .MACRO
.DS 3
.ENDM
; definisce un intero a 32 bit
DD .MACRO
.LWORD
.ENDM
; definisce un intero a 64 bit
DQ .MACRO
.BLKL 2
.ENDM
;----------------------------------------------------------
; MACRO DEFINIZIONE JMP-TABLE
;----------------------------------------------------------
SYSFUNC .MACRO SFunc, LocFunc
.MNLIST
.IFNDEF SFunc
.EXIT "ERROR: <SFunc> not defined."
.ENDIF
.MLIST
.ABSOLUTE
.ORG (.LOW16.SFunc - JMPTOFS)
jsr LocFunc
rtl
.RELATIVE
.MNLIST
.ENDM
SYSJMP .MACRO SFunc, LocFunc
.MNLIST
.IFNDEF SFunc
.EXIT "ERROR: <SFunc> not defined."
.ENDIF
.MLIST
.ABSOLUTE
.ORG (.LOW16.SFunc - JMPTOFS)
jmp LocFunc
.RELATIVE
.MNLIST
.ENDM
;----------------------------------------------------------
; MACRO DEFINIZIONE RECORD/STRUCT
;----------------------------------------------------------
STRUCT .MACRO SName
.MLIST
_|SName| .SECTION page0,common,ref_only,offset 0 ;SName Struct
;.ABSOLUTE
;.ORG 0
.MNLIST
.ENDM
LSTRUCT .MACRO SName
.MLIST
_|SName| .SECTION common,ref_only,offset 0 ;SName Struct
.MNLIST
.ENDM
ESTRUCT .MACRO SName
.MLIST
|SName|SIZE .DS 0
;.RELATIVE
.ENDS
.MNLIST
.ENDM
.IFDEF _ACIA_INC_
SPISR .MACRO num
.MLIST
.IFZ num
k .SET 0
SOBUFADDR .SET SPOUTBUFF
SIBUFADDR .SET SPINBUFF
.ELSE
k .SET 4
SOBUFADDR .SET SPOUTBUFF2
SIBUFADDR .SET SPINBUFF2
.ENDIF
ldy .ABS.ACIAISR+k ; interrupt status reg. (clear bit 3,4,5)
lda .ABS.ACIACSR+k ; control status register
;sty spisr+k ; save interrupt status reg.
sta spcsr+k ; save control status reg.
tya ; Y=status reg.
lsr a ; test RDRF bit
bcc ?lin ; go to test control lines
ldx .ABS.ACIARDR+k ; fetch rx data (clear int. status bits 0,1,2)
bit spstat+k ; rx error pending?
bmi ?lin ; yes, discard received data & test ctr. lines
and #00000011B ; 1: overrun/frame error, 2: parity error
bit spcsr+k ; test control status reg. bit 7: FE
bpl ?nof ; no framing error
ora #00000100B ; set framing error bit...
and #$FE ; ...and clear overrun error
?nof: cmp #0
beq ?rxok ; no rx error
ora #10000000B ; set rx error bit
bra ?sst ; set stus reg. & discard received data
?rxok: txa ; A=received data
INDEX16
.MLIST
ldx ibufcnt+k ; count of bytes stored in input buffer
bit spmode+k ; test if handshake is active
bpl ?chk ; bit 7=0 -> no handshake so check input buff.
bvs ?tst ; bit 6=1 -> hardware handshake
cmp #SPXON ; received an XON control byte?
bne ?xoff ; no, check if received an XOFF
lda #$40 ; received an XON: clear local pause flag
trb sppause+k ; bit 6=0 -> local pause off (resume tx)
bra ?cnt ; discard received data
?xoff: cmp #SPXOFF ; received an XOFF control byte?
bne ?tst ; no, check condition for remote pause
lda #$40 ; set local pause flag
tsb sppause+k ; bit 6=1 -> local pause on (stop tx operation)
bra ?cnt ; discard received data
?tst: cpx icntmax+k ; check input buff. for remote pause condition
bcc ?str ; below guard limit: store data
bit sppause+k ; remote pause is already on ?
bmi ?chk ; yes, so check input buffer
xba ; B = received data
bit spmode+k ; test handshake type
bvs ?rtsh ; bit 6=1 -> hardware handshake so set RTS=1
lda #SPXOFF ; send an XOFF to remote terminal
sta spout+k ; XOFF sending deffered until TDRE is set
bra ?xba ; check input buffer
?rtsh: lda spfr+k ; hardware handshake...
ora #10000001B ; ...set RTS=1
sta .ABS.ACIAFR+k ; update format register
lda #$80 ; set remote pause
tsb sppause+k ; bit 7=1 -> remote pause on
?xba: xba ; A = received data
?chk: cpx #SIBUFSIZ ; left room in input buffer?
bcc ?str ; yes, store received byte
lda #$C0 ; set bit 7: rx error, bit 6: rx overflow
?sst: sta spstat+k ; set status register
bra ?cnt ; discard received data
?str: inx ; now store received data
stx ibufcnt+k ; update bytes count
ldx ibuftail+k ; pointer to rx tail queue
sta >SIBUFADDR,x
inx ; update tail pointer
CPU16
.MLIST
txa
and #(SIBUFSIZ-1) ; circular queue
sta ibuftail+k
?cnt: CPU08 ; continue...
.MLIST
?lin: lda spcsr+k ; get control lines status
and #00111011B ; mask lines level
bit #00001000B ; check DSR line level
beq ?lin2 ; DSR is low
ora #01000000B ; DSR is high
?lin2: asl a ; 7:DSR, 6:CTS, 5:DCD, 2:DTR, 1:RTS
sta splin+k ; save lines level
;tya
bit spmode+k ; test for active handshake
bpl ?cnt2 ; no handshake, so ignore CTS/DCD trans.
bvc ?cnt2 ; softw. handshake, so ignore CTS/DCD trans.
;bit #00001000B ; change state on DSR line?
;beq ?cts ; no, go to check CTS line
;ldx #00100000B ; remote disconnession flag
;lda #00001000B ; check DSR line level
;bit spcsr+k
;beq ?dsrl ; DSR line at low level
;txa ; remote disconnession
;tsb spstat+k ; set status register
;bra ?cts
;?dsrl: ;txa ; remote terminal ready
;trb spstat+k ; set status register
;?cts:
lda spmode+k
lsr a ; check if uplink handshake (RTS/DCD control)
tya ; A=interrupt status reg.
bcs ?dcd ; yes, so check DCD line (uplink cable)
bit #00100000B ; change state on CTS line?
beq ?chkt ; no, so check TDRE flag
lda #00100000B ; check CTS line level
bra ?lvl
?dcd: bit #00010000B ; change state on DCD line?
beq ?chkt ; no, so check TDRE flag
lda #00010000B ; check DCD line level
?lvl: ldx #$40 ; local pause flag
bit spcsr+k
beq ?clp ; CTS (or DCD) = low so clear local pause
txa ; CTS (or DCD) = high so set local pause
tsb sppause+k
bra ?cnt2
?clp: txa
trb sppause+k
?cnt2: tya
?chkt: asl a ; check TDRE bit
bpl ?end ; TDRE=0: can't transmit at this time
lda spout+k ; pending an XON/XOFF sending?
beq ?cklp ; no... check local pause flag
sta .ABS.ACIATDR+k ; send XON/XOFF
stz spout+k ; clear XON/XOFF flag
cmp #SPXOFF
beq ?srp ; sent an XOFF
lda #$80 ; sent an XON: clear remote pause flag
trb sppause+k ; bit 7 = 0 -> remote pause off
?end: rts ; done
?srp: lda #$80 ; set remote pause flag
tsb sppause+k
rts
?cklp: bit sppause+k ; local pause is set ?
bvs ?end ; yes, no tx possible at this time
;bit spcsr+k ; check if remote terminal is ready
;bmi ?end ; not ready, skip tx
INDEX16
.MLIST
ldx obufcnt+k ; count of bytes in output buffer
beq ?done ; output buffer is empty: nothing to send
dex ; update count
stx obufcnt+k
ldx obufhead+k ; pointer to head of out buffer
lda >SOBUFADDR,x ; get data from output buffer
sta .ABS.ACIATDR+k ; send data
inx ; update head pointer
CPU16
.MLIST
txa
and #(SOBUFSIZ-1) ; circular queue
sta obufhead+k
?done: CPU08
.MLIST
rts
.ENDM
SPGETB .MACRO num
.MLIST
.IFZ num
k .SET 0
SIBUFADDR .SET SPINBUFF
.ELSE
k .SET 4
SIBUFADDR .SET SPINBUFF2
.ENDIF
sei ; disable interrupt
sec ; assume error
stx sptmp ; save X reg.
lda spstat+k ; rx pending error?
bmi ?done ; yes, exit
lda #0 ; assume no data available
tay ; Y = 0
INDEX16
.MLIST
ldx ibufcnt+k ; available new data?
beq ?done ; input queue is empty (exit with CF=1, A=0)
dex ; update count
stx ibufcnt+k
ldx ibufhead+k ; head input buffer pointer
lda >SIBUFADDR,x ; get byte from queue
inx ; update head pointer
cpx #SIBUFSIZ
bcc ?upd
tyx ; circular queue
?upd: stx ibufhead+k
bit sppause+k ; remote pause is on?
bpl ?ok ; no
ldx ibufcnt+k
cpx icntmin+k ; can clear remote pause?
bcs ?ok ; no
bit spmode+k ; handshake is on?
bpl ?ok ; no
xba ; save data
bvs ?hw ; hardware handshake
lda #SPXON ; software handshake: send an XON
bit .ABS.ACIACSR+k ; check TUR bit
bvc ?def ; can't send an XON at this time
sta .ABS.ACIATDR+k ; send now an XON
bra ?crp ; clear remote pause flag
?def: sta spout+k ; XON is deffered
bra ?xba
?hw: lda spfr+k ; hardware handshake: set RTS=0
sta .ABS.ACIAFR+k
?crp: lda #$80
trb sppause+k ; clear remote pause flag
?xba: xba ; recover data
?ok: clc
?done: INDEX08
.MLIST
ldx sptmp ; restore X reg.
cli
rts ; CF=1 & A=0 mean: no data available
.ENDM
SPPUTB .MACRO num
.MLIST
.IFZ num
k .SET 0
SOBUFADDR .SET SPOUTBUFF
.ELSE
k .SET 4
SOBUFADDR .SET SPOUTBUFF2
.ENDIF
sei ; disable interrupt
stx sptmp ; save X reg.
ldy #0 ; Y = 0
INDEX16
.MLIST
ldx obufcnt+k
cpx #SOBUFSIZ ; output buffer is full?
bcc ?str ; no, store byte
bit splin+k
bpl ?done ; exit with CF=1, Y=0: output buffer is full
dey
bra ?done ; exit with CF=1, Y=$FF: remote terminal off
?str: inx ; update count
stx obufcnt+k
ldx obuftail+k ; output buffer tail pointer
sta >SOBUFADDR,x ; store byte in output buffer
inx ; update tail pointer
cpx #SOBUFSIZ
bcc ?upd
tyx ; circular queue
?upd: stx obuftail+k
bit .ABS.ACIACSR+k ; check TUR bit: try to free output buffer
bvc ?ok ; can't send now: send by ISR
xba ; save data
lda spout+k ; XON/XOFF send pending?
beq ?snd ; no
sta .ABS.ACIATDR+k ; send an XON/XOFF
cmp #SPXON
bne ?xon
lda #$80
tsb sppause+k ; set remote pause
stz spout+k ; clear XOFF flag
bra ?xba ; done
?xon: lda #$80
trb sppause+k ; clear remote pause
stz spout+k ; clear XON flag
bra ?xba ; done
?snd: bit sppause+k
bvs ?xba ; local pause is on, can't send at this time
ldx obufcnt+k
beq ?xba ; output buffer is empty
dex ; update count
stx obufcnt+k
ldx obufhead+k
lda >SOBUFADDR,x ; get data from output buffer
sta .ABS.ACIATDR+k ; send data
inx ; update head pointer
cpx #SOBUFSIZ
bcc ?upd2
tyx ; circular queue
?upd2: stx obufhead+k
?xba: xba ; return A = sent data
?ok: clc ; no error
?done: INDEX08
.MLIST
ldx sptmp ; restore X reg.
cli
rts
.ENDM
.ENDIF