URL
https://opencores.org/ocsvn/rf6809/rf6809/trunk
Subversion Repositories rf6809
[/] [rf6809/] [trunk/] [software/] [boot/] [serial.asm] - Rev 14
Go to most recent revision | 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:clraclrbstd SerHeadRcv-1std SerTailRcv-1std SerHeadXmit-1std SerTailXmit-1clr SerRcvXonclr SerRcvXofflda COREIDsini1:cmpa IOFocusIDbne sini1ldb #$09 ; dtr,rts active, rxint enabled, no paritystb ACIA+ACIA_CMDldb #$1F ; baud 9600, 1 stop bit, 8 bit, internal baud genstb ACIA+ACIA_CTRLldb #$0A6 ; diable fifos, reset fifosstb ACIA+ACIA_CTRL2rts;------------------------------------------------------------------------------; 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,yldy #0sei ; disable interruptsbsr SerialRcvCount ; check number of chars in receive buffercmpb #8 ; less than 8?bhi sgc2ldb SerRcvXon ; skip sending XON if already sentbne sgc2 ; XON already sent?ldb #XON ; if <8 send an XONclr SerRcvXoff ; clear XOFF statusstb SerRcvXon ; flag so we don't send it multiple timesbsr SerialPutCharsgc2:ldb SerHeadRcv ; check if anything is in buffercmpb SerTailRcvbeq sgcNoChars ; no?ldx #SerRcvBufclraldb b,x ; get byte from bufferinc SerHeadRcv ; 4k wrap aroundbra sgcXitsgcNoChars:ldd #-1sgcXit:clipuls x,y,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,ccrseildb SerHeadRcv ; check if anything is in buffercmpb SerTailRcvbeq spcNoChars ; no?ldx #SerRcvBufclraldb b,x ; get byte from bufferbra spcXitspcNoChars:ldd #-1spcXit:puls x,ccr,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:lda COREID ; Ensure we have the IO Focuscmpa IOFocusIDbne spcd0001; Disallow interrupts between status read and rx read.seildb ACIA+ACIA_STATbitb #8 ; look for Rx not emptybeq spcd0001clraldb ACIA+ACIA_RXclirtsspcd0001:ldd #-1clirts;------------------------------------------------------------------------------; 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,ccrspc0001:lda COREID ; Ensure we have the IO Focuscmpa IOFocusIDbne spc0001cli ; provide a window for an interrupt to occursei; Between the status read and the transmit do not allow an; intervening interrupt.lda ACIA+ACIA_STAT ; wait until the uart indicates tx emptybita #16 ; bit #4 of the status regbeq spc0001 ; branch if transmitter is not emptystb ACIA+ACIA_TX ; send the bytepuls a,ccr,pc;------------------------------------------------------------------------------; Calculate number of character in input buffer;; Parameters:; y = 0 if current core, otherwise reference to core memory area $Cyxxxx; Returns:; d = number of bytes in buffer.;------------------------------------------------------------------------------SerialRcvCount:clraldb SerTailRcv,ysubb SerHeadRcv,ybge srcXitldd #$1000subd SerHeadRcv,yaddd SerTailRcv,ysrcXit: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 statusbitb #$08 ; bit 3 = rx fullbeq notRxIntldb ACIA+ACIA_RX ; get data from Rx buffer to clear interruptcmpb #CTRLT ; detect special keystrokebne sirq0001; bsr DumpTraceQueuesirq0001:pshs b; Compute receive buffer addresslda IOFocusIDaslaaslaaslaaslaora #$C00clrbtfr d,ypuls blda SerTailRcv,y ; check if recieve buffer fullincacmpa SerHeadRcv,ybeq sirqRxFullsta SerTailRcv,y ; update tail pointerdeca ; backupexg a,bleax SerRcvBuf,y ; x = buffer addresssta b,x ; store recieved byte in buffertst SerRcvXoff,y ; check if xoff already sentbne sirqNxtBytebsr SerialRcvCount ; if more than 4080 chars in buffercmpb #4080blo sirqNxtByteldb #XOFF ; send an XOFFclr SerRcvXon,y ; clear XON statusstb SerRcvXoff,y ; set XOFF statusstb ACIA+ACIA_TXbra sirqNxtByte ; check the status for another bytesirqRxFull:notRxInt:rtsnmeSerial:fcb "Serial",0;------------------------------------------------------------------------------; Put a string to the serial port.;; Parameters:; d = pointer to string; Modifies:; none; Returns:; none;------------------------------------------------------------------------------SerialPutString:pshs d,xtfr d,xsps2:ldb ,xbeq spsXitinxbsr SerialPutCharbra sps2spsXit:puls d,x,pc;------------------------------------------------------------------------------; A little routine to test serial output.;; Parameters:; none; Modifies:; none; Returns:; none;------------------------------------------------------------------------------SerialOutputTest:pshs dldd #msgSerialTestlbsr DisplayStringbsr SerialInitsotst1:ldb #XONbsr SerialPutCharbsr SerialPutCharbsr SerialPutCharldd #msgSerialTestbsr SerialPutStringlbsr INCHcmpb #CTRLCbne sotst1puls d,pcmsgSerialTest:fcb "Serial port test",CR,LF,0
Go to most recent revision | Compare with Previous | Blame | View Log
