Fixes to serial driver implementation

This commit is contained in:
Alex Thissen 2024-02-09 00:09:16 +00:00
parent 3dfe033000
commit 788ae82d30
3 changed files with 67 additions and 50 deletions

View File

@ -267,22 +267,26 @@ MIKEYHREV = $FD88
MIKEYSREV = $FD89 MIKEYSREV = $FD89
IODIR = $FD8A IODIR = $FD8A
IODAT = $FD8B IODAT = $FD8B
TxIntEnable = %10000000
RxIntEnable = %01000000
TxParEnable = %00010000
ResetErr = %00001000
TxOpenColl = %00000100
TxBreak = %00000010
ParEven = %00000001
TxReady = %10000000
RxReady = %01000000
TxEmpty = %00100000
RxParityErr = %00010000
RxOverrun = %00001000
RxFrameErr = %00000100
RxBreak = %00000010
ParityBit = %00000001
SERCTL = $FD8C SERCTL = $FD8C
; SERCTL bit definitions for write operations
TXINTEN = $80
RXINTEN = $40
PAREN = $10
RESETERR = $08
TXOPEN = $04
TXBRK = $02
PAREVEN = $01
; SERCTL bit definitions for read operations
TXRDY = $80
RXRDY = $40
TXEMPTY = $20
PARERR = $10
OVERRUN = $08
FRAMERR = $04
RXBRK = $02
PARBIT = $01
SERDAT = $FD8D SERDAT = $FD8D
SDONEACK = $FD90 SDONEACK = $FD90
CPUSLEEP = $FD91 CPUSLEEP = $FD91

View File

@ -68,7 +68,7 @@ MikeyInitData: .byte $9e,$18,$68,$1f,$00,$00,$00,$00,$00,$ff,$1a,$1b,$04,$0d,$2
; Disable the TX/RX IRQ; set to 8E1. ; Disable the TX/RX IRQ; set to 8E1.
lda #%00011101 lda #PAREN|RESETERR|TXOPEN|PAREVEN ; #%00011101
sta SERCTL sta SERCTL
; Clear all pending interrupts. ; Clear all pending interrupts.

View File

@ -73,7 +73,12 @@ SER_UNINSTALL:
; Must return an SER_ERR_xx code in a/x. ; Must return an SER_ERR_xx code in a/x.
SER_CLOSE: SER_CLOSE:
; Disable interrupts ; Disable interrupts and stop timer 4 (serial)
lda #$0C ; TXOPEN|RESETERR
sta SERCTL
lda #$00 ; Disable count and no reload
sta TIM4CTLA
; Done, return an error code ; Done, return an error code
lda #SER_ERR_OK lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error .assert SER_ERR_OK = 0, error
@ -108,7 +113,7 @@ SER_OPEN:
stz TxPtrIn stz TxPtrIn
stz TxPtrOut stz TxPtrOut
; clock = 8 * 15625 ; source period is 1 us
lda #%00011000 lda #%00011000
sta TIM4CTLA sta TIM4CTLA
ldy #SER_PARAMS::BAUDRATE ldy #SER_PARAMS::BAUDRATE
@ -118,7 +123,7 @@ SER_OPEN:
cmp #SER_BAUD_62500 cmp #SER_BAUD_62500
beq setbaudrate beq setbaudrate
ldx #2 ldx #3
cmp #SER_BAUD_31250 cmp #SER_BAUD_31250
beq setbaudrate beq setbaudrate
@ -194,13 +199,14 @@ SER_OPEN:
lda #SER_ERR_BAUD_UNAVAIL lda #SER_ERR_BAUD_UNAVAIL
ldx #0 ; return value is char ldx #0 ; return value is char
rts rts
setprescaler: setprescaler:
stx TIM4CTLA stx TIM4CTLA
bra baudsuccess bra baudsuccess
setbaudrate: setbaudrate:
stx TIM4BKUP stx TIM4BKUP
baudsuccess: baudsuccess:
ldx #TxOpenColl|ParEven ldx #TXOPEN|PAREVEN
stx contrl stx contrl
ldy #SER_PARAMS::DATABITS ; Databits ldy #SER_PARAMS::DATABITS ; Databits
lda (ptr1),y lda (ptr1),y
@ -218,15 +224,15 @@ baudsuccess:
beq checkhs beq checkhs
cmp #SER_PAR_SPACE cmp #SER_PAR_SPACE
bne @L0 bne @L0
ldx #TxOpenColl ldx #TXOPEN
stx contrl stx contrl
bra checkhs bra checkhs
@L0: @L0:
ldx #TxParEnable|TxOpenColl|ParEven ldx #PAREN|TXOPEN|PAREVEN
stx contrl stx contrl
cmp #SER_PAR_EVEN cmp #SER_PAR_EVEN
beq checkhs beq checkhs
ldx #TxParEnable|TxOpenColl ldx #PAREN|TXOPEN
stx contrl stx contrl
checkhs: checkhs:
ldx contrl ldx contrl
@ -237,7 +243,7 @@ checkhs:
bne invparameter bne invparameter
lda SERDAT lda SERDAT
lda contrl lda contrl
ora #RxIntEnable|ResetErr ora #RXINTEN|RESETERR ; Turn on interrupts for receive
sta SERCTL sta SERCTL
lda #SER_ERR_OK lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error .assert SER_ERR_OK = 0, error
@ -279,24 +285,26 @@ SER_PUT:
ina ina
cmp TxPtrOut cmp TxPtrOut
bne PutByte bne PutByte
lda #SER_ERR_OVERFLOW lda #SER_ERR_OVERFLOW
ldx #0 ; return value is char ldx #0 ; return value is char
rts rts
PutByte: PutByte:
ldy TxPtrIn ldy TxPtrIn
txa txa
sta TxBuffer,y sta TxBuffer,y
inc TxPtrIn inc TxPtrIn
bit TxDone bit TxDone ; Check bit 7 of TxDone (TXINTEN)
bmi @L1 bmi @L1 ; Was TXINTEN already set?
php php
sei sei
lda contrl lda contrl ; contrl does not include RXINTEN setting
ora #TxIntEnable|ResetErr ora #TXINTEN|RESETERR
sta SERCTL ; Allow TX-IRQ to hang RX-IRQ sta SERCTL ; Allow TX-IRQ to hang RX-IRQ (no receive while transmitting)
sta TxDone sta TxDone
plp plp ; Restore processor and interrupt enable
@L1: @L1:
lda #SER_ERR_OK lda #SER_ERR_OK
.assert SER_ERR_OK = 0, error .assert SER_ERR_OK = 0, error
@ -308,7 +316,7 @@ PutByte:
; Must return an SER_ERR_xx code in a/x. ; Must return an SER_ERR_xx code in a/x.
SER_STATUS: SER_STATUS:
ldy SerialStat lda SerialStat
ldx #$00 ldx #$00
sta (ptr1,x) sta (ptr1,x)
txa ; Return code = 0 txa ; Return code = 0
@ -342,27 +350,32 @@ SER_IRQ:
@L0: @L0:
bit TxDone bit TxDone
bmi @tx_irq ; Transmit in progress bmi @tx_irq ; Transmit in progress
ldx SERDAT
lda SERCTL ldx SERDAT ; Read received data
and #RxParityErr|RxOverrun|RxFrameErr|RxBreak lda contrl
beq @rx_irq and #PAREN ; Parity enabled implies SER_PAR_EVEN or SER_PAR_ODD
ora #OVERRUN|FRAMERR|RXBRK
bit SERCTL ; Compare with SERCTL
beq @rx_irq ; No errors so far
tsb SerialStat ; Save error condition tsb SerialStat ; Save error condition
bit #RxBreak bit #RXBRK ; Check for break signal
beq @noBreak beq @noBreak
stz TxPtrIn ; Break received - drop buffers stz TxPtrIn ; Break received - drop buffers
stz TxPtrOut stz TxPtrOut
stz RxPtrIn stz RxPtrIn
stz RxPtrOut stz RxPtrOut
@noBreak: @noBreak:
lda contrl lda contrl
ora #RxIntEnable|ResetErr ora #RXINTEN|RESETERR
sta SERCTL sta SERCTL
lda #$10
sta INTRST
bra @IRQexit bra @IRQexit
@rx_irq: @rx_irq:
lda contrl lda contrl
ora #RxIntEnable|ResetErr ora #RXINTEN|RESETERR
sta SERCTL sta SERCTL
txa txa
ldx RxPtrIn ldx RxPtrIn
@ -370,20 +383,22 @@ SER_IRQ:
txa txa
inx inx
@cont0:
cpx RxPtrOut cpx RxPtrOut
beq @1 beq @1
stx RxPtrIn stx RxPtrIn
lda #SERIAL_INTERRUPT
sta INTRST
bra @IRQexit bra @IRQexit
@1: @1:
sta RxPtrIn sta RxPtrIn
lda #$80 lda #$80
tsb SerialStat tsb SerialStat
lda contrl
ora #RXINTEN|RESETERR
sta SERCTL
bra @IRQexit
@tx_irq: @tx_irq:
ldx TxPtrOut ; Has all bytes been sent? ldx TxPtrOut ; Have all bytes been sent?
cpx TxPtrIn cpx TxPtrIn
beq @allSent beq @allSent
@ -393,24 +408,22 @@ SER_IRQ:
@exit1: @exit1:
lda contrl lda contrl
ora #TxIntEnable|ResetErr ora #TXINTEN|RESETERR
sta SERCTL sta SERCTL
lda #SERIAL_INTERRUPT
sta INTRST
bra @IRQexit bra @IRQexit
@allSent: @allSent:
lda SERCTL ; All bytes sent lda SERCTL ; All bytes sent
bit #TxEmpty bit #TXEMPTY
beq @exit1 beq @exit1
bvs @exit1 bvs @exit1
stz TxDone stz TxDone
lda contrl lda contrl
ora #RxIntEnable|ResetErr ora #RXINTEN|RESETERR ; Re-enable receive interrupt
sta SERCTL sta SERCTL
@IRQexit:
lda #SERIAL_INTERRUPT lda #SERIAL_INTERRUPT
sta INTRST sta INTRST
@IRQexit:
clc clc
rts rts