Subversion Repositories MB01 Project

Rev

Blame | Last modification | View Log | Download | RSS feed

;;
;; Copyright (c) 2016 Marco Granati <mg@unet.bz>
;;
;; Permission to use, copy, modify, and distribute this software for any
;; purpose with or without fee is hereby granted, provided that the above
;; copyright notice and this permission notice appear in all copies.
;;
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
;; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
;; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
;; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
;; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
;; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
;;

;; name: sp2.asm        
;; rev.: 2017/07/04
;; bios C816 version v1.0

;; serial port 65C51 & 16C550 handler

_ADDSER_INC_    .SET    1

        .INCLUDE inc\global.inc
        .INCLUDE inc\dirp00.inc
        .INCLUDE inc\dirp05.inc

.LIST   on

        .CODEF8
        
        .LONGA  off
        .LONGI  off

; set serial port #2 - 65C51
; A=mode
spset2:
        sei                     ; disable interrupt
        phd
        pea     #DP05ADDR
        pld
        sta     spmode3         ; save mode
        tax
        sta     !ACIASR         ; software reset
        lda     #ACIACMDOFF     ; disable all
        sta     !ACIACMD
        lda     !ACIADR         ; clear flags
        lda     !ACIASR
        and     #01000000B      ; get /DSR status
        beq     ?dsrl
        tsb     splin3          ; /DSR high
        bra     ?cts
?dsrl:  lda     #01000000B
        trb     splin3          ; /DSR low
?cts:   ldy     #$80
        lda     #00001000B      ; check /CTS line level: PA<3>
        bit     !VIA2+VIAPRANH
        beq     ?ctsl           ; /CTS is low
        tya
        tsb     splin3          ; /CTS is high
        bra     ?br
?ctsl:  tya
        trb     splin3          ; /CTS is low
?br:    txa                     ; <1:0> = baud rate select
        and     #00000011B
        sta     sptmp3
        lda     !VIA2+VIAPRANH
        and     #11111000B      ; /RTS low
        ora     sptmp3
        sta     !VIA2+VIAPRANH  
        lda     #00010000B      ; 8 bits, 1 stop bit, divisor = 1/16
        sta     !ACIACTRL       
        txa                     ; mode
        and     #00001100B      ; mask on bits 3 & 2 (parity mode)
        asl     a               ; shift <3:2> to <6:5>
        asl     a
        asl     a
        ora     #00000101B      ; enable all int., /DTR=low
        sta     sptmp3          ; byte for command register
        stz     sppause3        ; init work area
        stz     spout3
        stz     spstat3
        bit     spmode3
        CPU16                   ; init buffer's pointer's
        bvs     ?hw             ; hardware handshake
        lda     #NGUARD31
        ldy     #NFREE31
        bra     ?do
?hw:    lda     #NGUARD32
        ldy     #NFREE32
?do:    sta     icntmax3
        sty     icntmin3
        sec
        lda     #SIBUFSIZ3
        sbc     icntmax3
        sta     icntmax3
        stz     ibuftail3
        stz     ibufhead3
        stz     ibufcnt3
        stz     obuftail3
        stz     obufhead3
        stz     obufcnt3
        CPU08
        bit     spmode3
        bpl     ?ok             ; no handshake
        bvc     ?ok             ; software handshake
        bit     splin3          ; check /DSR line
        bvc     ?ok             ; remote terminal is connected
        ;lda    #$20
        ;tsb    spstat3         ; remote terminal not connected now
?ok:    lda     .ABS.ACIADR     ; discard any pending received data
        lda     .ABS.ACIASR     ; read current interrupt status
        lda     sptmp3          ; enable interrupts
        sta     .ABS.ACIACMD
        pld
        cli
        rts

; reset serial port #2 - 65C51
spres2:
        sta     !ACIASR         ; software reset
        lda     #ACIACMDOFF     ; disable all
        sta     !ACIACMD
        lda     !ACIADR         ; clear flags
        lda     !ACIASR
        rts
        
; send A to serial port 65C51
spput2:
        sei                     ; disable interrupt
        phd
        pea     #DP05ADDR
        pld
        stx     sptmp3          ; save X reg. 
        ldy     #0              ; Y = 0
        INDEX16
        ldx     obufcnt3
        cpx     #SOBUFSIZ3      ; output buffer is full?
        bcc     ?str            ; no, store byte
        bit     splin3
        bvc     ?done           ; exit with CF=1, Y=0: output buffer is full
        dey
        bra     ?done           ; exit with CF=1, Y=$FF: remote terminal off
?str:   inx                     ; update count
        stx     obufcnt3
        ldx     obuftail3       ; output buffer tail pointer
        sta     >SOBUFADDR3,x   ; store byte in output buffer
        inx                     ; update tail pointer
        cpx     #SOBUFSIZ3      
        bcc     ?upd
        tyx                     ; circular queue
?upd:   stx     obuftail3

        ; here at least one byte to send so check if tx interrupt is enabled
        ;
        xba                     ; save A
        lda     !ACIACMD
        bit     #00000100B      ; check CMD<2>
        bne     ?xba            ; tx interrupt enabled
        bit     sppause3
        bvs     ?xba            ; local pause is on, can't enable tx interrupt
        lda     #00001000B      ; first clear CMD<3>    
        trb     !ACIACMD
        lda     #00000100B      ; then set CMD<2>       
        tsb     !ACIACMD        ; re-enable tx interrupt        
?xba:   xba                     ; return A = sent data
        clc                     ; no error
?done:  INDEX08
        ldx     sptmp3          ; restore X reg.        
        pld
        cli
        rts

spget2:
        sei                     ; disable interrupt
        phd
        pea     #DP05ADDR
        pld
        sec                     ; assume error
        stx     sptmp3          ; save X reg.
        lda     spstat3         ; rx pending error?
        bmi     ?done           ; yes, exit
        lda     #0              ; assume no data available
        tay                     ; Y = 0
        INDEX16
        ldx     ibufcnt3        ; available new data?
        beq     ?done           ; input queue is empty (exit with CF=1, A=0)
        dex                     ; update count
        stx     ibufcnt3
        ldx     ibufhead3       ; head input buffer pointer
        lda     >SIBUFADDR3,x   ; get byte from queue
        inx                     ; update head pointer
        cpx     #SIBUFSIZ3
        bcc     ?upd
        tyx                     ; circular queue
?upd:   stx     ibufhead3
        bit     sppause3        ; remote pause is on?
        bpl     ?ok             ; no
        ldx     ibufcnt3        
        cpx     icntmin3        ; can clear remote pause?
        bcs     ?ok             ; no
        bit     spmode3         ; handshake is on?
        bpl     ?ok             ; no
        xba                     ; save data
        bvs     ?hw             ; hardware handshake
        lda     #SPXON          ; software handshake: send an XON
        sta     spout3          ; XON is deffered
        lda     #00001100B      ; re-enable tx interrupt
        trb     !ACIACMD
        lda     #00000100B
        tsb     !ACIACMD        
        bra     ?xba
?hw:    lda     #$04            ; hardware handshake: set RTS=0
        trb     .ABS.VIA2+VIAPRANH
        lda     #$80
        trb     sppause3        ; clear remote pause flag
?xba:   xba                     ; recover data
?ok:    clc
?done:  INDEX08
        ldx     sptmp3          ; restore X reg.
        pld
        cli
        rts                     ; CF=1 & A=0 mean: no data available 

;------------------

; set serial port 16C550
; A=mode
spset3:
        sei                     ; disable interrupt
        phd
        pea     #DP05ADDR
        pld
        sta     spmode4         ; save mode
        stz     !UART_LCR
        stz     !UART_IER       ; disable all UART interrupts
        stz     !UART_MCR       ; /RTS and /DTR high
        stz     !UART_FCR       ; disable FIFO
        ldx     .ABS.UART_RXTX  ; clear any pending interrupt
        ldx     .ABS.UART_LSR
        ldx     .ABS.UART_IIR   
        ldx     #$80            ; set DLAB = 1 in LCR
        stx     .ABS.UART_LCR
        tay                     ; save mode
        and     #00000011B      ; baud rate select
        tax
        lda     >?div,x         ; select divisor
        sta     !UART_DLL       ; set low latch
        stz     !UART_DLH       ; set high latch
        tya                     ; mode
        and     #00001100B      ; mask on bits 3 & 2 (parity mode)
        asl     a               ; shift <3:2> to <4:3>
        ora     #00000011B      ; 8N1 (8 bits data, 1 stop bit)
        sta     !UART_LCR
        lda     !UART_MSR       ; get /DSR & /CTS status
        tax
        asl     a
        asl     a               ; <7>: /DSR, <6>: /CTS
        and     #11000000B
        eor     #11000000B
        sta     splin4          ; update line status
        stz     sppause4        ; init work area
        stz     spstat4
        lda     #1              ; set tx count = 1
        sta     spcnt4
        CPU16                   ; init buffer's pointer's
        lda     #NGUARD32
        ldy     #NFREE32
        sta     icntmax4
        sty     icntmin4
        sec
        lda     #SIBUFSIZ4
        sbc     icntmax4
        sta     icntmax4
        stz     ibuftail4
        stz     ibufhead4
        stz     ibufcnt4
        stz     obuftail4
        stz     obufhead4
        stz     obufcnt4
        CPU08
        lda     #00000011B      ; set /RTS = /DTR low
        sta     !UART_MCR
        lda     #$20
        bit     spmode4
        bne     ?nof            ; no fifo
        lda     #1
        sta     !UART_FCR
        lda     #10000111B      ; enable fifo, reset rx/tx fifo, trigger level = 8      
        sta     !UART_FCR       ; rx fifo trigger = 8
        lda     #16             ; set tx count = 16 in FIFO mode
        sta     spcnt4  
?nof:   lda     !UART_LSR       ; again reset all interrupts
        lda     !UART_MSR       
        lda     !UART_IIR
        lda     #00001111B      ; enable all interrupts
        sta     !UART_IER       
        pld
        cli
        rts

;               19.200, 38.400, 57.600, 115.200
?div:   .DB     6,      3,      2,      1 

spres3:
        ;stz    !UART_LCR
        stz     !UART_IER       ; clear all interrupts
        ;stz    !UART_MCR       ; /RTS and /DTR high
        lda     #10000111B      ; enable fifo, reset rx/tx fifo
        stz     !UART_FCR       ; rx fifo trigger = 8
        lda     !UART_LSR
        lda     !UART_MSR
        rts

; send A to serial port 16C550
spput3:
        sei                     ; disable interrupt
        phd
        pea     #DP05ADDR
        pld
        stx     sptmp4          ; save X reg. 
        ldy     #0              ; Y = 0
        INDEX16
        ldx     obufcnt4
        cpx     #SOBUFSIZ4      ; output buffer is full?
        bcc     ?str            ; no, store byte
        bit     splin4          ; test /DSR line status
        bmi     ?ofl            ; remote terminal disconnected
        xba                     ; save A
        lda     #00000010B      ; enable TX interrupt...
        tsb     !UART_IER       ; ... hoping that ISR can make room in output buffer
        xba
        bra     ?done           ; exit with CF=1, Y=0: output buffer is full
?ofl:   dey                     ; /DSR high
        xba
        lda     #00000010B
        trb     !UART_IER       ; disable tx interrupt  
        xba
        bra     ?done           ; exit with CF=1, Y=$FF: remote terminal offline
?str:   inx                     ; update count
        stx     obufcnt4
        ldx     obufhead4       ; output buffer head pointer
        sta     >SOBUFADDR4,x   ; store byte in output buffer
        inx                     ; update head pointer
        cpx     #SOBUFSIZ4      
        bcc     ?upd
        tyx                     ; circular queue
?upd:   stx     obufhead4
        xba     
        ;lda    #00000010B
        ;trb    !UART_IER       ; re-enable tx interrupt        
        lda     #00000010B
        tsb     !UART_IER       ; re-enable tx interrupt        
        xba                     ; return A = sent data
        clc                     ; no error
?done:  INDEX08
        ldx     sptmp4          ; restore X reg.        
        pld
        cli
        rts

spget3:
        sei                     ; disable interrupt
        phd
        pea     #DP05ADDR
        pld
        sec                     ; assume error
        stx     sptmp4          ; save X reg.
        lda     spstat4         ; rx pending error?
        bmi     ?done           ; yes, exit (CF = 1, A = error code)
        lda     #0              ; assume no data available
        tay                     ; Y = 0
        INDEX16
        ldx     ibufcnt4        ; available new data?
        beq     ?done           ; input queue is empty (exit with CF=1, A=0)
        dex                     ; update count
        stx     ibufcnt4
        ldx     ibuftail4       ; tail input buffer pointer
        lda     >SIBUFADDR4,x   ; get byte from queue
        inx                     ; update tail pointer
        cpx     #SIBUFSIZ4
        bcc     ?upd
        tyx                     ; circular queue
?upd:   stx     ibuftail4
        bit     spmode4         ; handshake is on?
        bpl     ?ok             ; no, exit
        bit     sppause4        ; remote pause is on?
        bpl     ?ok             ; no, exit
        ldx     ibufcnt4        
        cpx     icntmin4        ; can clear remote pause?
        bcs     ?ok             ; no, exit
        xba                     ; save data
        lda     #00000010B      ; hardware handshake...
        tsb     !UART_MCR       ; ...set /RTS=0
        lda     #$80
        trb     sppause4        ; clear remote pause flag
        lda     #00000010B      ; set IER<1>
        tsb     !UART_IER       ; re-enable tx interrupt        
        xba                     ; recover data
?ok:    clc                     ; no error
?done:  CPU08
        ldx     sptmp4          ; restore X reg.
        pld
        cli
        rts                     ; CF=1 & A=0 mean: no data available 

;------------------

lspget2:
        .PUBLIC lspget2
        phb                     ; save DBR
        ldy     #0              ; set DBR = $00
        phy
        plb
        txy
        bne     ?get2
        jsr     spget3
        plb
        rtl
?get2:  jsr     spget2
        plb
        rtl
        
lspput2:
        .PUBLIC lspput2
        phb                     ; save DBR
        ldy     #0              ; set DBR = $00
        phy
        plb
        txy
        bne     ?put2
        jsr     spput3
        plb
        rtl
?put2:  jsr     spput2
        plb
        rtl

lspset2:
        .PUBLIC lspset2
        phb                     ; save DBR
        ldy     #0              ; set DBR = $00
        phy
        plb
        txy
        bne     ?set2
        jsr     spset3
        plb
        rtl     
?set2:  jsr     spset2
        plb
        rtl

lspres2:
        .PUBLIC lspres2
        phb                     ; save DBR
        ldy     #0              ; set DBR = $00
        phy
        plb
        txy
        bne     ?res2
        jsr     spres3
        plb
        rtl             
?res2:  jsr     spres2
        plb
        rtl

test0:
        sei
        phd
        pea     #DP05ADDR
        pld
        sta     sptmp4
        lda     #0
        sta     !UART_FCR
        
        lda     sptmp4
?00:    dec     a
        bne     ?00
        
        lda     #'@'
        ldx     #15
        xba
?01:    lda     #$20
        bit     !UART_LSR
        nop
        nop
        nop
        nop
        beq     ?01

        lda     sptmp4
?02:    dec     a
        bne     ?02
        
        xba
        sta     !UART_RXTX
        inc     a
        xba
        
        lda     sptmp4
?02a:   dec     a
        bne     ?02a

        dex
        bne     ?01

?03:    lda     #$20
        bit     !UART_LSR
        nop
        nop
        nop
        nop
        beq     ?03

        lda     sptmp4
?02b:   dec     a
        bne     ?02b
        
        lda     #$0D
        sta     !UART_RXTX
        lda     sptmp4
        pld
        cli
        brk

test1:
        sei
        phd
        pea     #DP05ADDR
        pld
        sta     sptmp4
        lda     #1
        sta     !UART_FCR
        
        lda     sptmp4
?00:    dec     a
        bne     ?00
        
        lda     #'@'
        ldx     #15
        xba
?01:    lda     #$20
        bit     !UART_LSR
        nop
        nop
        nop
        nop
        beq     ?01

        lda     sptmp4
?02:    dec     a
        bne     ?02
        
?0l:    xba
        sta     !UART_RXTX
        inc     a
        xba
        
        lda     sptmp4
?02a:   dec     a
        bne     ?02a

        dex
        bne     ?0l
        
        lda     #$0D
        sta     !UART_RXTX
        lda     sptmp4
        pld
        cli
        brk

test2:
        sei
        phd
        pea     #DP05ADDR
        pld
        ldy     #0
        lda     #1
        sta     !UART_FCR       
?00:    lda     #'@'
        ldx     #15
        xba
?01:    lda     #$20
        bit     !UART_LSR
        nop
        nop
        nop
        nop
        beq     ?01

?ll:    xba
        sta     !UART_RXTX
        inc     a
        xba
        dex
        bne     ?ll
        
        lda     #$0D
        sta     !UART_RXTX
        dey
        bne     ?00
        pld
        cli
        brk

;==========================================
; UM245R

umgetcmd:
        .PUBLIC umgetcmd

        lda     #$40
        trb     usbum           ; clear bit <6>: fifo data not available
        bit     usbum
        bmi     ?cmd            ; already connected: check command
        
        ; check connession request
        ldx     #7
?chk1:  lda     usbbuf,x
        cmp     >?usbconn,x
        beq     ?nxt
?nack:  lda     #$55            ; NACK
        sta     !UM245R
        rtl
?nxt:   dex
        bpl     ?chk1
        lda     #$AA            ; ACK
        sta     !UM245R
        lda     #$80
        tsb     usbum
        rtl
?cmd:   ldx     #(?usbtab2 - ?usbtab1 - 1)
        lda     usbbuf
?cmdl:  cmp     >?usbtab1,x
        beq     ?cmd2
        dex
        bpl     ?cmdl
        bmi     ?nack           ; not found
?cmd2:  lda     usbbuf+1
        cmp     >?usbtab2,x
        bne     ?nack           ; not found
        txa
        asl     a
        tax
        lda     #CA2IFRB        ; disable CA2 interrupt
        sta     !VIA2+VIAIER
        sta     !VIA2+VIAIFR
        jsr     usbsndack
        jsr     (?umjmp,x)
        sei
        lda     #SETFRB.OR.CA2IFRB ; enable CA2 interrupt
        sta     !VIA2+VIAIER
        sta     !VIA2+VIAIFR
        rtl

?umjmp:
        .DW     usbgetfmw

?usbconn:
        .DB     $87, $E9, $5D, $93, $B7, $57, $7D, $3B

?usbtab1:
        .DB     $99

?usbtab2:
        .DB     $51


; get firmware (512K)
usbgetfmw:
        cli
        stz     usbptr
        stz     usbptr+1
        lda     #$70
        sta     usbptr+2        ; put firmware in bank $30
        stz     usbsiz          ; full 64K bank
        stz     usbsiz+1
        lda     #$08            ; 8 banks
        sta     usbtmp
?lp:    lda     #$08
        sec
        sbc     usbtmp
        pha
        phk
        pea     #!?fmt1
        lda     #5
        pha
        BPRINTF
        jsr     usbgetblk
        bcs     ?err            ; error
        jsr     usbsndack
        SCNPRINT
        .DB     'done.', 13, 0
        inc     usbptr+2
        dec     usbtmp
        bne     ?lp

        lda     #$70
        sta     usbptr+2
        stz     usbcmp
        lda     #$08            ; 8 banks
        sta     usbtmp
?lp2:   lda     #$08
        sec
        sbc     usbtmp
        pha
        phk
        pea     #!?fmt3
        lda     #5
        pha
        BPRINTF
        
        ;jsr    usbcmpblk
        ;bcs    ?err            ; error
        ;bit    usbcmp
        ;bpl    ?ok
        ;jsr    usbsndnack
        ;bra    ?err
?ok:    ;jsr    usbsndack

        jsr     usbputbank
        bcs     ?err

        SCNPRINT
        .DB     'done.', 13, 0
        inc     usbptr+2
        dec     usbtmp
        bne     ?lp2
        
.COMMENT @
        ; send back for check
        lda     #$08            ; 8 banks
        sta     usbtmp
        lda     #$70
        sta     usbptr+2
?lp1:   lda     #$08
        sec
        sbc     usbtmp
        pha
        phk
        pea     #!?fmt2
        lda     #5
        pha
        BPRINTF
        ;jsr    usbputblk
        jsr     usbputbank
        ;jsr    usbrx
        bcs     ?err
        ;bne    ?err            ; NACK
        SCNPRINT
        .DB     'done.', 13, 0
        inc     usbptr+2
        dec     usbtmp
        bne     ?lp1
@

        ; wait final ACK
        jsr     usbrx
        bcs     ?err
        bne     ?err            ; NACK
        SCNPRINT
        .DB     'OK.', 13, 0
        rts
?err:
        SCNPRINT
        .DB     'error.', 13, 0
        rts

?fmt1:  .DB     'get firmware bank %bu...', 0
?fmt2:  .DB     'send back    bank %bu...', 0
?fmt3:  .DB     'verf. firmw. bank %bu...', 0

; get block: size in usbsiz, dest in usbptr     
usbgetblk:
        ldy     #0
        INDEX16
        ldx     usbsiz
        lda     #CA2IFRB        ; check CA2 flag
?lp:    bit     !VIA2+VIAPRANH  ; check /TXE
        bvs     ?err            ; /TXE is high: disconnession?
        bit     VIA2+VIAIFR     ; check CA2 flag
        beq     ?lp
        sta     !VIA2+VIAIFR    ; clear CA2 flag
        xba
        lda     !UM245R
        sta     [usbptr],y
        xba
        iny
        dex
        bne     ?lp
        clc
        INDEX08
        rts
?err:   CPU08SEC
        rts

; cmp block: size in usbsiz, dest in usbptr     
usbcmpblk:
        ldy     #0
        INDEX16
        ldx     usbsiz
        lda     #CA2IFRB        ; check CA2 flag
?lp:    bit     !VIA2+VIAPRANH  ; check /TXE
        bvs     ?err            ; /TXE is high: disconnession?
        bit     VIA2+VIAIFR     ; check CA2 flag
        beq     ?lp
        sta     !VIA2+VIAIFR    ; clear CA2 flag
        xba
        lda     !UM245R
        cmp     [usbptr],y
        beq     ?02
        lda     #$80
        sta     usbcmp
?02:    xba
        iny
        dex
        bne     ?lp
        clc
        INDEX08
        rts
?err:   CPU08SEC
        rts

; put a full: source in usbptr  
usbputbank:
        sei
        ldy     #0
?lp:    lda     !VIA2+VIAPRANH  ; check /TXE
        cmp     !VIA2+VIAPRANH
        bne     ?lp
        asl     a
        bmi     ?lp
        lda     [usbptr],y
        sta     >UM245R 
        iny
        bne     ?lp
        ;jsr    usbrx
        ;bcs    ?rts
        ;bne    ?err            ; NACK
        inc     usbptr+1
        bne     ?lp
        clc
?rts:   cli     
        rts
?err:   sec
        cli
        rts

; put block: size in usbsiz, dest in usbptr     
usbputblk:
        ldy     #0
        INDEX16
        ldx     usbsiz
;       bra     ?lp
;?lp0:  bit     !VIA2+VIAPRANH  ; check /TXE
;       bvs     ?lp
;       bvc     ?lp0
?lp:    bit     !VIA2+VIAPRANH  ; check /TXE
        ;cmp    !VIA2+VIAPRANH
        ;bne    ?lp
        ;asl    a
        ;bmi    ?lp             ; /TXE is high
        bvs     ?lp
        lda     [usbptr],y
        sta     !UM245R
        iny
        dex
        bne     ?lp
        clc
        INDEX08
        rts

; send nack
usbsndnack:
        lda     #$55
        bra     usbsnd

; send ack
usbsndack:
        lda     #$AA

; send a byte
usbsnd:
?lp:    bit     !VIA2+VIAPRANH  ; check /TXE
        bvs     ?lp             ; /TXE is high
        sta     !UM245R
        rts

usbrx:
        lda     #CA2IFRB        ; check CA2 flag
?lp:    bit     !VIA2+VIAPRANH  ; check /TXE
        bvs     ?err            ; /TXE is high: disconnession?
        bit     VIA2+VIAIFR     ; check CA2 flag
        beq     ?lp
        sta     !VIA2+VIAIFR    ; clear CA2 flag
        lda     !UM245R
        cmp     #$AA
        clc
        rts
?err:   sec
        rts