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:
commit
4bde3afd80
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user