[Flashforth-devel] UART delay for TeraTerm, CoolTerm
Brought to you by:
oh2aun
|
From: Mike M. <mi...@mo...> - 2015-05-19 19:59:07
|
I have been casually following the thread about TeraTerm.
I use TeraTerm on Windows, CoolTerm on OSX.
I have been using hardware handshake, with NO delay. I use a
USB-to-serial adapter using the FTDI chipset, which seems to get the
handshake right.
I has been a couple of years since I wrote these, so I hope I am
including all of the changes.
To do this, I have modified the UART driver. I use UART #2, FC_TYPE=2
I also have FC_TYPE=0 defined using the PIC's handshake control, but
that does not work very well.
I am using FF 4.8 on the PIC24FJ256GB110, so I map I/O pins:
<snip> in config file:
;;; UART2 configuration
;.equ BAUDRATE2, 38400 ; Serial baudrate UART2,
comment if not used
.equ BAUDRATE2, 115200 ; Serial baudrate UART2,
comment if not used
.equ FC2_TYPE, 2 ; ; 0 = UART CTS/RTS, 1 =
XON/XOFF, 2=(CTS)/RTS software
.equ AUTOBAUD2, 0 ; 0 = to use fixed baudrate
; 1 = Autobaud, First char
after reset must be 'U' (0x55)
;;; UART2 Peripheral pin mapping
.ifdecl RPINR19
.equ U2TXPIN, 17 ; RP17 pin 50
;.equ U2RXPIN, 10 ; RP10 PIN 49
.if FC2_TYPE == 0 ; UART controls RTS, CTS
.equ RPINR19VAL, 0x200a ; msb: U2CTS RP32, lsb: U2RXPIN RP10
.equ U2RTSPIN, 31 ; RP31 (RF13) pin 39 output
.else ; we control RTS, CTS
.equ RPINR19VAL, 0xff0a ; msb: (U2CTS RP32), lsb: U2RXPIN RP10
; we are controlling RTS, CTS
.equ U2RTSPORT, LATF
.equ U2RTSTRIS, TRISF
.equ U2RTSPIN, 13 ;RF13 (RF31) pin 39 output
.equ U2CTSPIN, 12 ;RF12 (RPI32) pin 40 input (not
implemented)
.endif
.endif
<snip> in FF.s:
.ifdecl BAUDRATE2 ; UART2
.ifdecl _U2RXREG
__U2RXInterrupt:
push.s
.ifdef CMAIN
lnk #ISTKSIZ
.endif ; CMAIN
.ifdef PEEPROM
push TBLPAG
.endif
inc2 W14, W14
__U2RXInterrupt0:
bclr IFS1, #U2RXIF
bset iflags, #istream ; Indicate UART activity.
mlit handle(U2RXQUEUE_DATA)+PFLASH
rcall CQUEUE_TOQ ; Space available ? false =
queue is full
cp0 [W14--]
bra z, U2RX_ERR1
bclr U2STA, #OERR
mov U2RXREG, W0 ; get chr
.if (CTRL_O_WARM_RESET == 1); Console only
cp W0, #15
bra z, RESET_FF_1
.endif
.if FC2_TYPE == 1
btsc iflags, #fFC2
bra U2_SKIP_FC_1
cp W0, #XOFF
bra z, __U2RXInterrupt3
.endif
U2_SKIP_FC_1:
mov W0, [++W14]
mlit handle(U2RXQUEUE_DATA)+PFLASH
rcall CQUEUE_TO ; Put to character queue
btsc iflags, #fFC2
bra U2_SKIP_FC_2
.if FC2_TYPE == 1
mov rbuf_wr2, W0
and W0, #0xf, W0
bra nz, __U2RXInterrupt3
__U2RXInterrupt2:
btsc U2STA, #UTXBF ; buffer full?
bra __U2RXInterrupt2
mov #XOFF, W0
mov W0, U2TXREG ; send chr
bset iflags, #ixoff2
.else
.if FC2_TYPE == 2
mov #RX2_OFF_FILL, W0
cp rbuf_lv2
bra n, __U2RXInterrupt3
bset U2RTSPORT, #U2RTSPIN ; RTS low
.endif
.endif
U2_SKIP_FC_2:
__U2RXInterrupt3:
btsc U2STA, #URXDA ; bit #0, data available
bra __U2RXInterrupt0
__U2RXTXIRQ_END:
bra __U1RXTXIRQ_END
U2RX_ERR1:
btss U2STA, #TRMT
bra U2RX_ERR1
mov U2RXREG, W0
mov #'|', W0
mov W0, U2TXREG ; send
bra __U2RXInterrupt3
__U2TXInterrupt:
push.s
.ifdef CMAIN
lnk #ISTKSIZ
.endif ; CMAIN
.ifdef PEEPROM
push TBLPAG
.endif
add W14, #2, W14
bclr IFS1, #U2TXIF ; clear interrupt flag
__U2TXInterrupt0:
btsc U2STA, #UTXBF ; uart buffer full?
bra __U2TXInterrupt3 ; buffer full
mlit handle(U2TXQUEUE_DATA)+PFLASH ; yes buffer ready
rcall CQUEUE_FROMQ ; Character available ?
false = no
cp0 [W14--]
bra z, __U2TXInterrupt3 ; queue empty
mlit handle(U2TXQUEUE_DATA)+PFLASH
rcall CQUEUE_FROM ; Get from character
queue
mov [W14--], W0
mov W0, U2TXREG ; Send chr
__U2TXInterrupt3:
bra __U1RXTXIRQ_END
.endif
.endif
<snip>
wait_silence:
rcall LOCKED
.if FC2_TYPE == 1
btsc U2STA, #UTXBF ; buffer full?
bra wait_silence
mov #XOFF, W2
mov W2, U2TXREG ; send chr
bset iflags, #ixoff2
.else
.if FC2_TYPE == 2
bset U2RTSPORT, #U2RTSPIN ; RTS low
.endif
.endif
.if FC2_TYPE == 1
wbtil:
bclr iflags, #istream
; The delay here should be 10 character times long
; times = Fcy/baud*40
; MJM mov #(FCY/BAUDRATE1*40), W2 ; This loop takes about
5 milliseconds @ 27 Mips
mov #13333, W2 ; This loop takes about 5 milliseconds
@ 27 Mips
wbtil2:
btsc iflags, #istream ; Check for UART activity.
bra wbtil ;
dec W2, W2 ;
bra nz, wbtil2 ;
.endif
return
<snip>
;;; Initialise UART2
.ifdecl BAUDRATE2
.ifdecl _U2RXREG
.if FC2_TYPE == 2 ; remap pins override tris
bclr U2RTSTRIS, #U2RTSPIN
bclr U2RTSPORT, #U2RTSPIN ; RTS high
.endif
.ifdecl RPINR19
mov #RPINR19VAL, W0 ; lsb is RX
mov W0, RPINR19 ; msb: (U2CTS), lsb: U2RX
mov #0x0005, W0 ; U2TX #5
mov.b WREG, RPOR0+U2TXPIN
.if FC2_TYPE == 0 ; UART RTS control MJM
mov #0x0006, W0 ; U2RTS #6
mov.b WREG, RPOR0+U2RTSPIN
; enable hdwe CTS/RTS
bset U2MODE, #UEN1 ; enable hdwe CTS/RTS MJM
.endif
.endif
;// Assign U2TX to pin RP17 (pin #50, RF5) MJM
; RPOR15bits.RP30R = 5; // 5 is code for U2TX
;// Assign U2RX to pin RP10 (pin #49, RF4)
; RPINR19bits.U2RXR = 10;
bclr PMD1, #U2MD ; enable UART2 clk
bset U2MODE, #UARTEN ; enable UART2
.ifdecl BRGH
bset U2MODE, #BRGH ; fast baud rates
.endif
mov #BAUD_DIV2, W0
mov W0, U2BRG
bset U2STA, #UTXEN
.ifdecl AUTOBAUD2
.if (AUTOBAUD2 == 1)
bset U2MODE, #ABAUD
WARM_ABAUD2:
btsc U2MODE, #ABAUD
bra WARM_ABAUD2
bclr IFS1, #U2RXIF
.endif
.endif
bset IEC1, #U2RXIE ; enable U2 interrupts
bset IEC1, #U2TXIE
.endif
.endif
<snip>
.pword paddr(RX1Q_L)+PFLASH
.ifdecl BAUDRATE2 ; UART2
.ifdecl _U2RXREG
U2TXQUEUE_L: ; ( -- queue-addr ) Leave the address of the queue for
UART2
.byte NFA|INLINE|5
.ascii "u2txq"
.align 2
U2TXQUEUE:
mlit handle(U2TXQUEUE_DATA)+PFLASH
return
U2TXQUEUE_DATA:
.word txqueue2
.word TX2_BUF_SIZE-1
.pword paddr(U2TXQUEUE_L)+PFLASH
U2RXQUEUE_L:
.byte NFA|INLINE|5
.ascii "u2rxq"
.align 2
U2RXQUEUE:
mlit handle(U2RXQUEUE_DATA)+PFLASH
return
U2RXQUEUE_DATA:
.word rxqueue2
.word RX2_BUF_SIZE-1
.pword paddr(U2RXQUEUE_L)+PFLASH
TX2_L: ; ( c -- ) Put a character to U2TXQ
.byte NFA|3
.ascii "tx2"
.align 2
TX2:
rcall PAUSE
rcall IDLE_
rcall TX2Q
cp0 [W14--]
bra z, TX2
rcall BUSY_
rcall U2TXQUEUE
rcall CQUEUE_TO ; Put to character queue
rcall U2TXQUEUE
rcall CQUEUE_FROMQ ; Character available ? false = no
mov [W14--], W0
sub #2, W0 ; If there are less than 2 chars
bra nn, TX2_2 ; in TX queue,
bset IFS1, #U2TXIF ; clr interrupt flag
TX2_2:
return
.pword paddr(TX2_L)+PFLASH
TX2Q_L: ; ( -- flag ) Leave false flag if
U2TXQ is full.
.byte NFA|4
.ascii "tx2?"
.align 2
TX2Q:
mlit handle(U2TXQUEUE_DATA)+PFLASH
goto CQUEUE_TOQ ; Space available ? false = queue
is full
.pword paddr(TX2Q_L)+PFLASH
RX2_L:
.byte NFA|3
.ascii "rx2"
.align 2
RX2:
rcall PAUSE
rcall RX2Q
cp0 [W14--]
.if FC2_TYPE == 2 ; MJM
bra nz, RX2_1 ; MJM
bclr U2RTSPORT, #U2RTSPIN ; RTS high
bra RX2
RX2_1:
.else
bra z, RX2 ; MJM
.endif
mlit handle(U2RXQUEUE_DATA)+PFLASH
rcall CQUEUE_FROM ; Get from character
queue
return
.pword paddr(RX2_L)+PFLASH
RX2Q_L:
.byte NFA|4
.ascii "rx2?"
.align 2
RX2Q:
rcall BUSY_
mlit handle(U2RXQUEUE_DATA)+PFLASH
rcall CQUEUE_FROMQ ; Character
available ? false = no
cp0 [W14]
bra nz, RX2Q1
rcall IDLE_
btss iflags, #fFC2
bra RX2Q1
.if FC2_TYPE == 1
btst iflags, #ixoff2
bra z, RX2Q1
bclr iflags, #ixoff2
mlit XON
rcall TX2
.else
.if FC2_TYPE == 2
cp0 rbuf_lv2 ; buffer empty?
bra nz, RX2Q1
bclr U2RTSPORT, #U2RTSPIN ; RTS high
.else ; FC2_TYPE == 0 UART handshake
cp0 rbuf_lv2 ; buffer empty?
bra nz, RX2Q1
mov U2RXREG, W0 ; get chr, dump
.endif
.endif
RX2Q1:
return
.pword paddr(RX2Q_L)+PFLASH
.endif
.endif
<snip>
.pword paddr(RX1Q_L)+PFLASH
.ifdecl BAUDRATE2 ; UART2
.ifdecl _U2RXREG
U2TXQUEUE_L: ; ( -- queue-addr ) Leave the address of the queue for
UART2
.byte NFA|INLINE|5
.ascii "u2txq"
.align 2
U2TXQUEUE:
mlit handle(U2TXQUEUE_DATA)+PFLASH
return
U2TXQUEUE_DATA:
.word txqueue2
.word TX2_BUF_SIZE-1
.pword paddr(U2TXQUEUE_L)+PFLASH
U2RXQUEUE_L:
.byte NFA|INLINE|5
.ascii "u2rxq"
.align 2
U2RXQUEUE:
mlit handle(U2RXQUEUE_DATA)+PFLASH
return
U2RXQUEUE_DATA:
.word rxqueue2
.word RX2_BUF_SIZE-1
.pword paddr(U2RXQUEUE_L)+PFLASH
TX2_L: ; ( c -- ) Put a character to U2TXQ
.byte NFA|3
.ascii "tx2"
.align 2
TX2:
rcall PAUSE
rcall IDLE_
rcall TX2Q
cp0 [W14--]
bra z, TX2
rcall BUSY_
rcall U2TXQUEUE
rcall CQUEUE_TO ; Put to character queue
rcall U2TXQUEUE
rcall CQUEUE_FROMQ ; Character available ? false = no
mov [W14--], W0
sub #2, W0 ; If there are less than 2 chars
bra nn, TX2_2 ; in TX queue,
bset IFS1, #U2TXIF ; clr interrupt flag
TX2_2:
return
.pword paddr(TX2_L)+PFLASH
TX2Q_L: ; ( -- flag ) Leave false flag if
U2TXQ is full.
.byte NFA|4
.ascii "tx2?"
.align 2
TX2Q:
mlit handle(U2TXQUEUE_DATA)+PFLASH
goto CQUEUE_TOQ ; Space available ? false = queue
is full
.pword paddr(TX2Q_L)+PFLASH
RX2_L:
.byte NFA|3
.ascii "rx2"
.align 2
RX2:
rcall PAUSE
rcall RX2Q
cp0 [W14--]
.if FC2_TYPE == 2 ; MJM
bra nz, RX2_1 ; MJM
bclr U2RTSPORT, #U2RTSPIN ; RTS high
bra RX2
RX2_1:
.else
bra z, RX2 ; MJM
.endif
mlit handle(U2RXQUEUE_DATA)+PFLASH
rcall CQUEUE_FROM ; Get from character
queue
return
.pword paddr(RX2_L)+PFLASH
RX2Q_L:
.byte NFA|4
.ascii "rx2?"
.align 2
RX2Q:
rcall BUSY_
mlit handle(U2RXQUEUE_DATA)+PFLASH
rcall CQUEUE_FROMQ ; Character
available ? false = no
cp0 [W14]
bra nz, RX2Q1
rcall IDLE_
btss iflags, #fFC2
bra RX2Q1
.if FC2_TYPE == 1
btst iflags, #ixoff2
bra z, RX2Q1
bclr iflags, #ixoff2
mlit XON
rcall TX2
.else
.if FC2_TYPE == 2
cp0 rbuf_lv2 ; buffer empty?
bra nz, RX2Q1
bclr U2RTSPORT, #U2RTSPIN ; RTS high
.else ; FC2_TYPE == 0 UART handshake
cp0 rbuf_lv2 ; buffer empty?
bra nz, RX2Q1
mov U2RXREG, W0 ; get chr, dump
.endif
.endif
RX2Q1:
return
<snip>
QUIT1:
rcall check_sp
rcall CR
rcall TIB
mov [W14++], [W14] ; dup
rcall TIBSIZE
mlit HOLD_SIZE ; Reserve for hold buffer
rcall MINUS
rcall ACCEPT
.if WRITE_METHOD == 2
.if FC2_TYPE == 1
mov #XOFF, W2
mov W2, U2TXREG ; send chr
bset iflags, #ixoff2
.endif
.endif
rcall SPACE_
rcall INTERPRET
rcall STATE
cp0 [W14--]
bra nz, QUIT1
.if WRITE_METHOD == 2
btss iflags1, #edirty ; If dirty then write after
timeout in PAUSE
.endif
rcall DP_TO_EEPROM
rcall XSQUOTE
.byte 3
.ascii "ok "
.align 2
rcall TYPE
rcall PROMPT
bra QUIT0
return
Mike Miller WB6TMH
Moon Valley Circuits
Glen Ellen, CA 95442
|