OpenCores
URL https://opencores.org/ocsvn/uart6551/uart6551/trunk

Subversion Repositories uart6551

[/] [uart6551/] [trunk/] [trunk/] [software/] [serial.asm] - Rev 5

Compare with Previous | Blame | View Log

; ============================================================================
;        __
;   \\__/ o\    (C) 2022  Robert Finch, Waterloo
;    \  __ /    All rights reserved.
;     \/_//     robfinch<remove>@opencores.org
;       ||
;  
;
; Serial port routines for a WDC6551 compatible circuit.
;
; This source file is free software: you can redistribute it and/or modify 
; it under the terms of the GNU Lesser General Public License as published 
; by the Free Software Foundation, either version 3 of the License, or     
; (at your option) any later version.                                      
;                                                                          
; This source file is distributed in the hope that it will be useful,      
; but WITHOUT ANY WARRANTY; without even the implied warranty of           
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
; GNU General Public License for more details.                             
;                                                                          
; You should have received a copy of the GNU General Public License        
; along with this program.  If not, see <http://www.gnu.org/licenses/>.    
;                                                                          
; ============================================================================
;
;------------------------------------------------------------------------------
; Initialize serial port.
;
; Clear buffer indexes. Two bytes are used for the buffer index even though
; only a single byte is needed. This is for convenience in calculating the
; number of characters in the buffer, done later. The upper byte remains at
; zero.
; The port is initialized for 9600 baud, 1 stop bit and 8 bits data sent.
; The internal baud rate generator is used.
;
; Parameters:
;               none
; Modifies:
;               d
; Returns:
;               none
;------------------------------------------------------------------------------

InitSerial:
SerialInit:
        clra
        clrb
        std             SerHeadRcv-1
        std             SerTailRcv-1
        std             SerHeadXmit-1
        std             SerTailXmit-1
        clr             SerRcvXon
        clr             SerRcvXoff
        ldb             #$09                                            ; dtr,rts active, rxint enabled, no parity
        stb             ACIA+ACIA_CMD
        ldb             #$1E                                            ; baud 9600, 1 stop bit, 8 bit, internal baud gen
        stb             ACIA+ACIA_CTRL
        ldb             #$0A6                                           ; diable fifos, reset fifos
        stb             ACIA+ACIA_CTRL2 
        rts

;------------------------------------------------------------------------------
; SerialGetChar
;
; Check the serial port buffer to see if there's a char available. If there's
; a char available then return it. If the buffer is almost empty then send an
; XON.
;
; Stack Space:
;               2 words
; Parameters:
;               none
; Modifies:
;               none
; Returns:
;               d = character or -1
;------------------------------------------------------------------------------

SerialGetChar:
                pshs    x
                sei                                                                             ; disable interrupts
                bsr             SerialRcvCount                  ; check number of chars in receive buffer
                cmpb    #8                                                      ; less than 8?
                bhi             sgc2
                ldb             SerRcvXon                               ; skip sending XON if already sent
                bne       sgc2            ; XON already sent?
                ldb             #XON                                            ; if <8 send an XON
                clr             SerRcvXoff                      ; clear XOFF status
                stb             SerRcvXon                               ; flag so we don't send it multiple times
                stb             ACIA+ACIA_TX
sgc2:
                ldb             SerHeadRcv                      ; check if anything is in buffer
                cmpb    SerTailRcv
                beq             sgcNoChars                      ; no?
                ldx             #SerRcvBuf
                abx
                clra
                ldb             ,x                                                      ; get byte from buffer
                inc             SerHeadRcv                      ; 4k wrap around
                bra             sgcXit
sgcNoChars:
                ldd             #-1
sgcXit:
                cli
                puls    x,pc

;------------------------------------------------------------------------------
; SerialPeekChar
;
; Check the serial port buffer to see if there's a char available. If there's
; a char available then return it. But don't update the buffer indexes. No need
; to send an XON here.
;
; Stack Space:
;               0 words
; Parameters:
;               none
; Modifies:
;               none
; Returns:
;               d = character or -1
;------------------------------------------------------------------------------

SerialPeekChar:
        pshs    x
        sei
        ldb             SerHeadRcv                              ; check if anything is in buffer
        cmpb    SerTailRcv
        beq             spcNoChars                              ; no?
        ldx             #SerRcvBuf
        abx
        clra
        ldb             ,x                                                              ; get byte from buffer
        bra             spcXit
spcNoChars:
        ldd             #-1
spcXit:
        cli
        puls    x,pc

;------------------------------------------------------------------------------
; SerialPeekChar
;               Get a character directly from the I/O port. This bypasses the input
; buffer.
;
; Stack Space:
;               0 words
; Parameters:
;               none
; Modifies:
;               d
; Returns:
;               d = character or -1
;------------------------------------------------------------------------------

SerialPeekCharDirect:
        ; Disallow interrupts between status read and rx read.
        sei
        ldb             ACIA+ACIA_STAT
        bitb    #8                                                                      ; look for Rx not empty
        beq             spcd0001
        clra
        ldb             ACIA+ACIA_RX
        cli
        rts
spcd0001:
        ldd             #-1
        cli
        rts

;------------------------------------------------------------------------------
; SerialPutChar
;    Put a character to the serial transmitter. This routine blocks until the
; transmitter is empty. 
;
; Stack Space
;               0 words
; Parameters:
;               b = character to put
; Modifies:
;               none
;------------------------------------------------------------------------------

SerialPutChar:
        pshs    a
spc0001:
        cli                                                                             ; provide a window for an interrupt to occur
        sei
        ; Between the status read and the transmit do not allow an
        ; intervening interrupt.
        lda             ACIA+ACIA_STAT  ; wait until the uart indicates tx empty
        bita    #16                                                     ; bit #4 of the status reg
        beq             spc0001                     ; branch if transmitter is not empty
        stb             ACIA+ACIA_TX            ; send the byte
        cli
        puls    a
        rts

;------------------------------------------------------------------------------
; Calculate number of character in input buffer
;
; Returns:
;               d = number of bytes in buffer.
;------------------------------------------------------------------------------

SerialRcvCount:
        clra
        ldb             SerTailRcv
        subb    SerHeadRcv
        bge             srcXit
        ldd             #$1000
        subd    SerHeadRcv
        addd    SerTailRcv
srcXit:
        rts

;------------------------------------------------------------------------------
; Serial IRQ routine
;
; Keeps looping as long as it finds characters in the ACIA recieve buffer/fifo.
; Received characters are buffered. If the buffer becomes full, new characters
; will be lost.
;
; Parameters:
;               none
; Modifies:
;               d,x
; Returns:
;               none
;------------------------------------------------------------------------------

SerialIRQ:
sirqNxtByte:
        ldb             ACIA+ACIA_STAT  ; check the status
        bitb    #$08                                            ; bit 3 = rx full
        beq             notRxInt
        ldb             ACIA+ACIA_RX            ; get data from Rx buffer to clear interrupt
        cmpb    #CTRLT                                  ; detect special keystroke
        bne     sirq0001
;       bsr     DumpTraceQueue
sirq0001:
        lda             SerTailRcv                      ; check if recieve buffer full
        inca
        cmpa    SerHeadRcv
        beq             sirqRxFull
        sta             SerTailRcv                      ; update tail pointer
        deca                                                                    ; backup
        exg             a,b
        ldx             #SerRcvBuf                      ; x = buffer address
        abx
        sta             ,x                                                      ; store recieved byte in buffer
        tst             SerRcvXoff                      ; check if xoff already sent
        bne             sirqNxtByte
        bsr             SerialRcvCount  ; if more than 4080 chars in buffer
        cmpb    #4080
        blo             sirqNxtByte
        ldb             #XOFF                                           ; send an XOFF
        clr             SerRcvXon                               ; clear XON status
        stb             SerRcvXoff                      ; set XOFF status
        stb             ACIA+ACIA_TX
        bra             sirqNxtByte     ; check the status for another byte
sirqRxFull:
notRxInt:
        rts

nmeSerial:
        fcb             "Serial",0

;------------------------------------------------------------------------------
; Put a string to the serial port.
;
; Parameters:
;               d = pointer to string
; Modifies:
;               none
; Returns:
;               none
;------------------------------------------------------------------------------

SerialPutString:
        pshs    d,x
        tfr             d,x
sps2:
        ldb             ,x
        beq             spsXit
        inx
        bsr             SerialPutChar
        bra             sps2
spsXit:
        puls    d,x,pc

;------------------------------------------------------------------------------
; A little routine to test serial output.
;
; Parameters:
;               none
; Modifies:
;               none
; Returns:
;               none
;------------------------------------------------------------------------------

SerialOutputTest:
        pshs    d
        ldd             #msgSerialTest
        lbsr    DisplayString
        bsr             SerialInit
sotst1:
        ldb             #XON
        bsr             SerialPutChar
        bsr             SerialPutChar
        bsr             SerialPutChar
        ldd             #msgSerialTest
        bsr             SerialPutString
        lbsr    INCH
        cmpb    #CTRLC
        bne             sotst1
        puls    d,pc

msgSerialTest:
        fcb     "Serial port test",CR,LF,0

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.