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

IIgs SCC: Rework branches to X-indexed variables

and general cleanup/commenting
This commit is contained in:
Colin Leroy-Mira 2024-02-20 07:17:12 +01:00 committed by Oliver Schmidt
parent 8b71fafb84
commit 86317711e0

View File

@ -66,36 +66,16 @@ HSType: .res 1 ; Flow-control type
RecvBuf: .res 256 ; Receive buffers: 256 bytes RecvBuf: .res 256 ; Receive buffers: 256 bytes
SendBuf: .res 256 ; Send buffers: 256 bytes SendBuf: .res 256 ; Send buffers: 256 bytes
ClockSource: .res 1 ; Whether to use BRG or XTAL for clock CurClockSource: .res 1 ; Whether to use BRG or RTxC for clock
.data .data
Opened: .byte $00 ; 1 when opened Opened: .byte $00 ; 1 when opened
Channel: .byte $00 ; Channel B by default Channel: .byte $00 ; Channel B by default
CurChanIrqFlags:.byte INTR_PENDING_RX_EXT_B CurChanIrqFlags:.byte $00
SerFlagOrig: .byte $00 SerFlagOrig: .byte $00
; Tables used to translate cc65 RS232 params into register values
; (Ref page 5-18 and 5-19)
BaudLowTable: .byte $7E ; SER_BAUD_300
.byte $5E ; SER_BAUD_1200
.byte $2E ; SER_BAUD_2400
.byte $16 ; SER_BAUD_4800
.byte $0A ; SER_BAUD_9600
.byte $04 ; SER_BAUD_19200
.byte $01 ; SER_BAUD_38400
.byte $00 ; SER_BAUD_57600
BaudHighTable: .byte $01 ; SER_BAUD_300
.byte $00 ; SER_BAUD_1200
.byte $00 ; SER_BAUD_2400
.byte $00 ; SER_BAUD_4800
.byte $00 ; SER_BAUD_9600
.byte $00 ; SER_BAUD_19200
.byte $00 ; SER_BAUD_38400
.byte $00 ; SER_BAUD_57600
RxBitTable: .byte %00000000 ; SER_BITS_5, in WR_RX_CTRL (WR3) RxBitTable: .byte %00000000 ; SER_BITS_5, in WR_RX_CTRL (WR3)
.byte %10000000 ; SER_BITS_6 (Ref page 5-7) .byte %10000000 ; SER_BITS_6 (Ref page 5-7)
.byte %01000000 ; SER_BITS_7 .byte %01000000 ; SER_BITS_7
@ -108,38 +88,65 @@ TxBitTable: .byte %00000000 ; SER_BITS_5, in WR_TX_CTRL (WR5)
.rodata .rodata
ClockMultiplier:.byte %01000000 ; Clock x16 (300-57600bps, ref page 5-8) ClockMultiplier:.byte %01000000 ; Clock x16 (300-57600bps, WR4, ref page 5-8)
.byte %10000000 ; Clock x32 (115200bps, ref page 5-8) .byte %10000000 ; Clock x32 (115200bps, ref page 5-8)
ClockSourceA: .byte %11010000 ; Use baud rate generator (page 5-17) ClockSource: .byte %01010000 ; Use baud rate generator (ch. B) (WR11, page 5-17)
.byte %10000000 ; Use XTAL (115200bps) .byte %00000000 ; Use RTxC (115200bps) (ch. B)
.byte %11010000 ; Use baud rate generator (ch. A)
.byte %10000000 ; Use RTxC (115200bps) (ch. A)
ClockSourceB: .byte %01010000 ; Use baud rate generator BrgEnabled: .byte %00000001 ; Baud rate generator on (WR14, page 5-19)
.byte %00000000 ; Use XTAL (115200bps) .byte %00000000 ; BRG Off
ChanIrqFlags: .byte %00000101 ; ANDed (RX/special IRQ, ch. B) (page 5-25)
.byte %00101000 ; ANDed (RX/special IRQ, ch. A)
ChanIrqMask: .byte %00000111 ; Ch. B IRQ flags mask
.byte %00111000 ; Ch. A IRQ flags mask
BaudTable: ; bit7 = 1 means setting is invalid BaudTable: ; bit7 = 1 means setting is invalid
; Otherwise refers to the index in ; Indexes cc65 RS232 SER_BAUD enum
; Baud(Low/High)Table ; into WR12/13 register values
.byte $FF ; SER_BAUD_45_5 ; (Ref page 5-18 and 5-19)
.byte $FF ; SER_BAUD_50 .word $FFFF ; SER_BAUD_45_5
.byte $FF ; SER_BAUD_75 .word $FFFF ; SER_BAUD_50
.byte $FF ; SER_BAUD_110 .word $FFFF ; SER_BAUD_75
.byte $FF ; SER_BAUD_134_5 .word $FFFF ; SER_BAUD_110
.byte $FF ; SER_BAUD_150 .word $FFFF ; SER_BAUD_134_5
.byte $00 ; SER_BAUD_300 .word $FFFF ; SER_BAUD_150
.byte $FF ; SER_BAUD_600 .word $017E ; SER_BAUD_300
.byte $01 ; SER_BAUD_1200 .word $FFFF ; SER_BAUD_600
.byte $FF ; SER_BAUD_1800 .word $005E ; SER_BAUD_1200
.byte $02 ; SER_BAUD_2400 .word $FFFF ; SER_BAUD_1800
.byte $FF ; SER_BAUD_3600 .word $002E ; SER_BAUD_2400
.byte $03 ; SER_BAUD_4800 .word $FFFF ; SER_BAUD_3600
.byte $FF ; SER_BAUD_7200 .word $0016 ; SER_BAUD_4800
.byte $04 ; SER_BAUD_9600 .word $FFFF ; SER_BAUD_7200
.byte $05 ; SER_BAUD_19200 .word $000A ; SER_BAUD_9600
.byte $06 ; SER_BAUD_38400 .word $0004 ; SER_BAUD_19200
.byte $07 ; SER_BAUD_57600 .word $0001 ; SER_BAUD_38400
.byte $00 ; SER_BAUD_115200 .word $0000 ; SER_BAUD_57600
.byte $FF ; SER_BAUD_230400 .word $0000 ; SER_BAUD_115200 (constant unused at that speed)
.word $FFFF ; SER_BAUD_230400
; About the speed selection: either we use the baud rate generator:
; - Load the time constants from BaudTable into WR12/WR13
; - Setup the TX/RX clock source to BRG (ClockSource into WR11)
; - Setup the clock multiplier (WR4)
; - Enable the baud rate generator (WR14)
; In this case, the baud rate will be:
; rate = crystal_clock/(2+BRG_time_constant))/(2*clock_multiplier)
; Example: (3686400/(2+0x0004)) / (2*16) = 19200 bps
;
; Or we don't use the baud rate generator:
; - Setup the TX/RX clock source to RTxC
; - Setup the clock multiplier
; - Disable the baud rate generator
; - WR12 and 13 are ignored
; In this case, the baud rate will be:
; rate = crystal_clock/clock_multiplier
; Example: 3686400/32 = 115200 bps
StopTable: .byte %00000100 ; SER_STOP_1, in WR_TX_RX_CTRL (WR4) StopTable: .byte %00000100 ; SER_STOP_1, in WR_TX_RX_CTRL (WR4)
.byte %00001100 ; SER_STOP_2 (Ref page 5-8) .byte %00001100 ; SER_STOP_2 (Ref page 5-8)
@ -167,6 +174,7 @@ SER_FLAG := $E10104
; ------------------------------------------------------------------------ ; ------------------------------------------------------------------------
; Channels ; Channels
CHANNEL_B = 0 CHANNEL_B = 0
CHANNEL_A = 1 CHANNEL_A = 1
@ -212,8 +220,6 @@ WR_BAUDL_CTRL = 12 ; (Ref page 5-18)
WR_BAUDH_CTRL = 13 ; (Ref page 5-19) WR_BAUDH_CTRL = 13 ; (Ref page 5-19)
WR_MISC_CTRL = 14 ; (Ref page 5-19) WR_MISC_CTRL = 14 ; (Ref page 5-19)
MISC_CTRL_RATE_GEN_ON = %00000001 ; STA'd
MISC_CTRL_RATE_GEN_OFF = %00000000 ; STA'd
WR_IRQ_CTRL = 15 ; (Ref page 5-20) WR_IRQ_CTRL = 15 ; (Ref page 5-20)
IRQ_CLEANUP_EIRQ = %00001000 IRQ_CLEANUP_EIRQ = %00001000
@ -228,13 +234,8 @@ IRQ_RX = %00100000
IRQ_SPECIAL = %01100000 IRQ_SPECIAL = %01100000
RR_INTR_PENDING_STATUS = 3 ; (Ref page 5-25) RR_INTR_PENDING_STATUS = 3 ; (Ref page 5-25)
INTR_PENDING_RX_EXT_A = %00101000 ; ANDed (RX or special IRQ)
INTR_PENDING_RX_EXT_B = %00000101 ; ANDed (RX or special IRQ)
INTR_IS_RX = %00100100 ; ANDed (RX IRQ, channel A or B) INTR_IS_RX = %00100100 ; ANDed (RX IRQ, channel A or B)
SER_FLAG_CH_A = %00111000
SER_FLAG_CH_B = %00000111
.code .code
; Read register value to A. ; Read register value to A.
@ -338,13 +339,12 @@ IIgs:
rts rts
getClockSource: getClockSource:
ldy #SER_PARAMS::BAUDRATE .assert SER_PARAMS::BAUDRATE = 0, error
lda (ptr1),y ; Baudrate index - cc65 value lda (ptr1) ; Baudrate index - cc65 value
ldy #$01
cmp #SER_BAUD_115200 cmp #SER_BAUD_115200
beq :+ lda #$00
ldy #$00 adc #$00
: sty ClockSource sta CurClockSource ; 0 = BRG, 1 = RTxC
rts rts
;---------------------------------------------------------------------------- ;----------------------------------------------------------------------------
@ -378,13 +378,13 @@ SER_OPEN:
ldy #RR_INIT_STATUS ; Hit rr0 once to sync up ldy #RR_INIT_STATUS ; Hit rr0 once to sync up
jsr readSSCReg jsr readSSCReg
ldy #WR_MISC_CTRL ; Turn everything off ldy #WR_MISC_CTRL ; WR14: Turn everything off
lda #$00 lda #$00
jsr writeSCCReg jsr writeSCCReg
jsr getClockSource ; Should we use BRG or XTAL? jsr getClockSource ; Should we use BRG or RTxC?
ldy #SER_PARAMS::STOPBITS ldy #SER_PARAMS::STOPBITS ; WR4 setup: clock mult., stop & parity
lda (ptr1),y ; Stop bits lda (ptr1),y ; Stop bits
tay tay
lda StopTable,y ; Get value lda StopTable,y ; Get value
@ -397,109 +397,92 @@ SER_OPEN:
ora ParityTable,y ; Get value ora ParityTable,y ; Get value
bmi InvParam bmi InvParam
ldy ClockSource ; Setup clock multiplier ldy CurClockSource ; Clock multiplier
ora ClockMultiplier,y ora ClockMultiplier,y
ldy #WR_TX_RX_CTRL ; Setup stop & parity bits ldy #WR_TX_RX_CTRL
jsr writeSCCReg jsr writeSCCReg ; End of WR4 setup
ldy ClockSource ldy CurClockSource ; WR11 setup: clock source
cpx #CHANNEL_B cpx #CHANNEL_B
bne ClockA beq SetClock
ClockB: iny ; Shift to get correct ClockSource val
lda ClockSourceB,y iny ; depending on our channel
SetClock:
lda ClockSource,y
ldy #WR_CLOCK_CTRL ldy #WR_CLOCK_CTRL
jsr writeSCCReg jsr writeSCCReg ; End of WR11 setup
lda #INTR_PENDING_RX_EXT_B ; Store which IRQ bits we'll check lda ChanIrqFlags,x ; Store which IRQ bits we'll check
sta CurChanIrqFlags
bra SetBaud
ClockA:
lda ClockSourceA,y
ldy #WR_CLOCK_CTRL
jsr writeSCCReg
lda #INTR_PENDING_RX_EXT_A ; Store which IRQ bits we'll check
sta CurChanIrqFlags sta CurChanIrqFlags
SetBaud: SetBaud:
ldy #SER_PARAMS::BAUDRATE .assert SER_PARAMS::BAUDRATE = 0, error
lda (ptr1),y ; Baudrate index - cc65 value lda (ptr1) ; Baudrate index - cc65 value
asl
tay tay
lda BaudTable,y ; Get chip value from Low/High tables lda BaudTable,y ; Get low byte of register value
bpl BaudOK ; Verify baudrate is supported bpl BaudOK ; Verify baudrate is supported
InvParam: InvParam:
lda #SER_ERR_INIT_FAILED lda #SER_ERR_INIT_FAILED
ldx #$00 ; Promote char return value ldy #$00 ; Mark port closed
stz Opened ; Mark port closed bra SetupOut
cli
rts
BaudOK: BaudOK:
tay phy ; WR12 setup: BRG time constant, low byte
cpy #SER_BAUD_115200 ldy #WR_BAUDL_CTRL ; Setting WR12 & 13 is useless if we're using
beq :+ ; Skip baud rate generator setup: jsr writeSCCReg ; RTxC, but doing it anyway makes code smaller
; For 115200bps, we use XTAL instead
lda BaudLowTable,y ; Get low byte
phy
ldy #WR_BAUDL_CTRL
jsr writeSCCReg
ply ply
lda BaudHighTable,y ; Get high byte iny
lda BaudTable,y ; WR13 setup: BRG time constant, high byte
ldy #WR_BAUDH_CTRL ldy #WR_BAUDH_CTRL
jsr writeSCCReg jsr writeSCCReg
: lda #MISC_CTRL_RATE_GEN_ON ; Setup BRG according to selected rate ldy CurClockSource ; WR14 setup: BRG enabling
ldy ClockSource lda BrgEnabled,y
cpy #$00 ldy #WR_MISC_CTRL ; Time to turn this thing on
beq :+
lda #MISC_CTRL_RATE_GEN_OFF
: ldy #WR_MISC_CTRL ; Time to turn this thing on
jsr writeSCCReg jsr writeSCCReg
ldy #SER_PARAMS::DATABITS ldy #SER_PARAMS::DATABITS ; WR3 setup: RX data bits
lda (ptr1),y ; Data bits lda (ptr1),y
tay tay
lda RxBitTable,y ; Data bits for RX lda RxBitTable,y
ora #RX_CTRL_ON ; and turn RX on ora #RX_CTRL_ON ; and turn receiver on
phy phy
ldy #WR_RX_CTRL ldy #WR_RX_CTRL
jsr writeSCCReg jsr writeSCCReg ; End of WR3 setup
ply ply
lda TxBitTable,y ; Data bits for TX lda TxBitTable,y ; WR5 setup: TX data bits
ora #TX_CTRL_ON ; and turn TX on ora #TX_CTRL_ON ; and turn transmitter on
and #TX_DTR_ON and #TX_DTR_ON ; and turn DTR on
sta RtsOff ; Save value for flow control sta RtsOff ; Save value for flow control
ora #TX_RTS_ON ora #TX_RTS_ON ; and turn RTS on
ldy #WR_TX_CTRL ldy #WR_TX_CTRL
jsr writeSCCReg jsr writeSCCReg ; End of WR5 setup
ldy #WR_IRQ_CTRL ldy #WR_IRQ_CTRL ; WR15 setup: IRQ
lda #IRQ_CLEANUP_EIRQ lda #IRQ_CLEANUP_EIRQ
jsr writeSCCReg jsr writeSCCReg
ldy #WR_INIT_CTRL ; Clear ext status (write twice) ldy #WR_INIT_CTRL ; WR0 setup: clear existing IRQs
lda #INIT_CTRL_CLEAR_EIRQ lda #INIT_CTRL_CLEAR_EIRQ
jsr writeSCCReg jsr writeSCCReg ; Clear (write twice)
jsr writeSCCReg jsr writeSCCReg
ldy #WR_TX_RX_MODE_CTRL ; Activate RX IRQ ldy #WR_TX_RX_MODE_CTRL ; WR1 setup: Activate RX IRQ
lda #TX_RX_MODE_RXIRQ lda #TX_RX_MODE_RXIRQ
jsr writeSCCReg jsr writeSCCReg
lda SCCBREG ; Activate master IRQ lda SCCBREG ; WR9 setup: Activate master IRQ
ldy #WR_MASTER_IRQ_RST ldy #WR_MASTER_IRQ_RST
lda #MASTER_IRQ_SET lda #MASTER_IRQ_SET
jsr writeSCCReg jsr writeSCCReg
@ -507,22 +490,15 @@ BaudOK:
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
cpx #CHANNEL_B ora ChanIrqMask,x ; Tell firmware which channel IRQs we want
bne IntA
IntB:
ora #SER_FLAG_CH_B ; Inform firmware we want channel B IRQs
bra StoreFlag
IntA:
ora #SER_FLAG_CH_A ; Inform firmware we want channel A IRQs
StoreFlag:
sta SER_FLAG sta SER_FLAG
ldy #$01 ; Mark port opened ldy #$01 ; Mark port opened
sty Opened
lda #SER_ERR_OK lda #SER_ERR_OK
ldx #$00 ; Promote char return value
SetupOut:
ldx #$00 ; Promote char return value
sty Opened
cli cli
rts rts