1 ; con speed of TERMINAL link, there are three bottlenecks :
2 ; 1- time to send XOFF/RTS_high on CR (CR+LF=EOL), first emergency.
3 ; 2- the char loop time,
4 ; 3- the time between sending XON/RTS_low and clearing UCRXIFG on first received char,
5 ; everything must be done to reduce these times, taking into account the necessity of switching to SLEEP (LPMx mode).
6 ; --------------------------------------;
7 ; (ACCEPT) part I: prepare TERMINAL_INT ;
8 ; --------------------------------------;
9 MOV #ENDACCEPT,S ;2 S = ACCEPT XOFF return
10 MOV #AKEYREAD1,T ;2 T = default XON return
11 .word 152Dh ;5 PUSHM IP,S,T, as IP ret, XOFF ret, XON ret
12 MOV TOS,W ;1 -- addr len
13 MOV @PSP,TOS ;2 -- org ptr )
14 ADD TOS,W ;1 -- org ptr W=Bound )
15 MOV #0Dh,T ;2 T = 'CR' to speed up char loop in part II > prepare stack and registers
16 MOV #20h,S ;2 S = 'BL' to speed up char loop in part II ) for TERMINAL_INT use
17 BIT #UCRXIFG,&TERMIFG ;3 RX_Int ?
18 JZ ACCEPTNEXT ;2 no : case of quiet input terminal
19 MOV &TERMRXBUF,Y ;3 yes: clear RX_Int
20 CMP #0Ah,Y ;2 received char = LF ? (end of downloading ?)
21 JNZ RXON ;2 no : RXON return = AKEYREAD1, to process first char of new line.
22 ACCEPTNEXT ADD #2,RSP ;1 yes: remove AKEYREAD1 as XON return,
23 MOV #SLEEP,X ;2 and set XON return = SLEEP
24 .word 153Ch ;6 PUSHM S,T,W,X before SLEEP (and so WAKE on any interrupts)
25 ; --------------------------------------;
27 ; --------------------------------------;
28 .IFDEF TERMINAL3WIRES ;
29 RXON_LOOP BIT #UCTXIFG,&TERMIFG ;3 wait the sending end of XON, useless at high baudrates
31 MOV #17,&TERMTXBUF ;4 move char XON into TX_buf
33 .IFDEF TERMINAL4WIRES ;
34 BIC.B #RTS,&HANDSHAKOUT ;4 set RTS low
36 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
37 ; starts first and 3th stopwatches ;
38 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
39 RET ;4 to SLEEP (End of file download or quiet input) or AKEYREAD1 (get next line of file downloading)
40 ; --------------------------------------;
42 ; --------------------------------------;
44 ; --------------------------------------;
45 .IFDEF TERMINAL3WIRES ;
46 RXOFF_LOOP BIT #UCTXIFG,&TERMIFG ;3 wait the sending end of XOFF, useless at high baudrates
48 MOV #19,&TERMTXBUF ;4 move XOFF char into TX_buf
50 .IFDEF TERMINAL4WIRES ;
51 BIS.B #RTS,&HANDSHAKOUT ;4 set RTS high
54 ; --------------------------------------;
56 ; --------------------------------------;
57 ASMWORD "SLEEP" ; may be redirected
60 ; --------------------------------------;
62 ; --------------------------------------;
65 BIS &LPM_MODE,SR ;3 enter in LPMx sleep mode with GIE=1
66 ; --------------------------------------; default FAST FORTH mode (for its input terminal use) : LPM0.
68 ;###############################################################################################################
69 ;###############################################################################################################
71 ; ### # # ####### ####### ###### ###### # # ###### ####### ##### # # ####### ###### #######
72 ; # ## # # # # # # # # # # # # # # # # # # # #
73 ; # # # # # # # # # # # # # # # # # # # # # #
74 ; # # # # # ##### ###### ###### # # ###### # ##### ####### ##### ###### #####
75 ; # # # # # # # # # # # # # # # # # # # # #
76 ; # # ## # # # # # # # # # # # # # # # # # #
77 ; ### # # # ####### # # # # ##### # # ##### # # ####### # # #######
79 ;###############################################################################################################
80 ;###############################################################################################################
83 ; here, Fast FORTH sleeps, waiting any interrupt.
84 ; IP,S,T,W,X,Y registers (R13 to R8) are free for any interrupt routine...
85 ; ...and so PSP and RSP stacks with their rules of use.
86 ; remember: in any interrupt routine you must include : BIC #0x78,0(RSP) before RETI
87 ; to force return to SLEEP.
88 ; or (bad idea ? previous SR flags are lost) simply : ADD #2 RSP, then RET instead of RETI
91 ; ======================================;
92 JMP SLEEP ;2 here is the return for any interrupts, else TERMINAL_INT :-)
93 ; ======================================;
96 ; **************************************;
97 TERMINAL_INT ; <--- TEMR RX interrupt vector, delayed by the LPMx wake up time
98 ; **************************************; if wake up time increases, max bauds rate decreases...
99 ; (ACCEPT) part II under interrupt ; Org Ptr -- len'
100 ; --------------------------------------;
101 ADD #4,RSP ;1 remove SR and PC from stack, SR flags are lost (unused by FORTH interpreter)
102 .word 172Ah ;5 POPM W=buffer_bound,T=0Dh,S=20h
103 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
104 ; starts the 2th stopwatch ;
105 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
106 AKEYREAD MOV.B &TERMRXBUF,Y ;3 read character into Y, UCRXIFG is cleared
107 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
108 ; stops the 3th stopwatch ; 3th bottleneck result : 17~ + LPMx wake_up time ( + 5~ XON loop if F/Bds<230401 )
109 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
110 AKEYREAD1 ; <--- XON RET address 2 ; first emergency: anticipate XOFF on CR as soon as possible
111 CMP.B T,Y ;1 char = CR ?
112 JZ RXOFF ;2 then RET to ENDACCEPT
113 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;+ 4 to send RXOFF
114 ; stops the first stopwatch ;= first bottleneck (empty line process), best case result: 20~ + LPMx wake_up time..
115 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^; ...or 11~ in case of empty line
116 CMP.B S,Y ;1 printable char ?
117 JHS ASTORETEST ;2 yes
118 CMP.B #8,Y ; char = BS ?
119 JNE WAITaKEY ; case of other control chars
120 ; --------------------------------------;
121 ; start of backspace ; made only by an human
122 ; --------------------------------------;
123 CMP @PSP,TOS ; Ptr = Org ?
124 JZ WAITaKEY ; yes: do nothing else
125 SUB #1,TOS ; no : dec Ptr
127 ; --------------------------------------;
129 ; --------------------------------------;
130 ASTORETEST CMP W,TOS ; 1 Bound is reached ?
131 JZ WAITaKEY ; 2 yes: loopback
132 MOV.B Y,0(TOS) ; 3 no: store char @ Ptr, send echo then loopback
133 ADD #1,TOS ; 1 increment Ptr
134 ; --------------------------------------;
135 WAITaKEY BIT #UCRXIFG,&TERMIFG ; 3 new char in TERMRXBUF ?
138 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
139 ; stops the 2th stopwatch ; best case result: 23~ ==> 434 kBds/MHz
140 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
141 ; --------------------------------------;
142 ENDACCEPT ; <--- XOFF return address
143 ; --------------------------------------;
144 MOV #LPM0+GIE,&LPM_MODE ; reset LPM_MODE to default mode LPM0 for next line of input stream
145 CMP #0,&LINE ; if LINE <> 0...
147 ADD #1,&LINE ; ...increment LINE
148 DROPEXIT SUB @PSP+,TOS ; Org Ptr -- len'
149 MOV @RSP+,IP ; 2 and continue with INTERPRET with GIE=0.
150 ; So FORTH machine is protected against any interrupt...
151 mNEXT ; ...until next falling down to LPMx mode of (ACCEPT) part1,
152 ; **************************************; i.e. when the FORTH interpreter has no more to do.
154 ; ------------------------------------------------------------------------------
155 ; TERMINAL I/O, output part
156 ; ------------------------------------------------------------------------------
159 ;Z (EMIT) c -- output character (byte) to the terminal
160 ; hardware or software control on TX flow seems not necessary with UARTtoUSB bridges because
161 ; they stop TX when their RX buffer is full. So no problem when the terminal input is echoed to output.
163 PARENEMIT MOV TOS,Y ; 1
165 YEMIT1 BIT #UCTXIFG,&TERMIFG ; 3 wait the sending end of previous char, useless at high baudrates
167 .IFDEF TERMINAL5WIRES ;
168 YEMIT2 BIT.B #CTS,&HANDSHAKIN ;
171 YEMIT .word 4882h ; hi7/4~ lo:12/4~ send/send_not echo to terminal
172 .word TERMTXBUF ; 3 MOV Y,&TERMTXBUF