]> git.sur5r.net Git - cc65/commitdiff
Renamed the comlynx source and driver to lynx-comlynx, so it follows the
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 20 Sep 2009 16:47:30 +0000 (16:47 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 20 Sep 2009 16:47:30 +0000 (16:47 +0000)
existing naming conventions.

git-svn-id: svn://svn.cc65.org/cc65/trunk@4201 b7a2c559-68d2-44c3-8de9-860c34a00d81

libsrc/lynx/Makefile
libsrc/lynx/comlynx.s [deleted file]
libsrc/lynx/lynx-comlynx.s [new file with mode: 0644]

index 76643b0b74e74235706e6384699cbfc0020ebdef..b355d9e8b58372d123b997f0f91bc4ab08fa4a0f 100644 (file)
@@ -46,7 +46,6 @@ CFLAGS        = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include
 # Object files
 
 OBJS =  cgetc.o         \
-        comlynx.o       \
         crt0.o          \
        ctype.o         \
         eeprom.o        \
@@ -65,7 +64,7 @@ JOYS = lynx-stdjoy.joy
 
 MOUS =
 
-SERS =
+SERS = lynx-comlynx.ser
 
 TGIS = lynx-160-102-16.tgi
 
diff --git a/libsrc/lynx/comlynx.s b/libsrc/lynx/comlynx.s
deleted file mode 100644 (file)
index 8b55e93..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-;
-; Serial driver for the Atari Lynx ComLynx port.
-;
-; Karri Kaksonen, 17.09.2009
-;
-
-       .include        "lynx.inc"
-       .include        "zeropage.inc"
-       .include        "ser-kernel.inc"
-       .include        "ser-error.inc"
-
-; ------------------------------------------------------------------------
-; Header. Includes jump table
-
-       .segment        "JUMPTABLE"
-
-       ; Driver signature
-       .byte   $73, $65, $72           ; "ser"
-       .byte   SER_API_VERSION         ; Serial API version number
-
-       ; Jump table.
-       .addr   INSTALL
-       .addr   UNINSTALL
-       .addr   OPEN
-       .addr   CLOSE
-       .addr   GET
-       .addr   PUT
-       .addr   STATUS
-       .addr   IOCTL
-       .addr   IRQ
-
-;----------------------------------------------------------------------------
-; Global variables
-;
-; The ring buffers will be at the fixed place
-; Tx buffer $200 - $2ff. Rx buffer $300 - $3ff.
-; This memory area can usually not be used for anything as the encryption
-; stuff needs it. But for this purpose it fits perfectly.
-
-       .bss
-
-TxBuffer = $0200
-RxBuffer = $0300
-RxPtrIn:       .res    1
-RxPtrOut:      .res    1
-TxPtrIn:       .res    1
-TxPtrOut:      .res    1
-contrl:                .res    1
-SerialStat:    .res    1
-TxDone:                .res    1
-
-       .code
-
-;----------------------------------------------------------------------------
-; INSTALL: Is called after the driver is loaded into memory.
-;
-; Must return an SER_ERR_xx code in a/x.
-
-INSTALL:
-       ; Set up IRQ vector ?
-
-;----------------------------------------------------------------------------
-; UNINSTALL: Is called before the driver is removed from memory.
-; No return code required (the driver is removed from memory on return).
-;
-
-UNINSTALL:
-
-;----------------------------------------------------------------------------
-; CLOSE: Close the port and disable interrupts. Called without parameters.
-; Must return an SER_ERR_xx code in a/x.
-
-CLOSE:
-       ; Disable interrupts
-       ; Done, return an error code
-       lda     #<SER_ERR_OK
-       ldx     #>SER_ERR_OK
-       rts
-
-;----------------------------------------------------------------------------
-; OPEN: A pointer to a ser_params structure is passed in ptr1.
-;
-; The Lynx has only two correct serial data formats:
-; 8 bits, parity mark, 1 stop bit
-; 8 bits, parity space, 1 stop bit
-;
-; It also has two wrong formats;
-; 8 bits, even parity, 1 stop bit
-; 8 bits, odd parity, 1 stop bit
-;
-; Unfortunately the parity bit includes itself in the calculation making
-; parity not compatible with the rest of the world.
-;
-; We can only specify a few baud rates.
-; Lynx has two non-standard speeds 31250 and 62500 which are
-; frequently used in games.
-;
-; The receiver will always read the parity and report parity errors.
-;
-; Must return an SER_ERR_xx code in a/x.
-
-OPEN:  
-       stz     RxPtrIn
-       stz     RxPtrOut
-       stz     TxPtrIn
-       stz     TxPtrOut
-
-       ; clock = 8 * 15625
-       lda     #%00011000
-       sta     TIM4CTLA
-       ldy     #SER_PARAMS::BAUDRATE
-       lda     (ptr1),y
-
-       ldx     #1
-       cmp     #SER_BAUD_62500
-       beq     setbaudrate
-
-       ldx     #2
-       cmp     #SER_BAUD_31250
-       beq     setbaudrate
-
-       ldx     #12
-       cmp     #SER_BAUD_9600
-       beq     setbaudrate
-
-       ldx     #25
-       cmp     #SER_BAUD_4800
-       beq     setbaudrate
-
-       ldx     #51
-       cmp     #SER_BAUD_2400
-       beq     setbaudrate
-
-       ldx     #103
-       cmp     #SER_BAUD_1200
-       beq     setbaudrate
-
-       ldx     #207
-       cmp     #SER_BAUD_600
-       beq     setbaudrate
-
-       ; clock = 6 * 15625
-       ldx     #%00011010
-       stx     TIM4CTLA
-
-       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
-       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     #>SER_ERR_BAUD_UNAVAIL
-       rts
-setprescaler:
-       stx     TIM4CTLA
-       bra     baudsuccess
-setbaudrate:
-       stx     TIM4BKUP
-baudsuccess:
-       ldx     #TxOpenColl|ParEven
-       stx     contrl
-       ldy     #SER_PARAMS::DATABITS   ; Databits
-       lda     (ptr1),y
-       cmp     #SER_BITS_8
-       bne     invparameter
-       ldy     #SER_PARAMS::STOPBITS   ; Stopbits
-       lda     (ptr1),y
-       cmp     #SER_STOP_1
-       bne     invparameter
-       ldy     #SER_PARAMS::PARITY     ; Parity
-       lda     (ptr1),y
-       cmp     #SER_PAR_NONE
-       beq     invparameter
-       cmp     #SER_PAR_MARK
-       beq     checkhs
-       cmp     #SER_PAR_SPACE
-       bne     @L0
-       ldx     #TxOpenColl
-       stx     contrl
-       bra     checkhs
-@L0:
-       ldx     #TxParEnable|TxOpenColl|ParEven
-       stx     contrl
-       cmp     #SER_PAR_EVEN
-       beq     checkhs
-       ldx     #TxParEnable|TxOpenColl
-       stx     contrl
-checkhs:
-       ldx     contrl
-       stx     SERCTL
-       ldy     #SER_PARAMS::HANDSHAKE  ; Handshake
-       lda     (ptr1),y
-       cmp     #SER_HS_NONE
-       bne     invparameter
-       lda     SERDAT
-        lda    contrl
-        ora    #RxIntEnable|ResetErr
-        sta    SERCTL
-       lda     #<SER_ERR_OK
-       ldx     #>SER_ERR_OK
-       rts
-invparameter:
-       lda     #<SER_ERR_INIT_FAILED
-       ldx     #>SER_ERR_INIT_FAILED
-       rts
-
-;----------------------------------------------------------------------------
-; GET: Will fetch a character from the receive buffer and store it into the
-; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is
-; returned.
-
-GET:
-       lda     RxPtrIn
-       cmp     RxPtrOut
-       bne     GetByte
-       lda     #<SER_ERR_NO_DATA
-       ldx     #>SER_ERR_NO_DATA
-       rts
-GetByte:
-       ldy     RxPtrOut
-       lda     RxBuffer,y      
-       inc     RxPtrOut
-       ldx     #$00
-       sta     (ptr1,x)
-       txa                     ; Return code = 0
-       rts
-
-;----------------------------------------------------------------------------
-; PUT: Output character in A.
-; Must return an SER_ERR_xx code in a/x.
-
-PUT:
-       tax
-       lda     TxPtrIn
-       ina
-       cmp     TxPtrOut
-       bne     PutByte
-       lda     #<SER_ERR_OVERFLOW
-       ldx     #>SER_ERR_OVERFLOW
-       rts
-PutByte:
-       ldy     TxPtrIn
-       txa
-       sta     TxBuffer,y
-       inc     TxPtrIn
-
-        bit    TxDone
-        bmi    @L1
-        php
-        sei
-        lda    contrl
-        ora    #TxIntEnable|ResetErr
-        sta    SERCTL       ; Allow TX-IRQ to hang RX-IRQ
-        sta    TxDone
-        plp
-@L1:
-       lda     #<SER_ERR_OK
-       tax
-       rts
-
-;----------------------------------------------------------------------------
-; STATUS: Return the status in the variable pointed to by ptr1.
-; Must return an SER_ERR_xx code in a/x.
-
-STATUS:
-       ldy     SerialStat
-       ldx     #$00
-       sta     (ptr1,x)
-       txa                     ; Return code = 0
-       rts
-
-;----------------------------------------------------------------------------
-; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
-; specific data in ptr1, and the ioctl code in A.
-; Must return an SER_ERR_xx code in a/x.
-
-IOCTL:
-       lda     #<SER_ERR_INV_IOCTL
-       ldx     #>SER_ERR_INV_IOCTL
-       rts
-
-;----------------------------------------------------------------------------
-; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
-; registers are already saved, no parameters are passed, but the carry flag
-; is clear on entry. The routine must return with carry set if the interrupt
-; was handled, otherwise with carry clear.
-;
-; Both the Tx and Rx interrupts are level sensitive instead of edge sensitive.
-; Due to this bug you have to disable the interrupt before clearing it.
-
-IRQ:
-               lda     INTSET          ; Poll all pending interrupts
-               and     #SERIAL_INTERRUPT
-        bne    @L0
-       clc
-       rts
-@L0:
-       bit     TxDone
-        bmi    @tx_irq     ; Transmit in progress
-        ldx    SERDAT
-        lda    SERCTL
-        and    #RxParityErr|RxOverrun|RxFrameErr|RxBreak
-        beq    @rx_irq
-        tsb    SerialStat  ; Save error condition
-        bit    #RxBreak
-        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
-@rx_irq:
-       lda     contrl
-        ora    #RxIntEnable|ResetErr
-        sta    SERCTL
-        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
-@tx_irq:
-        ldx    TxPtrOut    ; Has all bytes been sent?
-        cpx    TxPtrIn
-        beq    @allSent
-
-        lda    TxBuffer,x  ; Send next byte
-        sta    SERDAT
-        inc    TxPtrOut
-
-@exit1:
-        lda    contrl
-        ora    #TxIntEnable|ResetErr
-        sta    SERCTL
-        lda    #SERIAL_INTERRUPT
-        sta    INTRST
-        bra    @IRQexit
-
-@allSent:
-        lda    SERCTL       ; All bytes sent
-        bit    #TxEmpty
-        beq    @exit1
-        bvs    @exit1
-        stz    TxDone
-       lda     contrl
-        ora    #RxIntEnable|ResetErr
-        sta    SERCTL
-
-        lda    #SERIAL_INTERRUPT
-        sta    INTRST
-@IRQexit:
-       clc
-        rts
-
diff --git a/libsrc/lynx/lynx-comlynx.s b/libsrc/lynx/lynx-comlynx.s
new file mode 100644 (file)
index 0000000..8b55e93
--- /dev/null
@@ -0,0 +1,412 @@
+;
+; Serial driver for the Atari Lynx ComLynx port.
+;
+; Karri Kaksonen, 17.09.2009
+;
+
+       .include        "lynx.inc"
+       .include        "zeropage.inc"
+       .include        "ser-kernel.inc"
+       .include        "ser-error.inc"
+
+; ------------------------------------------------------------------------
+; Header. Includes jump table
+
+       .segment        "JUMPTABLE"
+
+       ; Driver signature
+       .byte   $73, $65, $72           ; "ser"
+       .byte   SER_API_VERSION         ; Serial API version number
+
+       ; Jump table.
+       .addr   INSTALL
+       .addr   UNINSTALL
+       .addr   OPEN
+       .addr   CLOSE
+       .addr   GET
+       .addr   PUT
+       .addr   STATUS
+       .addr   IOCTL
+       .addr   IRQ
+
+;----------------------------------------------------------------------------
+; Global variables
+;
+; The ring buffers will be at the fixed place
+; Tx buffer $200 - $2ff. Rx buffer $300 - $3ff.
+; This memory area can usually not be used for anything as the encryption
+; stuff needs it. But for this purpose it fits perfectly.
+
+       .bss
+
+TxBuffer = $0200
+RxBuffer = $0300
+RxPtrIn:       .res    1
+RxPtrOut:      .res    1
+TxPtrIn:       .res    1
+TxPtrOut:      .res    1
+contrl:                .res    1
+SerialStat:    .res    1
+TxDone:                .res    1
+
+       .code
+
+;----------------------------------------------------------------------------
+; INSTALL: Is called after the driver is loaded into memory.
+;
+; Must return an SER_ERR_xx code in a/x.
+
+INSTALL:
+       ; Set up IRQ vector ?
+
+;----------------------------------------------------------------------------
+; UNINSTALL: Is called before the driver is removed from memory.
+; No return code required (the driver is removed from memory on return).
+;
+
+UNINSTALL:
+
+;----------------------------------------------------------------------------
+; CLOSE: Close the port and disable interrupts. Called without parameters.
+; Must return an SER_ERR_xx code in a/x.
+
+CLOSE:
+       ; Disable interrupts
+       ; Done, return an error code
+       lda     #<SER_ERR_OK
+       ldx     #>SER_ERR_OK
+       rts
+
+;----------------------------------------------------------------------------
+; OPEN: A pointer to a ser_params structure is passed in ptr1.
+;
+; The Lynx has only two correct serial data formats:
+; 8 bits, parity mark, 1 stop bit
+; 8 bits, parity space, 1 stop bit
+;
+; It also has two wrong formats;
+; 8 bits, even parity, 1 stop bit
+; 8 bits, odd parity, 1 stop bit
+;
+; Unfortunately the parity bit includes itself in the calculation making
+; parity not compatible with the rest of the world.
+;
+; We can only specify a few baud rates.
+; Lynx has two non-standard speeds 31250 and 62500 which are
+; frequently used in games.
+;
+; The receiver will always read the parity and report parity errors.
+;
+; Must return an SER_ERR_xx code in a/x.
+
+OPEN:  
+       stz     RxPtrIn
+       stz     RxPtrOut
+       stz     TxPtrIn
+       stz     TxPtrOut
+
+       ; clock = 8 * 15625
+       lda     #%00011000
+       sta     TIM4CTLA
+       ldy     #SER_PARAMS::BAUDRATE
+       lda     (ptr1),y
+
+       ldx     #1
+       cmp     #SER_BAUD_62500
+       beq     setbaudrate
+
+       ldx     #2
+       cmp     #SER_BAUD_31250
+       beq     setbaudrate
+
+       ldx     #12
+       cmp     #SER_BAUD_9600
+       beq     setbaudrate
+
+       ldx     #25
+       cmp     #SER_BAUD_4800
+       beq     setbaudrate
+
+       ldx     #51
+       cmp     #SER_BAUD_2400
+       beq     setbaudrate
+
+       ldx     #103
+       cmp     #SER_BAUD_1200
+       beq     setbaudrate
+
+       ldx     #207
+       cmp     #SER_BAUD_600
+       beq     setbaudrate
+
+       ; clock = 6 * 15625
+       ldx     #%00011010
+       stx     TIM4CTLA
+
+       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
+       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     #>SER_ERR_BAUD_UNAVAIL
+       rts
+setprescaler:
+       stx     TIM4CTLA
+       bra     baudsuccess
+setbaudrate:
+       stx     TIM4BKUP
+baudsuccess:
+       ldx     #TxOpenColl|ParEven
+       stx     contrl
+       ldy     #SER_PARAMS::DATABITS   ; Databits
+       lda     (ptr1),y
+       cmp     #SER_BITS_8
+       bne     invparameter
+       ldy     #SER_PARAMS::STOPBITS   ; Stopbits
+       lda     (ptr1),y
+       cmp     #SER_STOP_1
+       bne     invparameter
+       ldy     #SER_PARAMS::PARITY     ; Parity
+       lda     (ptr1),y
+       cmp     #SER_PAR_NONE
+       beq     invparameter
+       cmp     #SER_PAR_MARK
+       beq     checkhs
+       cmp     #SER_PAR_SPACE
+       bne     @L0
+       ldx     #TxOpenColl
+       stx     contrl
+       bra     checkhs
+@L0:
+       ldx     #TxParEnable|TxOpenColl|ParEven
+       stx     contrl
+       cmp     #SER_PAR_EVEN
+       beq     checkhs
+       ldx     #TxParEnable|TxOpenColl
+       stx     contrl
+checkhs:
+       ldx     contrl
+       stx     SERCTL
+       ldy     #SER_PARAMS::HANDSHAKE  ; Handshake
+       lda     (ptr1),y
+       cmp     #SER_HS_NONE
+       bne     invparameter
+       lda     SERDAT
+        lda    contrl
+        ora    #RxIntEnable|ResetErr
+        sta    SERCTL
+       lda     #<SER_ERR_OK
+       ldx     #>SER_ERR_OK
+       rts
+invparameter:
+       lda     #<SER_ERR_INIT_FAILED
+       ldx     #>SER_ERR_INIT_FAILED
+       rts
+
+;----------------------------------------------------------------------------
+; GET: Will fetch a character from the receive buffer and store it into the
+; variable pointed to by ptr1. If no data is available, SER_ERR_NO_DATA is
+; returned.
+
+GET:
+       lda     RxPtrIn
+       cmp     RxPtrOut
+       bne     GetByte
+       lda     #<SER_ERR_NO_DATA
+       ldx     #>SER_ERR_NO_DATA
+       rts
+GetByte:
+       ldy     RxPtrOut
+       lda     RxBuffer,y      
+       inc     RxPtrOut
+       ldx     #$00
+       sta     (ptr1,x)
+       txa                     ; Return code = 0
+       rts
+
+;----------------------------------------------------------------------------
+; PUT: Output character in A.
+; Must return an SER_ERR_xx code in a/x.
+
+PUT:
+       tax
+       lda     TxPtrIn
+       ina
+       cmp     TxPtrOut
+       bne     PutByte
+       lda     #<SER_ERR_OVERFLOW
+       ldx     #>SER_ERR_OVERFLOW
+       rts
+PutByte:
+       ldy     TxPtrIn
+       txa
+       sta     TxBuffer,y
+       inc     TxPtrIn
+
+        bit    TxDone
+        bmi    @L1
+        php
+        sei
+        lda    contrl
+        ora    #TxIntEnable|ResetErr
+        sta    SERCTL       ; Allow TX-IRQ to hang RX-IRQ
+        sta    TxDone
+        plp
+@L1:
+       lda     #<SER_ERR_OK
+       tax
+       rts
+
+;----------------------------------------------------------------------------
+; STATUS: Return the status in the variable pointed to by ptr1.
+; Must return an SER_ERR_xx code in a/x.
+
+STATUS:
+       ldy     SerialStat
+       ldx     #$00
+       sta     (ptr1,x)
+       txa                     ; Return code = 0
+       rts
+
+;----------------------------------------------------------------------------
+; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
+; specific data in ptr1, and the ioctl code in A.
+; Must return an SER_ERR_xx code in a/x.
+
+IOCTL:
+       lda     #<SER_ERR_INV_IOCTL
+       ldx     #>SER_ERR_INV_IOCTL
+       rts
+
+;----------------------------------------------------------------------------
+; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
+; registers are already saved, no parameters are passed, but the carry flag
+; is clear on entry. The routine must return with carry set if the interrupt
+; was handled, otherwise with carry clear.
+;
+; Both the Tx and Rx interrupts are level sensitive instead of edge sensitive.
+; Due to this bug you have to disable the interrupt before clearing it.
+
+IRQ:
+               lda     INTSET          ; Poll all pending interrupts
+               and     #SERIAL_INTERRUPT
+        bne    @L0
+       clc
+       rts
+@L0:
+       bit     TxDone
+        bmi    @tx_irq     ; Transmit in progress
+        ldx    SERDAT
+        lda    SERCTL
+        and    #RxParityErr|RxOverrun|RxFrameErr|RxBreak
+        beq    @rx_irq
+        tsb    SerialStat  ; Save error condition
+        bit    #RxBreak
+        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
+@rx_irq:
+       lda     contrl
+        ora    #RxIntEnable|ResetErr
+        sta    SERCTL
+        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
+@tx_irq:
+        ldx    TxPtrOut    ; Has all bytes been sent?
+        cpx    TxPtrIn
+        beq    @allSent
+
+        lda    TxBuffer,x  ; Send next byte
+        sta    SERDAT
+        inc    TxPtrOut
+
+@exit1:
+        lda    contrl
+        ora    #TxIntEnable|ResetErr
+        sta    SERCTL
+        lda    #SERIAL_INTERRUPT
+        sta    INTRST
+        bra    @IRQexit
+
+@allSent:
+        lda    SERCTL       ; All bytes sent
+        bit    #TxEmpty
+        beq    @exit1
+        bvs    @exit1
+        stz    TxDone
+       lda     contrl
+        ora    #RxIntEnable|ResetErr
+        sta    SERCTL
+
+        lda    #SERIAL_INTERRUPT
+        sta    INTRST
+@IRQexit:
+       clc
+        rts
+