Subversion Repositories MB01 Project

Rev

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