******************************************************************************
* 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