Thursday, December 17, 2009

SCIDRV.ASM

******************************************************************************
*                       S C I   D R I V E R   M O D U L E                     *
*                                                                             *
*******************************************************************************

isrrtn    equ    $360        ; Address of Common Interrupt Exit routine

SCIINTLV  equ    5           ; SCI Interrupt Level
SCIINTV   equ    $3A         ; SCI Interrupt Vector

QMCR      equ    $FC00
QILR      equ    $FC04       ; QSM Interrupt Levels Register
QIVR      equ    $FC05       ; QSM Interrupt Vector Register

SCCR0     equ    $FC08       ; SCI Control Register 0
SCCR1     equ    $FC0A       ; SCI Control Register 1
SCSR      equ    $FC0C       ; SCI Status Register
SCDR      equ    $FC0E       ; SCI Data Register

*******************************************************************************
*  SCCR1 REGISTER FIELDS                                                      *
*******************************************************************************

SRK       equ    $01         ; Send Break
RWU       equ    $02         ; Receiver Wakeup
RE        equ    $04         ; Receiver Enable
TE        equ    $08         ; Transmitter Enable
RIE       equ    $20         ; Receiver Interrupt Enable
TIE       equ    $80         ; Transmitter Interrupt Enable

*******************************************************************************
*  SCI STATUS REGISTER FIELDS                                                 *
*******************************************************************************

RDRF      equ    $40         ; Receive Data Register Full
TDRE      equ    $01         ; Transmit Data Register Empty (high byte of $0100)

*******************************************************************************
*  SCI DRIVER EQUATES                                                         *
*******************************************************************************

INTS_OFF  equ    $00E0       ; Disable interrupts
SCIINTON  equ    (SCIINTLV<<5+$FF1F) ; Enable interrupts at SCIINTLV (2)
BR9600    equ    $37         ; SCCR0(0-12) setting for 9600 Baud

          PAGE
*******************************************************************************
*                                                                             *
*                       S C I   I N P U T   D R I V E R                       *
*                                                                             *
*******************************************************************************

sciidrv:  orp    #INTS_OFF   ; Turn off interrupts while enabling SCI
          ldab   #$F
          tbek               ; EK = F (K=$Fxxx)

          ldd    #$008A
          std    QMCR        ; Set IARB=10 for intermodule bus arbitration

          ldd    QILR        ; Get content of QSM Interrupt Levels Register
          anda   #$E8        ; Clear out ILSCI field
          oraa   #SCIINTLV   ; Set SCI interrupt level in ILSCI field
          ldab   #SCIINTV     ; Load SCI Interrupt Vector #
          std    QILR        ; Update QILR

          ldd    #RIE+RE+TE  ; Receiver enabled with interrupts active,
                             ; Transmitter enabled without interrupts,
                             ; 1 Start Bit, 1 Stop Bit, 8 Data Bits
          std    SCCR1       ; Set up SCI operating conditions
          ldd    #BR9600     ; Set up 9600 baud rate
          std    SCCR0

rdclr:    ldd    SCSR        ; Get current status of SCI
          bitb   #RDRF       ; See if receive data ready
          beq    scirdy      ; if not SCI is a
          ldab   SCDR        ; Read input data
          bra    rdclr       ; Loop until clear
scirdy:   andp   #$FF1F      ; Turn interrupts on again

inloop:   ldab   #1          ; bank 1
          tbek               ; EK = 1
          tbxk               ; XK = 1 (K=$11xx)
          ldab   #SCIISEMA
          ldaa   #MCX_WAIT   ; Wait for input character
          swi

          ldaa   inchar      ; Get input character captured by isr
          ldx    #EQ3src     ; Move it to safe place
          staa   0,x
          ldab   #SCIIQ      ; Then move the character into SCIIQ
          ldaa   #MCX_ENQUEUE_W
          swi

          bra    inloop      ; Loop forever

          PAGE
*******************************************************************************
*                                                                             *
*                     S C I   O U T P U T   D R I V E R                       *
*                                                                             *
*******************************************************************************

sciodrv:  ldab   #$F
          tbek               ; EK=F  (K=$Fxxx)
          ldab   #1
          tbxk               ; XK=1  (K=$F1xx)

scioloop: ldx    #DQ4dest
          ldab   #SCIOQ      ; Get next character from SCIOQ and put it into
          ldaa   #MCX_DEQUEUE_W  ; DQ4dest as temporary location
          swi

          ldab   0,x         ; Get the character
          cmpb   #$0A        ; New Line?
          bne    notnl       ; Branch if not "\n"
          ldd    SCSR        ; Get SCI status
          ldaa   #$0D
          staa   SCDR+1      ; Output a "\r"
          ldd    #RIE+RE+TE+TIE
          std    SCCR1       ; Enable transmitter interrupts
;         ldab   #RIE+RE+TE+TIE
;         stab   SCCR1+1     ; Enable transmitter interrupts

          ldab   #SCIOSEMA   ; Wait for it to be output completely
          ldaa   #MCX_WAIT
          swi

notnl:    ldd    SCSR        ; Read status
          ldaa   0,x         ; Get character to output
          staa   SCDR+1      ; Output it
          ldd    #RIE+RE+TE+TIE
          std    SCCR1       ; Enable transmitter interrupts
;         ldab   #RIE+RE+TE+TIE
;         stab   SCCR1+1     ; Enable transmitter interrupts

          ldab   #SCIOSEMA   ; Wait for it to be output completely
          ldaa   #MCX_WAIT
          swi

          bra    scioloop    ; Loop forever

          PAGE
*******************************************************************************
*                                                                             *
*           S C I   I N T E R R U P T   S E R V I C E   R O U T I N E         *
*                                                                             *
*******************************************************************************

pshsema   macro
          ldab   #\1
          orp    #INTS_OFF
          lde    $06,x
          stab   e,z
          incw   $06,x
          andp   #SCIINTON
          endm

sciisr:   orp    #INTS_OFF   ; Save the interrupt context
          pshm   d,e,x,y,z,k
          ldab   #1
          tbek               ; EK=1  (K=$1xxx)
          tbyk               ; YK=1  (K=$1x1x)
          tbzk               ; ZK=1  (K=$1x11)
          clrb
          tbxk               ; XK=0  (K=$1011)
          ldx    $0000       ; x = [$10000]
          tst    $000A
          bne    notlvl0
          ldy    $0004       ; y = [$10004]
          sts    8,y         ; [y+8] = SP
          lds    $14,x       ; SP = [X+20]
notlvl0:  inc    $000A       ; [$1000A] = [$1000A]+1
          andp   #SCIINTON   ; Interrupts back on
          ldz    $12,x

          ldab   #$F         ; EK = F  (K=$Fx11)
          tbek
          ldab   #1
          tbxk               ; XK = 1  (K=$F111)
          ldx    #$0000      ;
          ldy    #inchar     ; y = &inchar

          ldd    SCCR1       ; If TDRE is set, see if SCCR1 has TIE set
          bitb   #TIE
          beq    notout      ; If not, this is not an output interrupt
          ldd    SCSR        ; Check SCI status register for TDRE
          bita   #TDRE
          beq    chkrd       ; TDRE not set
          ldd    #RIE+RE+TE  ; If so, this is a transmitter interrupt, turn
                             ;  TIE off now that the character is out
          std    SCCR1       ; Update SCCR1. That takes care of the output side

          ldd    SCSR        ; Now treat a possible input interrupt that is
                             ;  simultaneous with the output. Reread the status
          bitb   #RDRF       ; Check for RDRF set
          beq    noin        ; Branch if no input occurred
          ldd    SCDR        ; Yes it did. Read the input character
          andb   #$7F        ; Strip it to 7 bits
          stab   0,y         ; Store in temporary location (inchar)
          pshsema SCIISEMA   ; Put SCIISEMA into Signal List
noin:     ldaa   #SCIOSEMA   ; Now signal the SCI output semaphore
          jmp    isrrtn

notout:   ldd    SCSR        ; Read status again
chkrd:    bitb   #RDRF       ; See if this is an input interrupt. Check RDRF
          beq    notin       ; It is not an input interrupt. So what was it?
          ldd    SCDR        ; If it was an input interrupt, get the character
          andb   #$7F        ; Strip it to 7 bits
          stab   0,y         ; Store in temporary location (inchar)
                             ; That takes care of the input. Now see if there
                             ;  was a simultaneous output interrupt
          ldd    SCSR        ; Check SCI status register for TDRE
          bita   #TDRE
          beq    noout       ; TDRE not set
          ldd    SCCR1       ; If TDRE is set, see if SCCR1 has TIE set
          bitb   #TIE
          beq    noout       ; If not, this cannot be an output interrupt
          ldd    #RIE+RE+TE  ; If so, this is a transmitter interrupt, turn
                             ;  TIE off now that the character is out
          std    SCCR1       ; Update SCCR1
          pshsema SCIOSEMA   ; Signal SCI Output Semaphore

noout:    ldaa   #SCIISEMA   ; Now signal the input semaphore
          jmp    isrrtn

notin:    clra               ; This wasn't a recognizable SCI interrupt
          jmp    isrrtn

          PAGE
*******************************************************************************
*  SCI VECTOR                                                                 *
*******************************************************************************

          ORG    SCIINTV*2

          dc.w   sciisr

*******************************************************************************
*  SCI DRIVER DATA VARIABLES                                                  *
*******************************************************************************

          ORG    $003FD

inchar:   ds     1
DQ4dest:  ds     1
EQ3src:   ds     1

*******************************************************************************
*                                                                             *
*                       S C I   D R I V E R   M O D U L E                     *
*

No comments:

Post a Comment