1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-07 23:29:39 +00:00

Merge pull request #2410 from alexthissen/serial

Improvements and fixes in serial support for Atari Lynx
This commit is contained in:
Bob Andrews 2024-02-12 12:50:02 +01:00 committed by GitHub
commit 4bde3afd80
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 115 additions and 113 deletions

View File

@ -259,30 +259,44 @@ SND_INTERRUPT = TIMER7_INTERRUPT
INTRST = $FD80 INTRST = $FD80
INTSET = $FD81 INTSET = $FD81
MAGRDY0 = $FD84 MAGRDY0 = $FD84
MAGRDY1 = $FD85 MAGRDY1 = $FD85
AUDIN = $FD86 AUDIN = $FD86
SYSCTL1 = $FD87 SYSCTL1 = $FD87
MIKEYHREV = $FD88 MIKEYHREV = $FD88
MIKEYSREV = $FD89 MIKEYSREV = $FD89
IODIR = $FD8A
IODAT = $FD8B IODIR = $FD8A
TxIntEnable = %10000000 IODAT = $FD8B
RxIntEnable = %01000000 ; IODIR and IODAT bit definitions
TxParEnable = %00010000 AUDIN_BIT = $10 ; Note that there is also the address AUDIN
ResetErr = %00001000 READ_ENABLE = $10 ; Same bit for AUDIN_BIT
TxOpenColl = %00000100 RESTLESS = $08
TxBreak = %00000010 NOEXP = $04 ; If set, redeye is not connected
ParEven = %00000001 CART_ADDR_DATA = $02
TxReady = %10000000 CART_POWER_OFF = $02 ; Same bit for CART_ADDR_DATA
RxReady = %01000000 EXTERNAL_POWER = $01
TxEmpty = %00100000
RxParityErr = %00010000 SERCTL = $FD8C
RxOverrun = %00001000 ; SERCTL bit definitions for write operations
RxFrameErr = %00000100 TXINTEN = $80
RxBreak = %00000010 RXINTEN = $40
ParityBit = %00000001 PAREN = $10
SERCTL = $FD8C 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 #TXOPEN|RESETERR
sta SERCTL
stz TIM4CTLA ; Disable count and no reload
stz SerialStat ; Reset status
; 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,17 +113,17 @@ SER_OPEN:
stz TxPtrIn stz TxPtrIn
stz TxPtrOut stz TxPtrOut
; clock = 8 * 15625
lda #%00011000
sta TIM4CTLA
ldy #SER_PARAMS::BAUDRATE ldy #SER_PARAMS::BAUDRATE
lda (ptr1),y lda (ptr1),y
; Source period is 1 us
ldy #%00011000 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_1
ldx #1 ldx #1
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
@ -134,6 +139,10 @@ SER_OPEN:
cmp #SER_BAUD_2400 cmp #SER_BAUD_2400
beq setbaudrate beq setbaudrate
ldx #68
cmp #SER_BAUD_1800
beq setbaudrate
ldx #103 ldx #103
cmp #SER_BAUD_1200 cmp #SER_BAUD_1200
beq setbaudrate beq setbaudrate
@ -142,65 +151,22 @@ SER_OPEN:
cmp #SER_BAUD_600 cmp #SER_BAUD_600
beq setbaudrate beq setbaudrate
; clock = 6 * 15625 ; Source period is 8 us
ldx #%00011010 ldy #%00011011 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_8
stx TIM4CTLA
ldx #12 ldx #51
cmp #SER_BAUD_7200
beq setbaudrate
ldx #25
cmp #SER_BAUD_3600
beq setbaudrate
ldx #207
stx TIM4BKUP
; clock = 4 * 15625
ldx #%00011100
cmp #SER_BAUD_300 cmp #SER_BAUD_300
beq setprescaler
; clock = 6 * 15625
ldx #%00011110
cmp #SER_BAUD_150
beq setprescaler
; clock = 1 * 15625
ldx #%00011111
stx TIM4CTLA
cmp #SER_BAUD_75
beq baudsuccess
ldx #141
cmp #SER_BAUD_110
beq setbaudrate
; clock = 2 * 15625
ldx #%00011010
stx TIM4CTLA
ldx #68
cmp #SER_BAUD_1800
beq setbaudrate
; clock = 6 * 15625
ldx #%00011110
stx TIM4CTLA
ldx #231
cmp #SER_BAUD_134_5
beq setbaudrate beq setbaudrate
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:
stx TIM4CTLA
bra baudsuccess
setbaudrate: setbaudrate:
sty TIM4CTLA
stx TIM4BKUP stx TIM4BKUP
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 +184,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
@ -234,15 +200,27 @@ checkhs:
ldy #SER_PARAMS::HANDSHAKE ; Handshake ldy #SER_PARAMS::HANDSHAKE ; Handshake
lda (ptr1),y lda (ptr1),y
cmp #SER_HS_NONE cmp #SER_HS_NONE
beq redeye_ok
cmp #SER_HS_SW ; Software handshake will check for connected redeye
bne invparameter bne invparameter
lda IODAT
and #NOEXP ; Check if redeye bit flag is unset
beq redeye_ok
lda #SER_ERR_NO_DEVICE ; ComLynx cable is not inserted
ldx #0
rts
redeye_ok:
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
tax tax
rts rts
invparameter: invparameter:
lda #SER_ERR_INIT_FAILED lda #SER_ERR_INIT_FAILED
ldx #0 ; return value is char ldx #0 ; return value is char
@ -264,8 +242,8 @@ GetByte:
ldy RxPtrOut ldy RxPtrOut
lda RxBuffer,y lda RxBuffer,y
inc RxPtrOut inc RxPtrOut
sta (ptr1)
ldx #$00 ldx #$00
sta (ptr1,x)
txa ; Return code = 0 txa ; Return code = 0
rts rts
@ -279,24 +257,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,9 +288,9 @@ 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
sta (ptr1)
ldx #$00 ldx #$00
sta (ptr1,x)
txa ; Return code = 0 txa ; Return code = 0
rts rts
@ -342,48 +322,56 @@ 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
tay
ora #OVERRUN|FRAMERR|RXBRK
and SERCTL ; Check presence of relevant error flags in 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 bra @exit0
ora #RxIntEnable|ResetErr
sta SERCTL
lda #$10
sta INTRST
bra @IRQexit
@rx_irq: @rx_irq:
tya
bne @2 ; Parity was enabled so no marker bit check needed
lda contrl lda contrl
ora #RxIntEnable|ResetErr eor SERCTL ; Should match current parity bit
sta SERCTL and #PARBIT ; Check for mark or space value
bne @exit0
@2:
txa txa
ldx RxPtrIn ldx RxPtrIn
sta RxBuffer,x sta RxBuffer,x
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
bra @exit0
@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 +381,24 @@ 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
@exit0:
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

View File

@ -40,14 +40,14 @@ cont1:
bra loop1 bra loop1
read_byte: read_byte:
bit SERCTL bit SERCTL ; Check for RXRDY ($40)
bvc read_byte bvc read_byte
lda SERDAT lda SERDAT
rts rts
_UpLoaderIRQ: _UpLoaderIRQ:
lda INTSET lda INTSET
and #$10 and #SERIAL_INTERRUPT
bne @L0 bne @L0
clc clc
rts rts
@ -69,7 +69,7 @@ again:
; last action : clear interrupt ; last action : clear interrupt
; ;
exit: exit:
lda #$10 lda #SERIAL_INTERRUPT
sta INTRST sta INTRST
clc clc
rts rts