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 ; ----------------------------------;
10 PUSHM #4,R7 ;6 push R7,R6,R5,R4
12 MOV #ENDACCEPT,S ;2 S = ACCEPT XOFF return
13 MOV #AKEYREAD1,T ;2 T = default XON return
14 PUSHM #3,IP ;5 PUSHM IP,S,T, as IP ret, XOFF ret, XON ret
15 MOV TOS,W ;1 -- addr len
16 MOV @PSP,TOS ;2 -- org ptr )
17 ADD TOS,W ;1 -- org ptr W=Bound )
18 MOV #0Dh,T ;2 T = 'CR' to speed up char loop in part II > prepare stack and registers
19 MOV #20h,S ;2 S = 'BL' to speed up char loop in part II ) for TERMINAL_INT use
20 BIT #UCRXIFG,&TERM_IFG ;3 RX_Int ?
21 JZ ACCEPTNEXT ;2 no : case of quiet input terminal
22 MOV &TERM_RXBUF,Y ;3 yes: clear RX_Int
23 CMP #0Ah,Y ;2 received char = LF ? (end of downloading ?)
24 JNZ RXON ;2 no : RXON return = AKEYREAD1, to process first char of new line.
25 ACCEPTNEXT ADD #2,RSP ;1 yes: remove AKEYREAD1 as XON return,
26 MOV #SLEEP,X ;2 and set XON return = SLEEP
27 PUSHM #4,S ;6 PUSHM S,T,W,X before SLEEP (and so WAKE on any interrupts)
28 ; ----------------------------------;
31 MOV #0A503h,&SYSCFG0 ; disable write MAIN + INFO
33 MOV #0A501h,&MPUCTL0 ; set MPU (Memory Protection Unit) enable bit
36 ; ----------------------------------;
39 ; ----------------------------------;
40 .IFDEF TERMINAL3WIRES ;
41 RXON_LOOP BIT #UCTXIFG,&TERM_IFG ;3 wait the sending end of XON, useless at high baudrates
43 MOV #17,&TERM_TXBUF ;4 move char XON into TX_buf
45 .IFDEF TERMINAL4WIRES ;
46 BIC.B #RTS,&HANDSHAKOUT ;4 set RTS low
48 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
49 ; starts first and 3th stopwatches ;
50 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
51 RET ;4 to SLEEP (End of file download or quiet input) or AKEYREAD1 (get next line of file downloading)
52 ; ----------------------------------;
54 ; ----------------------------------;
56 ; ----------------------------------;
57 .IFDEF TERMINAL3WIRES ;
58 RXOFF_LOOP BIT #UCTXIFG,&TERM_IFG ;3 wait the sending end of XOFF, useless at high baudrates
60 MOV #19,&TERM_TXBUF ;4 move XOFF char into TX_buf
62 .IFDEF TERMINAL4WIRES ;
63 BIS.B #RTS,&HANDSHAKOUT ;4 set RTS high
66 ; ----------------------------------;
68 ; ----------------------------------;
69 ASMWORD "SLEEP" ; may be redirected
70 SLEEP MOV @PC+,PC ;3 Code Field Address (CFA) of SLEEP
71 PFASLEEP .word BODYSLEEP ; Parameter Field Address (PFA) of SLEEP, with default value
72 BODYSLEEP BIS &LPM_MODE,SR ;3 enter in LPMx sleep mode with GIE=1
73 ; ----------------------------------; default FAST FORTH mode (for its input terminal use) : LPM0.
75 ;###############################################################################################################
76 ;###############################################################################################################
78 ; ### # # ####### ####### ###### ###### # # ###### ####### ##### # # ####### ###### #######
79 ; # ## # # # # # # # # # # # # # # # # # # # #
80 ; # # # # # # # # # # # # # # # # # # # # # #
81 ; # # # # # ##### ###### ###### # # ###### # ##### ####### ##### ###### #####
82 ; # # # # # # # # # # # # # # # # # # # # #
83 ; # # ## # # # # # # # # # # # # # # # # # #
84 ; ### # # # ####### # # # # ##### # # ##### # # ####### # # #######
86 ;###############################################################################################################
87 ;###############################################################################################################
90 ; here, Fast FORTH sleeps, waiting any interrupt.
91 ; IP,S,T,W,X,Y registers (R13 to R8) are free for any interrupt routine...
92 ; ...and so PSP and RSP stacks with their rules of use.
93 ; remember: in any interrupt routine you must include : BIC #0x78,0(RSP) before RETI
94 ; to force return to SLEEP.
95 ; or (bad idea ? previous SR flags are lost) simply : ADD #2 RSP, then RET instead of RETI
97 ; ==================================;
98 JMP SLEEP ;2 here is the return for any interrupts, else TERMINAL_INT :-)
99 ; ==================================;
102 ; **********************************;
103 TERMINAL_INT ; <--- TEMR RX interrupt vector, delayed by the LPMx wake up time
104 ; **********************************; if wake up time increases, max bauds rate decreases...
105 ; (ACCEPT) part II under interrupt ; Org Ptr -- len'
106 ; ----------------------------------;
107 POPM #5,S ;8 POPM Y=SR,X=PC,W=buffer_bound, T=0Dh,S=20h
108 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
109 ; starts the 2th stopwatch ;
110 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
111 AKEYREAD MOV.B &TERM_RXBUF,Y ;3 read character into Y, UCRXIFG is cleared
112 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
113 ; stops the 3th stopwatch ; 3th bottleneck result : 17~ + LPMx wake_up time ( + 5~ XON loop if F/Bds<230401 )
114 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
115 AKEYREAD1 ; <--- XON RET address 2 ; first emergency: anticipate XOFF on CR as soon as possible
116 CMP.B T,Y ;1 char = CR ?
117 JZ RXOFF ;2 then RET to ENDACCEPT
118 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;+ 4 to send RXOFF
119 ; stops the first stopwatch ;= first bottleneck (empty line process), best case result: 20~ + LPMx wake_up time..
120 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^; ...or 11~ in case of empty line
121 CMP.B S,Y ;1 printable char ?
122 JHS ASTORETEST ;2 yes
123 CMP.B #8,Y ; char = BS ?
124 JNE WAITaKEY ; case of other control chars
125 ; ----------------------------------;
126 ; start of backspace ; made only by an human
127 ; ----------------------------------;
128 CMP @PSP,TOS ; Ptr = Org ?
129 JZ WAITaKEY ; yes: do nothing else
130 SUB #1,TOS ; no : dec Ptr
132 ; ----------------------------------;
134 ; ----------------------------------;
135 ASTORETEST CMP W,TOS ; 1 Bound is reached ?
136 JZ WAITaKEY ; 2 yes: loopback
137 MOV.B Y,0(TOS) ; 3 no: store char @ Ptr, send echo then loopback
138 ADD #1,TOS ; 1 increment Ptr
139 ; ----------------------------------;
140 WAITaKEY BIT #UCRXIFG,&TERM_IFG ; 3 new char in TERMRXBUF ?
143 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
144 ; stops the 2th stopwatch ; best case result: 23~ ==> 434 kBds/MHz
145 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
146 ; ----------------------------------;
147 ENDACCEPT ; <--- XOFF return address
148 ; ----------------------------------;
149 MOV #LPM0+GIE,&LPM_MODE ; reset LPM_MODE to default mode LPM0 for next line of input stream
150 ; ----------------------------------;
153 MOV #0A500h,&SYSCFG0 ; enable write MAIN + INFO
155 MOV #0A500h,&MPUCTL0 ; clear MPU (Memory Protection Unit) enable bit
158 ; ----------------------------------;
159 CMP #0,&LINE ; if LINE <> 0...
161 ADD #1,&LINE ; ...increment LINE
162 ACCEPTEND SUB @PSP+,TOS ; Org Ptr -- len'
163 MOV @RSP+,IP ; 2 and continue with INTERPRET with GIE=0.
164 ; So FORTH machine is protected against any interrupt...
166 POPM #4,R7 ;6 pop R4,R5,R6,R7
168 mNEXT ; ...until next falling down to LPMx mode of (ACCEPT) part1,
169 ; **********************************; i.e. when the FORTH interpreter has no more to do.
171 ; ------------------------------------------------------------------------------
172 ; TERMINAL I/O, output part
173 ; ------------------------------------------------------------------------------
176 ;https://forth-standard.org/standard/core/EMIT
177 ;C EMIT c -- output character to the output device ; deferred word
179 EMIT MOV @PC+,PC ;3 15~
180 PFAEMIT .word BODYEMIT ; Parameter Field Address (PFA) of EMIT, with its default value
181 BODYEMIT MOV TOS,Y ; 1
183 YEMIT1 BIT #UCTXIFG,&TERM_IFG ; 3 wait the sending end of previous char, useless at high baudrates
185 .IFDEF TERMINAL5WIRES ;
186 YEMIT2 BIT.B #CTS,&HANDSHAKIN ;
189 YEMIT .word 4882h ; hi7/4~ lo:12/4~ send/send_not echo to terminal
190 .word TERM_TXBUF ; 3 MOV Y,&TERMTXBUF