]> git.sur5r.net Git - cc65/blobdiff - libsrc/c64/c64-swlink.s
fix comments
[cc65] / libsrc / c64 / c64-swlink.s
index 3fc4055e638f5e384efde9d8b7496bf76077c680..9f1b23c5b45a177cecb113395458a2486997248a 100644 (file)
 ; Driver signature
 
         .byte   $73, $65, $72           ; "ser"
-        .byte   $00                     ; Serial API version number
+        .byte   SER_API_VERSION         ; Serial API version number
 
 ; Jump table.
 
         .word   INSTALL
         .word   UNINSTALL
-        .word   PARAMS
+        .word   OPEN
+        .word   CLOSE
         .word   GET
         .word   PUT
-        .word   PAUSE
-       .word   UNPAUSE
         .word   STATUS
         .word   IOCTL
+        .word   IRQ
 
 ;----------------------------------------------------------------------------
 ; I/O definitions
@@ -57,25 +57,24 @@ ACIA_DATA       = ACIA+0        ; Data register
 ACIA_STATUS     = ACIA+1        ; Status register
 ACIA_CMD        = ACIA+2        ; Command register
 ACIA_CTRL       = ACIA+3        ; Control register
-ACIA_CLOCK      = ACIA+7        ; Turbo232 external baud-rate generator
 
 ;----------------------------------------------------------------------------
 ;
 ; Global variables
 ;
 
+; We reuse the RS232 zero page variables for the driver, since the ROM
+; routines cannot be used together with this driver.
+RecvHead        = $B5           ; Head of receive buffer
+RecvTail        = $BD           ; Tail of receive buffer
+RecvFreeCnt     = $F7           ; Number of bytes in receive buffer
+SendHead        = $F8           ; Head of send buffer
+SendTail        = $F9           ; Tail of send buffer
+SendFreeCnt     = $FA           ; Number of bytes free in send buffer
+
 .bss
-DropCnt:       .res    4       ; Number of bytes lost from rx buffer full
 Stopped:       .res    1       ; Flow-stopped flag
 RtsOff:                .res    1       ;
-Errors:                .res    1       ; Number of bytes received in error, low byte
-RecvHead:      .res    1       ; Head of receive buffer
-RecvTail:      .res    1       ; Tail of receive buffer
-RecvFreeCnt:   .res    1       ; Number of bytes in receive buffer
-SendHead:      .res    1       ; Head of send buffer
-SendTail:      .res    1       ; Tail of send buffer
-SendFreeCnt:   .res    1       ; Number of bytes free in send buffer
-BaudCode:      .res    1       ; Current baud in effect
 
 ; Send and receive buffers: 256 bytes each
 RecvBuf:       .res    256
@@ -95,15 +94,15 @@ BaudTable:                      ; bit7 = 1 means setting is invalid
         .byte   $FF             ; SER_BAUD_75
         .byte   $FF             ; SER_BAUD_110
         .byte   $FF             ; SER_BAUD_134_5
-        .byte   $FF             ; SER_BAUD_150
+        .byte   $02             ; SER_BAUD_150
         .byte   $05             ; SER_BAUD_300
         .byte   $06             ; SER_BAUD_600
         .byte   $07             ; SER_BAUD_1200
         .byte   $FF             ; SER_BAUD_1800
         .byte   $08             ; SER_BAUD_2400
-        .byte   $FF             ; SER_BAUD_3600
+        .byte   $09             ; SER_BAUD_3600
         .byte   $0A             ; SER_BAUD_4800
-        .byte   $FF             ; SER_BAUD_7200
+        .byte   $0B             ; SER_BAUD_7200
         .byte   $0C             ; SER_BAUD_9600
         .byte   $0E             ; SER_BAUD_19200
         .byte   $0F             ; SER_BAUD_38400
@@ -128,36 +127,6 @@ ParityTable:
         .byte   $A0             ; SER_PAR_MARK
         .byte   $E0             ; SER_PAR_SPACE
 
-HandshakeTable:                 ; bit7 = 1 means that setting is invalid
-        .byte   $FF             ; SER_HS_NONE
-        .byte   $00             ; SER_HS_HW
-        .byte   $FF             ; SER_HS_SW
-
-; Delay times: 32 byte-receive times in milliseconds, or 100 max.
-; Formula = 320,000 / baud. Invalid values do contain $FF.
-PauseTimes:
-        .byte   $FF             ; SER_BAUD_45_5
-        .byte   $FF             ; SER_BAUD_50
-        .byte   $FF             ; SER_BAUD_75
-        .byte   $FF             ; SER_BAUD_110
-        .byte   $FF             ; SER_BAUD_134_5
-        .byte   $FF             ; SER_BAUD_150
-        .byte   100             ; SER_BAUD_300
-        .byte   100             ; SER_BAUD_600
-        .byte   100             ; SER_BAUD_1200
-        .byte   $FF             ; SER_BAUD_1800
-        .byte   100             ; SER_BAUD_2400
-        .byte   $FF             ; SER_BAUD_3600
-        .byte   67              ; SER_BAUD_4800
-        .byte   $FF             ; SER_BAUD_7200
-        .byte   34              ; SER_BAUD_9600
-        .byte   17              ; SER_BAUD_19200
-        .byte   9               ; SER_BAUD_38400
-        .byte   $FF             ; SER_BAUD_57600
-        .byte   $FF             ; SER_BAUD_115200
-        .byte   $FF             ; SER_BAUD_230400
-
-
 .code
 
 ;----------------------------------------------------------------------------
@@ -167,20 +136,12 @@ PauseTimes:
 
 INSTALL:
 
-; Initialize buffers & control
+; Deactivate DTR and disable 6551 interrupts
 
-@L4:   lda     #0
-       sta     RecvHead
-       sta     SendHead
-       sta     RecvTail
-       sta     SendTail
-       sta     Errors
-       sta     Stopped
-       lda     #255
-               sta     RecvFreeCnt
-       sta     SendFreeCnt
+       lda     #%00001010
+               sta     ACIA_CMD
 
-; Set up nmi's
+; Set up the nmi vector
 
        lda     NMIVec
        ldy     NMIVec+1
@@ -188,27 +149,13 @@ INSTALL:
        sty     NmiSave+1
        lda     #<NmiHandler
        ldy     #>NmiHandler
-       sta     NMIVec
+SetNMI: sta    NMIVec
        sty     NMIVec+1
 
-; Set default to 2400-8N1, enable interrupts
-
-       lda     ACIA_DATA
-       lda     ACIA_STATUS
-       lda     #$18
-        sta            ACIA_CTRL
-
-       lda     #$01
-       sta     RtsOff
-       ora     #$08
-               sta     ACIA_CMD
-       lda     #$06
-       sta     BaudCode
-
 ; Done, return an error code
 
-        lda     #SER_ERR_OK
-        tax
+        lda     #<SER_ERR_OK
+        tax                     ; A is zero
        rts
 
 ;----------------------------------------------------------------------------
@@ -219,169 +166,110 @@ UNINSTALL:
 
 ; Stop interrupts, drop DTR
 
-       lda     RtsOff
-       and     #%11100010
-       ora     #%00000010
-       sta     ACIA_CMD
+       lda     #%00001010
+               sta     ACIA_CMD
 
-; Restore NMI vector
+; Restore NMI vector and return OK
 
        lda     NmiSave+0
        ldy     NmiSave+1
-       sta     NMIVec
-       sty     NMIVec+1
-
-; Flag uninitialized
-
-        lda    #SER_ERR_OK
-       tax
-       rts
+       jmp     SetNMI
 
 ;----------------------------------------------------------------------------
 ; PARAMS routine. A pointer to a ser_params structure is passed in ptr1.
 ; Must return an SER_ERR_xx code in a/x.
 
-PARAMS:
-        ldy     #SER_PARAMS_BAUDRATE
-        lda     (ptr1),y                ; Baudrate index
-        tax
-        lda     BaudTable,x             ; Get 6551 value
-        bmi     invalid                 ; Branch if rate not supported
-        sta     tmp1
+OPEN:
+
+; Check if the handshake setting is valid
 
-        iny                             ; Databits
+        ldy    #SER_PARAMS::HANDSHAKE  ; Handshake
         lda     (ptr1),y
-        tax
-        lda     BitTable,x
-        ora     tmp1
+        cmp    #SER_HS_HW              ; This is all we support
+        bne    InvParam
+
+; Initialize buffers
+
+        jsr     InitBuffers
+
+; Set the value for the control register, which contains stop bits, word
+; length and the baud rate.
+
+        ldy     #SER_PARAMS::BAUDRATE
+        lda     (ptr1),y                ; Baudrate index
+        tay
+        lda     BaudTable,y             ; Get 6551 value
+        bmi     InvBaud                        ; Branch if rate not supported
         sta     tmp1
 
-        iny                             ; Stopbits
+        ldy    #SER_PARAMS::DATABITS   ; Databits
         lda     (ptr1),y
-        tax
-        lda     StopTable,x
+        tay
+        lda     BitTable,y
         ora     tmp1
         sta     tmp1
 
-        iny                             ; Parity
+        ldy    #SER_PARAMS::STOPBITS   ; Stopbits
         lda     (ptr1),y
-        tax
-        lda     ParityTable,x
+        tay
+        lda     StopTable,y
         ora     tmp1
-        sta     tmp1
+        ora    #%00010000              ; Receiver clock source = baudrate
+       sta     ACIA_CTRL
 
-        iny                             ; Handshake
+; Set the value for the command register. We remember the base value in
+; RtsOff, since we will have to manipulate ACIA_CMD often.
+
+        ldy            #SER_PARAMS::PARITY     ; Parity
         lda     (ptr1),y
-        tax
-        lda     HandshakeTable,x
-        bmi     invalid
+        tay
+        lda     ParityTable,y
+       ora     #%00000001              ; DTR active
+       sta     RtsOff
+               ora     #%00001000              ; Enable receive interrupts
+               sta     ACIA_CMD
 
+; Done
 
+        lda     #<SER_ERR_OK
+        tax                             ; A is zero
+               rts
+
+; Invalid parameter
 
+InvParam:
+       lda     #<SER_ERR_INIT_FAILED
+       ldx     #>SER_ERR_INIT_FAILED
+       rts
 
+; Baud rate not available
 
+InvBaud:
+        lda     #<SER_ERR_BAUD_UNAVAIL
+        ldx     #>SER_ERR_BAUD_UNAVAIL
+        rts
 
 ;----------------------------------------------------------------------------
+; CLOSE: Close the port, disable interrupts and flush the buffer. Called
+; without parameters. Must return an error code in a/x.
 ;
-; unsigned char __fastcall__ rs232_params (unsigned char params, unsigned char parity);
-; /* Set the port parameters. Use a combination of the #defined values above. */
-;
-; Set communication parameters.
-;
-; baud rates              stops     word    |   parity
-; ---------------------   -----     -----   |   ---------
-; $00=50     $08=9600     $00=1     $00=8   |   $00=none
-; $01=110    $09=19200    $80=2     $20=7   |   $20=odd
-; $02=134.5  $0a=38400              $40=6   |   $60=even
-; $03=300    $0b=57600              $60=5   |   $A0=mark
-; $04=600    $0c=115200                     |   $E0=space
-; $05=1200   $0d=230400
-; $06=2400   $0e=future
-; $07=4800   $0f=future
-;
-
-_rs232_params:
-        and    #%11100000              ; Save new parity
-       ora     #%00000001
-       sta     tmp2
 
-; Check cpu speed against baud rate
+CLOSE:
 
-       jsr     popa
-               sta     tmp1
-       and     #$0f
-       cmp     #$0c
-       bcc     @L3
+; Stop interrupts, drop DTR
 
-       ldx     CpuSpeed                ; ###
-       cpx     #1+1
-       bcc     @L2
-       cmp     #$0c
-       beq     @L3
-       cpx     #4
-       bcs     @L3
-@L2:   lda     #RS_ERR_BAUD_TOO_FAST
-       bne     @L9
+       lda     #%00001010
+               sta     ACIA_CMD
 
-; Set baud/parameters
+; Initalize buffers. Returns zero in a
 
-@L3:   lda     tmp1
-       and     #$0f
-       tax
-       lda     BaudTable,x
-        cmp    #$ff
-       bne     @L5
-       lda     #RS_ERR_BAUD_NOT_AVAIL
-       bne     @L9
-
-@L5:   tax
-       and     #$30
-               beq     @L6
-       bit     Turbo232
-       bmi     @L6
-       lda     #RS_ERR_BAUD_NOT_AVAIL
-       bne     @L9
-
-@L6:   lda     tmp1
-       and     #$0f
-       sta     BaudCode
-       lda     tmp1
-       and     #%11100000
-       ora     #%00010000
-       sta     tmp1
-       txa
-       and     #$0f
-       ora     tmp1
-       sta     ACIA_CTRL
-       txa
-       and     #%00110000
-       beq     @L7
-       lsr
-       lsr
-       lsr
-       lsr
-       eor     #%00000011
-       sta     ACIA_CLOCK
-
-; Set new parity
-
-@L7:   lda     tmp2
-       sta     RtsOff
-       ora     #%00001000
-       sta     ACIA_CMD
-       lda     #0
-@L9:   ldx     #0
-       rts
+        jsr     InitBuffers
 
-.rodata
+; Return OK
 
-BaudTable:
-   .byte $ff,$ff,$ff,$05,$06,$07,$08,$0a,$0c,$0e,$0f,$10,$20,$30,$ff,$ff
-     ;in:  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
-     ;baud50 110 134   3   6  12  24  48  96  19  38  57 115 230 exp exp
-     ;out masks: $0F=Baud, val$FF=err
-     ;           $30=t232ExtBaud: $00=none, $10=57.6, $20=115.2, $30=230.4
-.code
+        lda     #<SER_ERR_OK
+        tax                             ; A is zero
+               rts
 
 ;----------------------------------------------------------------------------
 ; GET: Will fetch a character from the receive buffer and store it into the
@@ -389,12 +277,8 @@ BaudTable:
 ; return.
 ;
 
-GET:
-
-; Check for bytes to send
-
-       ldx     SendFreeCnt
-       cpx     #$ff
+GET:    ldx    SendFreeCnt             ; Send data if necessary
+               inx                             ; X == $FF?
        beq     @L1
        lda     #$00
        jsr     TryToSend
@@ -404,8 +288,8 @@ GET:
 @L1:   lda     RecvFreeCnt             ; (25)
        cmp     #$ff
        bne     @L2
-       lda     #SER_ERR_NO_DATA
-       ldx     #0
+       lda     #<SER_ERR_NO_DATA
+       ldx     #>SER_ERR_NO_DATA
        rts
 
 ; Check for flow stopped & enough free: release flow control
@@ -432,7 +316,7 @@ GET:
        rts
 
 ;----------------------------------------------------------------------------
-; PUT: Output character in A. 
+; PUT: Output character in A.
 ; Must return an error code in a/x.
 ;
 
@@ -441,7 +325,7 @@ PUT:
 ; Try to send
 
         ldx    SendFreeCnt
-       cpx     #$ff
+               inx                             ; X = $ff?
        beq     @L2
        pha
        lda     #$00
@@ -466,72 +350,31 @@ PUT:
                rts
 
 ;----------------------------------------------------------------------------
-; PAUSE: Assert flow control and disable interrupts.
+; STATUS: Return the status in the variable pointed to by ptr1.
 ; Must return an error code in a/x.
 ;
 
-PAUSE:
-
-; Assert flow control
-
-       lda     RtsOff
-       sta     Stopped
-       sta     ACIA_CMD
-
-; Delay for flow stop to be received
-
-       ldx     BaudCode
-       ldy     PauseTimes,x
-       jsr     DelayMs
-
-; Stop rx interrupts
-
-       lda     RtsOff
-       ora     #$02
-       sta     ACIA_CMD
-       lda     #<SER_ERR_OK
-       tax
-       rts
-
+STATUS: lda            ACIA_STATUS
+               ldx     #0
+       sta     (ptr1,x)
+       txa                             ; SER_ERR_OK
+        rts
 
 ;----------------------------------------------------------------------------
-; UNPAUSE: Re-enable interrupts and release flow control.
+; 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 error code in a/x.
 ;
 
-UNPAUSE:
-
-; Re-enable rx interrupts & release flow control
-
-@L1:           lda     #$00
-               sta     Stopped
-               lda     RtsOff
-               ora     #%00001000
-               sta     ACIA_CMD
-
-; Poll for stalled char & exit
-
-               jsr     PollReceive
-               lda     #<SER_ERR_OK
-       tax
-       rts
+IOCTL:  lda     #<SER_ERR_INV_IOCTL     ; We don't support ioclts for now
+        ldx     #>SER_ERR_INV_IOCTL
+       rts
 
 ;----------------------------------------------------------------------------
-; STATUS: Return the status in the variable pointed to by ptr1.
-; Must return an error code in a/x.
+; IRQ: Not used on the C64
 ;
 
-STATUS:
-
-; Get status
-
-        lda            ACIA_STATUS
-       ldy     #0
-       sta     (ptr1),y
-       jsr     PollReceive             ; bug-recovery hack
-       tya                             ; SER_ERR_OK
-       tax
-        rts
+IRQ     = $0000
 
 ;----------------------------------------------------------------------------
 ;
@@ -548,46 +391,31 @@ STATUS:
 
 NmiHandler:
        pha
-               lda     ACIA_STATUS             ;(4) ;status ;check for byte received
-       and     #$08                    ;(2)
-               beq     @L9                     ;(2*)
+               lda     ACIA_STATUS     ;(4) ;status ;check for byte received
+       and     #$08            ;(2)
+               beq     @L9             ;(2*)
        cld
        txa
        pha
        tya
        pha
-               lda     ACIA_STATUS             ;(4) opt ;status ;check for receive errors
-       and     #$07                    ;(2) opt
-               beq     @L1                     ;(3*)opt
-       inc     Errors                  ;(5^)opt
-@L1:   lda     ACIA_DATA               ;(4) ;data  ;get byte and put into receive buffer
-       ldy     RecvTail                ;(4)
-       ldx     RecvFreeCnt             ;(4)
-       beq     @L3                     ;(2*)
-       sta     RecvBuf,y               ;(5)
-       inc     RecvTail                ;(6)
-       dec     RecvFreeCnt             ;(6)
-       cpx     #33                     ;(2)  ;check for buffer space low
-               bcc     @L2                     ;(2*)
-       jmp     NMIEXIT                 ;(3)
+@L1:   lda     ACIA_DATA       ;(4)  data  ;get byte and put into receive buffer
+       ldy     RecvTail        ;(4)
+       ldx     RecvFreeCnt     ;(4)
+       beq     @L3             ;(2*) Jump if no space in receive buffer
+       sta     RecvBuf,y       ;(5)
+       inc     RecvTail        ;(6)
+       dec     RecvFreeCnt     ;(6)
+       cpx     #33             ;(2)  check for buffer space low
+               bcc     @L2             ;(2*)
+       jmp     NMIEXIT         ;(3)
 
 ; Assert flow control
 
-@L2:   lda     RtsOff                  ;(3)  ;assert flow control if buffer space too low
-       sta     ACIA_CMD        ;(4) ;command
-       sta     Stopped                 ;(3)
-       jmp     NMIEXIT                 ;(3)
-
-; Drop this char
-
-@L3:   inc     DropCnt+0               ; not time-critical
-       bne     @L4
-       inc     DropCnt+1
-       bne     @L4
-       inc     DropCnt+2
-       bne     @L4
-       inc     DropCnt+3
-@L4:           jmp     NMIEXIT
+@L2:   lda     RtsOff          ;(3) assert flow control if buffer space too low
+       sta     ACIA_CMD        ;(4) command
+       sta     Stopped         ;(3)
+@L3:    jmp    NMIEXIT         ;(3)
 
 @L9:   pla
        jmp     NmiContinue
@@ -627,57 +455,19 @@ NmiHandler:
 
 .endproc
 
-;----------------------------------------------------------------------------
-;
-; PollReceive - poll for rx char
-;   This function is useful in odd cases where the 6551 has a character in
-;   it but it fails to raise an NMI.  It might be edge-triggering conditions?
-;   Actually, I'm not entirely sure that this condition can still arrise, but
-;   calling this function does no harm.
-;
-
-.proc   PollReceive
-
-       lda     #$08
-       and     ACIA_STATUS
-       beq     @L9
-               and     ACIA_STATUS
-       beq     @L9
-               lda     ACIA_DATA
-       ldx     RecvFreeCnt
-       beq     @L9
-       ldx     RecvTail
-       sta     RecvBuf,x
-       inc     RecvTail
-       dec     RecvFreeCnt
-@L9:   rts
-
-.endproc
 
 ;----------------------------------------------------------------------------
-;
-;  DelayMs : delay for given number of milliseconds
-;    This implementation isn't very rigerous; it merely delays for the
-;    approximate number of clock cycles for the processor speed.
-;    Algorithm:
-;       repeat for number of milliseconds:
-;         delay for 1017 clock cycles
-;
-
-
-.proc   DelayMs                 ;( .A=milliseconds )
-
-@L1:           ldx     #203            ;(2)
-@L2:           dex                     ;(2)
-               bne     @L2             ;(3) // 1017 cycles
-       dey
-       bne     @L1
-       rts
-
-.endproc
-
-
-.end
-
-
+; Initialize buffers
+
+InitBuffers:
+        ldx    #0
+        stx     Stopped
+               stx     RecvHead
+       stx     RecvTail
+       stx     SendHead
+       stx     SendTail
+        dex                             ; X = 255
+               stx     RecvFreeCnt
+       stx     SendFreeCnt
+        rts