Fix register r/w timing

This commit is contained in:
Colin Leroy-Mira
2023-10-09 22:03:08 +02:00
committed by Oliver Schmidt
parent b300b7ac8b
commit 9e87e558d2

View File

@@ -239,33 +239,34 @@ SER_FLAG_CH_B = %00000111
.code .code
; Read a register ; Read register value to A.
; Input: X as channel ; Input: X as channel
; Output result in A ; Y as register
.macro rra In,Reg ; Output: A
lda Reg readSSCReg:
sta In,x cpx #0
lda In,x bne ReadAreg
.endmacro sty SCCBREG
lda SCCBREG
rts
ReadAreg:
sty SCCAREG
lda SCCAREG
rts
; Write value of A to a register. ; Write value of A to a register.
; Input: X as channel ; Input: X as channel
.macro wra Out,Reg ; Y as register
pha writeSCCReg:
lda Reg cpx #0
sta Out,x bne WriteAreg
pla sty SCCBREG
sta Out,x sta SCCBREG
.endmacro rts
WriteAreg:
; Write value passed as parameter to a register. sty SCCAREG
; Input: X as channel sta SCCAREG
.macro wrr Out,Reg,Val rts
lda Reg
sta Out,x
lda Val
sta Out,x
.endmacro
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
; SER_INSTALL: Is called after the driver is loaded into memory. If possible, ; SER_INSTALL: Is called after the driver is loaded into memory. If possible,
@@ -291,8 +292,13 @@ SER_CLOSE:
; Deactivate interrupts ; Deactivate interrupts
sei sei
wrr SCCBREG, #WR_MASTER_IRQ_RST, #MASTER_IRQ_SHUTDOWN ldy #WR_MASTER_IRQ_RST
wrr SCCBREG, #WR_TX_RX_MODE_CTRL, #TX_RX_MODE_OFF lda #MASTER_IRQ_SHUTDOWN
jsr writeSCCReg
ldy #WR_TX_RX_MODE_CTRL
lda #TX_RX_MODE_OFF
jsr writeSCCReg
; Reset SerFlag to what it was ; Reset SerFlag to what it was
lda SerFlagOrig lda SerFlagOrig
@@ -303,14 +309,13 @@ SER_CLOSE:
; Clear external interrupts (twice) ; Clear external interrupts (twice)
ldy #WR_INIT_CTRL ldy #WR_INIT_CTRL
lda #INIT_CTRL_CLEAR_EIRQ lda #INIT_CTRL_CLEAR_EIRQ
jsr writeSCCReg
sty SCCBREG jsr writeSCCReg
sta SCCBREG
sty SCCBREG
sta SCCBREG
; Reset MIE for firmware use ; Reset MIE for firmware use
wrr SCCBREG, #WR_MASTER_IRQ_RST, #MASTER_IRQ_MIE_RST ldy #WR_MASTER_IRQ_RST
lda #MASTER_IRQ_MIE_RST
jsr writeSCCReg
ldx #$00 ldx #$00
stx Slot ; Mark port as closed stx Slot ; Mark port as closed
@@ -346,6 +351,8 @@ SetupErrOut:
rts rts
HardwareFound: HardwareFound:
sei ; Disable interrupts
; Check if the handshake setting is valid ; Check if the handshake setting is valid
ldy #SER_PARAMS::HANDSHAKE ; Handshake ldy #SER_PARAMS::HANDSHAKE ; Handshake
lda (ptr1),y lda (ptr1),y
@@ -370,7 +377,12 @@ SetupBufs:
ldx Channel ldx Channel
rra SCCBREG,#$00 ; Hit rr0 once to sync up ldy #RR_INIT_STATUS ; Hit rr0 once to sync up
jsr readSSCReg
ldy #WR_MISC_CTRL ; Turn everything off
lda #$00
jsr writeSCCReg
ldy #SER_PARAMS::STOPBITS ldy #SER_PARAMS::STOPBITS
lda (ptr1),y ; Stop bits lda (ptr1),y ; Stop bits
@@ -388,19 +400,24 @@ SetupBufs:
ora #TX_RX_CLOCK_MUL ora #TX_RX_CLOCK_MUL
wra SCCBREG,#WR_TX_RX_CTRL ldy #WR_TX_RX_CTRL ; Setup stop & parity bits
jsr writeSCCReg
cpx #$00 cpx #$00
bne ClockA bne ClockA
ClockB: ClockB:
wrr SCCBREG,#WR_CLOCK_CTRL,#CLOCK_CTRL_CH_B ldy #WR_CLOCK_CTRL
lda #CLOCK_CTRL_CH_B
jsr writeSCCReg
lda #INTR_PENDING_RX_EXT_B ; Store which IRQ bits we'll check lda #INTR_PENDING_RX_EXT_B ; Store which IRQ bits we'll check
sta CurChanIrqFlags sta CurChanIrqFlags
bra SetBaud bra SetBaud
ClockA: ClockA:
wrr SCCBREG,#WR_CLOCK_CTRL,#CLOCK_CTRL_CH_A ldy #WR_CLOCK_CTRL
lda #CLOCK_CTRL_CH_A
jsr writeSCCReg
lda #INTR_PENDING_RX_EXT_A ; Store which IRQ bits we'll check lda #INTR_PENDING_RX_EXT_A ; Store which IRQ bits we'll check
sta CurChanIrqFlags sta CurChanIrqFlags
@@ -416,50 +433,58 @@ SetBaud:
lda BaudLowTable,y ; Get low byte lda BaudLowTable,y ; Get low byte
bmi InvParam ; Branch if rate not supported bmi InvParam ; Branch if rate not supported
wra SCCBREG,#WR_BAUDL_CTRL phy
ldy #WR_BAUDL_CTRL
jsr writeSCCReg
ply
lda BaudHighTable,y ; Get high byte lda BaudHighTable,y ; Get high byte
wra SCCBREG,#WR_BAUDH_CTRL ldy #WR_BAUDH_CTRL
jsr writeSCCReg
lda #$00 ldy #WR_MISC_CTRL ; Time to turn this thing on
wra SCCBREG,#WR_MISC_CTRL lda #MISC_CTRL_RATE_GEN_ON
jsr writeSCCReg
ora #MISC_CTRL_RATE_GEN_ON ; Time to turn this thing on
wra SCCBREG,#WR_MISC_CTRL
; Final write to RX_CTRL
ldy #SER_PARAMS::DATABITS ldy #SER_PARAMS::DATABITS
lda (ptr1),y ; Data bits lda (ptr1),y ; Data bits
tay tay
lda RxBitTable,y ; Data bits for RX lda RxBitTable,y ; Data bits for RX
ora #RX_CTRL_ON ; Plus turn on ora #RX_CTRL_ON ; and turn RX on
wra SCCBREG,#WR_RX_CTRL
phy
ldy #WR_RX_CTRL
jsr writeSCCReg
ply
lda TxBitTable,y ; Data bits for TX lda TxBitTable,y ; Data bits for TX
ora #TX_CTRL_ON ; Plus turn on ora #TX_CTRL_ON ; and turn TX on
and #TX_DTR_ON and #TX_DTR_ON
sta RtsOff ; Save value for flow control sta RtsOff ; Save value for flow control
ora #TX_RTS_ON ora #TX_RTS_ON
wra SCCBREG,#WR_TX_CTRL
wrr SCCBREG,#WR_IRQ_CTRL,#IRQ_CLEANUP_EIRQ ldy #WR_TX_CTRL
jsr writeSCCReg
lda #WR_INIT_CTRL ; Clear ext status (write twice) ldy #WR_IRQ_CTRL
sta SCCBREG,x lda #IRQ_CLEANUP_EIRQ
jsr writeSCCReg
ldy #WR_INIT_CTRL ; Clear ext status (write twice)
lda #INIT_CTRL_CLEAR_EIRQ lda #INIT_CTRL_CLEAR_EIRQ
sta SCCBREG,x jsr writeSCCReg
jsr writeSCCReg
lda #WR_INIT_CTRL ldy #WR_TX_RX_MODE_CTRL ; Activate RX IRQ
sta SCCBREG,x lda #TX_RX_MODE_RXIRQ
lda #INIT_CTRL_CLEAR_EIRQ jsr writeSCCReg
sta SCCBREG,x
; Activate RX IRQ lda SCCBREG ; Activate master IRQ
wrr SCCBREG,#WR_TX_RX_MODE_CTRL,#TX_RX_MODE_RXIRQ ldy #WR_MASTER_IRQ_RST
lda #MASTER_IRQ_SET
wrr SCCBREG,#WR_MASTER_IRQ_RST,#MASTER_IRQ_SET jsr writeSCCReg
lda SER_FLAG ; Get SerFlag's current value lda SER_FLAG ; Get SerFlag's current value
sta SerFlagOrig ; and save it sta SerFlagOrig ; and save it
@@ -502,7 +527,9 @@ SER_GET:
lda RtsOff lda RtsOff
ora #TX_RTS_ON ora #TX_RTS_ON
wra SCCBREG,#WR_TX_CTRL
ldy #WR_TX_CTRL
jsr writeSCCReg
: ldy RecvHead ; Get byte from buffer : ldy RecvHead ; Get byte from buffer
lda RecvBuf,y lda RecvBuf,y
@@ -597,8 +624,10 @@ SER_IOCTL:
; was handled, otherwise with carry clear. ; was handled, otherwise with carry clear.
SER_IRQ: SER_IRQ:
ldx #$00 ; IRQ status is always in A reg ldx #$01 ; IRQ status is always in A reg
rra SCCAREG,#RR_INTR_PENDING_STATUS ldy #RR_INTR_PENDING_STATUS
jsr readSSCReg
and CurChanIrqFlags ; Is this ours? and CurChanIrqFlags ; Is this ours?
beq Done beq Done
@@ -620,7 +649,8 @@ SER_IRQ:
CheckSpecial: CheckSpecial:
; Always check IRQ special flags from Channel B (Ref page 5-24) ; Always check IRQ special flags from Channel B (Ref page 5-24)
; X is still 0 there. ; X is still 0 there.
rra SCCBREG,#RR_IRQ_STATUS ldy #RR_IRQ_STATUS
jsr readSSCReg
and #IRQ_MASQ and #IRQ_MASQ
cmp #IRQ_SPECIAL cmp #IRQ_SPECIAL
@@ -628,19 +658,28 @@ CheckSpecial:
; Clear exint ; Clear exint
ldx Channel ldx Channel
wrr SCCBREG,#WR_INIT_CTRL,#INIT_CTRL_CLEAR_EIRQ
ldy #WR_INIT_CTRL
lda #INIT_CTRL_CLEAR_EIRQ
jsr writeSCCReg
sec sec
rts rts
Flow: ldx Channel ; Assert flow control if buffer space too low Flow: ldx Channel ; Assert flow control if buffer space too low
ldy #WR_TX_CTRL
lda RtsOff lda RtsOff
wra SCCBREG,#WR_TX_CTRL jsr writeSCCReg
sta Stopped sta Stopped
sec ; Interrupt handled sec ; Interrupt handled
Done: rts Done: rts
Special: Special:ldx Channel
rra SCCBREG,#RR_SPEC_COND_STATUS ldy #RR_SPEC_COND_STATUS
jsr readSSCReg
tax tax
and #SPEC_COND_FRAMING_ERR and #SPEC_COND_FRAMING_ERR
bne BadChar bne BadChar
@@ -648,7 +687,10 @@ Special:
and #SPEC_COND_OVERRUN_ERR and #SPEC_COND_OVERRUN_ERR
beq BadChar beq BadChar
wrr SCCBREG,#WR_INIT_CTRL,#INIT_CTRL_CLEAR_ERR ldy #WR_INIT_CTRL
lda #INIT_CTRL_CLEAR_ERR
jsr writeSCCReg
sec sec
rts rts
@@ -669,14 +711,19 @@ Again: lda SendFreeCnt ; Anything to send?
lda Stopped ; Check for flow stopped lda Stopped ; Check for flow stopped
bne Quit ; Bail out if it is bne Quit ; Bail out if it is
Wait:
lda SCCBREG,x ; Check that we're ready to send lda SCCBREG,x ; Check that we're ready to send
tay tay
and #INIT_STATUS_READY and #INIT_STATUS_READY
bne Send beq NotReady
tya tya
and #INIT_STATUS_RTS ; Ready to send and #INIT_STATUS_RTS ; Ready to send
bne Send
NotReady:
bit tmp1 ; Keep trying if must try hard bit tmp1 ; Keep trying if must try hard
bmi Again bmi Wait
Quit: rts Quit: rts
Send: ldy SendHead ; Send byte Send: ldy SendHead ; Send byte