diff --git a/asminc/lynx.inc b/asminc/lynx.inc index 5ae17f6ef..0d34e1c7c 100644 --- a/asminc/lynx.inc +++ b/asminc/lynx.inc @@ -259,30 +259,44 @@ SND_INTERRUPT = TIMER7_INTERRUPT INTRST = $FD80 INTSET = $FD81 + MAGRDY0 = $FD84 MAGRDY1 = $FD85 AUDIN = $FD86 SYSCTL1 = $FD87 MIKEYHREV = $FD88 MIKEYSREV = $FD89 -IODIR = $FD8A -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 + +IODIR = $FD8A +IODAT = $FD8B +; IODIR and IODAT bit definitions +AUDIN_BIT = $10 ; Note that there is also the address AUDIN +READ_ENABLE = $10 ; Same bit for AUDIN_BIT +RESTLESS = $08 +NOEXP = $04 ; If set, redeye is not connected +CART_ADDR_DATA = $02 +CART_POWER_OFF = $02 ; Same bit for CART_ADDR_DATA +EXTERNAL_POWER = $01 + +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 SDONEACK = $FD90 CPUSLEEP = $FD91 diff --git a/libsrc/lynx/crt0.s b/libsrc/lynx/crt0.s index 238a2c99d..030f523e9 100644 --- a/libsrc/lynx/crt0.s +++ b/libsrc/lynx/crt0.s @@ -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. - lda #%00011101 + lda #PAREN|RESETERR|TXOPEN|PAREVEN ; #%00011101 sta SERCTL ; Clear all pending interrupts. diff --git a/libsrc/lynx/ser/lynx-comlynx.s b/libsrc/lynx/ser/lynx-comlynx.s index 8aa3c838e..c4ae3d5b6 100644 --- a/libsrc/lynx/ser/lynx-comlynx.s +++ b/libsrc/lynx/ser/lynx-comlynx.s @@ -73,7 +73,12 @@ SER_UNINSTALL: ; Must return an SER_ERR_xx code in a/x. 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 lda #SER_ERR_OK .assert SER_ERR_OK = 0, error @@ -108,17 +113,17 @@ SER_OPEN: stz TxPtrIn stz TxPtrOut - ; clock = 8 * 15625 - lda #%00011000 - sta TIM4CTLA ldy #SER_PARAMS::BAUDRATE lda (ptr1),y + ; Source period is 1 us + ldy #%00011000 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_1 + ldx #1 cmp #SER_BAUD_62500 beq setbaudrate - ldx #2 + ldx #3 cmp #SER_BAUD_31250 beq setbaudrate @@ -134,6 +139,10 @@ SER_OPEN: cmp #SER_BAUD_2400 beq setbaudrate + ldx #68 + cmp #SER_BAUD_1800 + beq setbaudrate + ldx #103 cmp #SER_BAUD_1200 beq setbaudrate @@ -142,65 +151,22 @@ SER_OPEN: cmp #SER_BAUD_600 beq setbaudrate - ; clock = 6 * 15625 - ldx #%00011010 - stx TIM4CTLA + ; Source period is 8 us + ldy #%00011011 ; ENABLE_RELOAD|ENABLE_COUNT|AUD_8 - ldx #12 - cmp #SER_BAUD_7200 - beq setbaudrate - - ldx #25 - cmp #SER_BAUD_3600 - beq setbaudrate - - ldx #207 - stx TIM4BKUP - - ; clock = 4 * 15625 - ldx #%00011100 + ldx #51 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 lda #SER_ERR_BAUD_UNAVAIL ldx #0 ; return value is char rts -setprescaler: - stx TIM4CTLA - bra baudsuccess + setbaudrate: + sty TIM4CTLA stx TIM4BKUP -baudsuccess: - ldx #TxOpenColl|ParEven + + ldx #TXOPEN|PAREVEN stx contrl ldy #SER_PARAMS::DATABITS ; Databits lda (ptr1),y @@ -218,15 +184,15 @@ baudsuccess: beq checkhs cmp #SER_PAR_SPACE bne @L0 - ldx #TxOpenColl + ldx #TXOPEN stx contrl bra checkhs @L0: - ldx #TxParEnable|TxOpenColl|ParEven + ldx #PAREN|TXOPEN|PAREVEN stx contrl cmp #SER_PAR_EVEN beq checkhs - ldx #TxParEnable|TxOpenColl + ldx #PAREN|TXOPEN stx contrl checkhs: ldx contrl @@ -234,15 +200,27 @@ checkhs: ldy #SER_PARAMS::HANDSHAKE ; Handshake lda (ptr1),y cmp #SER_HS_NONE + beq redeye_ok + cmp #SER_HS_SW ; Software handshake will check for connected redeye 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 contrl - ora #RxIntEnable|ResetErr + ora #RXINTEN|RESETERR ; Turn on interrupts for receive sta SERCTL lda #SER_ERR_OK .assert SER_ERR_OK = 0, error tax rts + invparameter: lda #SER_ERR_INIT_FAILED ldx #0 ; return value is char @@ -264,8 +242,8 @@ GetByte: ldy RxPtrOut lda RxBuffer,y inc RxPtrOut + sta (ptr1) ldx #$00 - sta (ptr1,x) txa ; Return code = 0 rts @@ -279,24 +257,26 @@ SER_PUT: ina cmp TxPtrOut bne PutByte + lda #SER_ERR_OVERFLOW ldx #0 ; return value is char rts + PutByte: ldy TxPtrIn txa sta TxBuffer,y inc TxPtrIn - bit TxDone - bmi @L1 + bit TxDone ; Check bit 7 of TxDone (TXINTEN) + bmi @L1 ; Was TXINTEN already set? php sei - lda contrl - ora #TxIntEnable|ResetErr - sta SERCTL ; Allow TX-IRQ to hang RX-IRQ + lda contrl ; contrl does not include RXINTEN setting + ora #TXINTEN|RESETERR + sta SERCTL ; Allow TX-IRQ to hang RX-IRQ (no receive while transmitting) sta TxDone - plp + plp ; Restore processor and interrupt enable @L1: lda #SER_ERR_OK .assert SER_ERR_OK = 0, error @@ -308,9 +288,9 @@ PutByte: ; Must return an SER_ERR_xx code in a/x. SER_STATUS: - ldy SerialStat + lda SerialStat + sta (ptr1) ldx #$00 - sta (ptr1,x) txa ; Return code = 0 rts @@ -342,48 +322,56 @@ SER_IRQ: @L0: bit TxDone bmi @tx_irq ; Transmit in progress - ldx SERDAT - lda SERCTL - and #RxParityErr|RxOverrun|RxFrameErr|RxBreak - beq @rx_irq + + ldx SERDAT ; Read received data + lda contrl + 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 - bit #RxBreak + bit #RXBRK ; Check for break signal beq @noBreak + stz TxPtrIn ; Break received - drop buffers stz TxPtrOut stz RxPtrIn stz RxPtrOut @noBreak: - lda contrl - ora #RxIntEnable|ResetErr - sta SERCTL - lda #$10 - sta INTRST - bra @IRQexit + bra @exit0 + @rx_irq: + tya + bne @2 ; Parity was enabled so no marker bit check needed + lda contrl - ora #RxIntEnable|ResetErr - sta SERCTL + eor SERCTL ; Should match current parity bit + and #PARBIT ; Check for mark or space value + bne @exit0 + +@2: txa ldx RxPtrIn sta RxBuffer,x txa inx -@cont0: cpx RxPtrOut beq @1 stx RxPtrIn - lda #SERIAL_INTERRUPT - sta INTRST bra @IRQexit @1: sta RxPtrIn lda #$80 tsb SerialStat + bra @exit0 + @tx_irq: - ldx TxPtrOut ; Has all bytes been sent? + ldx TxPtrOut ; Have all bytes been sent? cpx TxPtrIn beq @allSent @@ -393,24 +381,24 @@ SER_IRQ: @exit1: lda contrl - ora #TxIntEnable|ResetErr + ora #TXINTEN|RESETERR sta SERCTL - lda #SERIAL_INTERRUPT - sta INTRST bra @IRQexit @allSent: lda SERCTL ; All bytes sent - bit #TxEmpty + bit #TXEMPTY beq @exit1 bvs @exit1 stz TxDone + +@exit0: lda contrl - ora #RxIntEnable|ResetErr + ora #RXINTEN|RESETERR ; Re-enable receive interrupt sta SERCTL +@IRQexit: lda #SERIAL_INTERRUPT sta INTRST -@IRQexit: clc rts diff --git a/libsrc/lynx/uploader.s b/libsrc/lynx/uploader.s index df3e5df40..5ce21b489 100644 --- a/libsrc/lynx/uploader.s +++ b/libsrc/lynx/uploader.s @@ -40,14 +40,14 @@ cont1: bra loop1 read_byte: - bit SERCTL + bit SERCTL ; Check for RXRDY ($40) bvc read_byte lda SERDAT rts _UpLoaderIRQ: lda INTSET - and #$10 + and #SERIAL_INTERRUPT bne @L0 clc rts @@ -69,7 +69,7 @@ again: ; last action : clear interrupt ; exit: - lda #$10 + lda #SERIAL_INTERRUPT sta INTRST clc rts