1 ; -*- coding: utf-8 -*-
4 ; ---------------------------------------
5 ; TERMINAL driver for FastForth target
6 ; ---------------------------------------
7 ; +---------------------------+
8 ; ------ | +-----------------+ |
9 ; WIRING | | +--------+ | |
11 ; FastForth target TXD RXD RTS <--> CTS TXD RXD UARTtoUSB <--> COMx <--> TERMINAL
12 ; -----------------------------------------------------------------------------------------
13 ; MSP_EXP430FR5739 P2.0 P2.1 P2.2 PL2303TA TERATERM.EXE
14 ; MSP_EXP430FR5969 P2.0 P2.1 P4.1 PL2303HXD
15 ; MSP_EXP430FR5994 P2.0 P2.1 P4.2 CP2102
16 ; MSP_EXP430FR6989 P3.4 P3.5 P3.0
17 ; MSP_EXP430FR4133 P1.0 P1.1 P2.3
18 ; CHIPSTICK_FR2433 P1.4 P1.5 P3.2
19 ; MSP_EXP430FR2433 P1.4 P1.5 P1.0
20 ; MSP_EXP430FR2355 P4.3 P4.2 P2.0
21 ; LP_MSP430FR2476 P1.4 P1.5 P6.1
23 ;-------------------------------------------------------------------------------
24 ; UART TERMINAL: QABORT ABORT_TERM COLD_TERM INI_TERM RXON RXOFF
25 ;-------------------------------------------------------------------------------
26 ; define run-time part of ABORT"
27 ;Z ?ABORT xi f c-addr u -- abort & print msg.
29 QABORT CMP #0,2(PSP) ; -- f c-addr u test flag f
31 THREEDROP ADD #4,PSP ; -- u
34 ; ----------------------------------;
35 ABORT_TERM ; exit from downloading file then reinit some variables via INI_FORTH
36 ; ----------------------------------;
37 CALL #RXON ; PFA resume downloading source file if any
38 A_UART_LOOP BIC #RX_TERM,&TERM_IFG ; clear RX_TERM
39 MOV &FREQ_KHZ,Y ; 1000, 2000, 4000, 8000, 16000, 240000
40 A_USB_LOOPJ MOV #65,X ; 2~ <-------+ linux with minicom seems very very slow...
41 A_USB_LOOPI SUB #1,X ; 1~ <---+ | ==> ((65*3)+5)*1000 = 200ms delay
42 JNZ A_USB_LOOPI ; 2~ 3~ loop ---+ | to refill its USB buffer
44 JNZ A_USB_LOOPJ ; 2~ 200~ loop -----+
45 BIT #RX_TERM,&TERM_IFG ; 4 new char in TERMRXBUF after A_USB_LOOPJ delay ?
46 JNZ A_UART_LOOP ; 2 yes, the input stream is still active: loop back
47 CALL #INI_FORTH ; common ?ABORT|RST, "hybrid" subroutine with return to FORTH interpreter
48 ; ----------------------------------;
49 ; display line of error if NOECHO ;
50 ; ----------------------------------;
51 .word lit,LINE,FETCH ; -- f c-addr u line fetch line number before set ECHO !
54 .byte 4,27,"[7m" ; type ESC[7m (set reverse video)
56 .word QDUP,QFBRAN ; don't display line if line = 0 (ECHO was ON)
58 .word XSQUOTE ; -- f c-addr u line c-addr1 u1 displays the line where error occured
59 .byte 15,"LAST.4TH, line " ;
60 .word TYPE ; -- f c-addr u line
61 .word UDOT ; -- f c-addr u
62 ; ----------------------------------;
63 ; Display ABORT|WARM message ; <== WARM jumps here
64 ; ----------------------------------;
65 ABORT_TYPE .word TYPE ; -- f type abort message
66 .word XSQUOTE ; -- f c-addr u
68 .word TYPE ; -- f set normal video
69 .word ABORT ; without return
70 ; ----------------------------------;
72 ; ----------------------------------;
73 COLD_TERM ; default STOP_APP: wait TERMINAL idle
74 ; ----------------------------------;
76 BIT #1,&TERM_STATW ;3 uart busy ?
77 JNZ COLD_TERM ;2 loop back while TERM_UART is busy
78 MOV @RSP+,PC ; return to software_BOR
79 ; ----------------------------------;
81 ; ----------------------------------;
82 INIT_TERM ; TOS = RSTIV_MEM
83 ; ----------------------------------;
86 JNC UART_INIT_TERM_END ; no INIT_TERM if RSTIV_MEM U< 2 (WARM|ABORT)
87 ; ----------------------------------;
88 MOV #0081h,&TERM_CTLW0 ; UC SWRST + UCLK = SMCLK
89 MOV &TERMBRW_RST,&TERM_BRW ; init value in FRAM INFO
90 MOV &TERMMCTLW_RST,&TERM_MCTLW ; init value in FRAM INFO
91 BIS.B #BUS_TERM,&TERM_SEL ; Configure pins TERM_UART|TERM_I2C
92 BIC #1,&TERM_CTLW0 ; release UC_TERM from reset...
93 BIS #WAKE_UP,&TERM_IE ; then enable interrupt for wake up on terminal input
94 BIC #LOCKLPM5,&PM5CTL0 ; activate all previous I/O settings.
97 ; ----------------------------------;
100 ; ----------------------------------;
101 UART_RXON JMP RXON_EXE ; Software and/or hardware flow control, to start Terminal UART for one line
102 ; ----------------------------------;
104 ; ----------------------------------;
105 RXOFF ; Software and/or hardware flow control, to stop Terminal UART comunication
106 ; ----------------------------------;
108 .IFDEF TERMINAL3WIRES ; first software flow control
109 RXOFF_LOOP BIT #TX_TERM,&TERM_IFG ;3 wait the sending of last char
111 MOV #19,&TERM_TXBUF ;4 move XOFF char into TX_buf
113 .IFDEF TERMINAL4WIRES ; and hardware flow control after
114 BIS.B #RTS,&HANDSHAKOUT ;3 set RTS high
116 MOV @RSP+,PC ;4 to CR_NEXT, ...or user defined
117 ; ----------------------------------;
119 ; ----------------------------------;
120 RXON ; default BACKGND_APP
121 ; ----------------------------------;
123 ; ----------------------------------;
124 .IFDEF TERMINAL3WIRES ; first software flow control
125 RXON_LOOP BIT #TX_TERM,&TERM_IFG ;3 wait the sending of last char, useless at high baudrates
127 MOV #17,&TERM_TXBUF ;4 move char XON into TX_buf
129 .IFDEF TERMINAL4WIRES ; and hardware flow control after
130 BIC.B #RTS,&HANDSHAKOUT ;3 set RTS low
132 MOV @RSP+,PC ;4 to BACKGND (End of file download or quiet input) or AKEYREAD...
133 ; ----------------------------------; ... (get next line of file downloading), or user defined
136 ;-------------------------------------------------------------------------------
137 ; UART TERMINAL : WIPE COLD WARM ACCEPT KEY EMIT ECHO NOECHO
138 ;-------------------------------------------------------------------------------
140 ;-----------------------------------;
141 FORTHWORD "WIPE" ; software DEEP_RESET
142 ;-----------------------------------;
143 WIPE MOV #-1,&RSTIV_MEM ; negative value ==> DEEP_RESET
146 ;-----------------------------------;
148 ;-----------------------------------;
149 ;Z COLD -- performs a software RESET
150 ; as pin RST is replaced by pin NMI, RESET by pin activation is redirected here via USER NMI vector
151 ; that allows actions to be performed before executing software BOR.
152 COLD CALL @PC+ ; COLD first calls STOP_APP, in this instance: CALL #COLD_TERM by default
153 PFACOLD .word COLD_TERM ; INI_COLD_DEF: default value set by WIPE. see forthMSP430FR_TERM_xxxx.asm
154 BIT.B #IO_WIPE,&WIPE_IN ; hardware Deep_RESET request (low) ?
156 MOV #-1,&RSTIV_MEM ; yes, set negative value to force DEEP_RESET
157 COLDEXE MOV #0A504h,&PMMCTL0 ; performs software_BOR --> RST_vector --> RESET in forthMSP430FR.asm
158 ; ----------------------------------;
160 ;-----------------------------------;
162 ;-----------------------------------;
163 ;Z WARM xi -- ; common part of WARM|PUC
164 ;-----------------------------------;
166 ;-------------------------------------------------------------------------------
167 ; PUC 7: if RSTIV_MEM <> WARM, init TERM and enable I/O
168 ;-------------------------------------------------------------------------------
169 CALL @PC+ ; init TERM, only if TOS U>= 2 (RSTIV_MEM <> WARM)
170 .IFNDEF SD_CARD_LOADER ;
171 PFAWARM .word INIT_TERM ; INI_HARD_APP default value, init TERM UC, unlock I/O's, TOS = RSTIV_MEM
173 PFAWARM .word INI_HARD_SD ; init SD Card + init TERM, see forthMSP430FR_SD_INIT.asm
174 .ENDIF ; TOS = RSTIV_MEM
175 ;-----------------------------------;
176 WARM_DISPLAY ; TOS = RSTIV_MEM value
177 ASMtoFORTH ; display a message then goto QUIT, without return
179 .byte 7,13,10,27,"[7m#" ; CR + cmd "reverse video" + #
181 .word DOT ; display TOS = RSTIV_MEM value
183 .byte 25,"FastForth ©J.M.Thoorens "
185 .word LIT,FRAM_FULL,HERE,MINUS,UDOT
187 .byte 10,"bytes free"
188 .word BRAN,ABORT_TYPE
189 ; ----------------------------------;
191 ;-----------------------------------;
193 ;-----------------------------------;
194 ;https://forth-standard.org/standard/core/ACCEPT
195 ;C ACCEPT addr addr len -- addr len' from REFILL, get line at addr to interpret len' chars
196 ACCEPT MOV @PC+,PC ;3 Code Field Address (CFA) of ACCEPT
197 PFAACCEPT .word BODYACCEPT ; Parameter Field Address (PFA) of ACCEPT
198 BODYACCEPT ; BODY of ACCEPT = default execution of ACCEPT
199 ; ----------------------------------;
200 ; ACCEPT part I prepare TERMINAL_INT; this version allows to RX one char (LF) after sending XOFF
201 ; ----------------------------------;
202 MOV TOS,Y ;1 -- addr len
203 MOV @PSP,TOS ;2 -- org ptr
204 ADD TOS,Y ;1 -- org ptr Y = buf_end )
205 MOV #0Dh,X ;2 X = 'CR' to speed up char loop in part II )
206 MOV #20h,W ;2 W = 'BL' to speed up char loop in part II >
207 MOV #YEMIT_NEXT,T ;2 T = return for QYEMIT )
208 MOV #CR_NEXT,S ;2 S = CR_NEXT )
209 PUSHM #6,IP ;8 PUSHM IP,S,T,W,X,Y r-- ACCEPT_ret CR_NEXT YEMIT_NEXT BL CR buf_end
210 JMP SLEEP ;2 which calls RXON before falling down to LPMx mode
211 ; ----------------------------------;
213 ; **********************************;
214 TERMINAL_INT ; <--- TEMR RX interrupt vector, delayed by the LPMx wake up time
215 ; **********************************; if wake up time increases, max bauds rate decreases...
216 ; ACCEPT part II under interrupt ; Org Ptr -- len'
217 ; ----------------------------------;
218 ADD #4,RSP ;1 remove SR and PC from stack, cleared flags: V SCG1 OSCOFF CPUOFF GIE N Z C
219 POPM #4,IP ;6 POPM W=buffer_bound, T=0Dh, S=20h, IP=YEMIT_NEXT r-- ACCEPT_ret CR_NEXT
220 ; ----------------------------------;
221 AKEYREAD MOV.B &TERM_RXBUF,Y ;3 read character into Y, RX_TERM is cleared
222 ; ----------------------------------;
224 JZ RXOFF ;2 then RET to CR_NEXT
225 CMP.B S,Y ;1 printable char ?
227 ; ----------------------------------;
228 CMP.B #8,Y ;1 char = BS ?
229 JNE WAITaKEY ;2 case of other control chars
230 ; ----------------------------------;
231 ; start of backspace ; made only by an human
232 ; ----------------------------------;
233 CMP @PSP,TOS ; Ptr = Org ?
234 JZ WAITaKEY ; yes: do nothing
235 SUB #1,TOS ; no : dec Ptr
236 JMP YEMIT ; don't store BS
237 ; ----------------------------------;
238 ASTORETEST CMP W,TOS ; 1 Bound is reached ?
239 JZ YEMIT ; 2 yes: don't store char @ Ptr
240 MOV.B Y,0(TOS) ; 3 no: store char @ Ptr
241 ADD #1,TOS ; 1 increment Ptr
242 ; ----------------------------------;
243 YEMIT BIT #TX_TERM,&TERM_IFG ; 3 wait the sending end of previous char, useless at high baudrates,
244 JZ YEMIT ; 2 but there's no point in wanting to save time here:
245 .IFDEF TERMINAL5WIRES ;
246 YEMIT1 BIT.B #CTS,&HANDSHAKIN ; 3 CTS is pulled low if unwired.
249 QYEMIT .word 48C2h ; 48C2h = MOV.B Y,&<next_adr>
252 ; ----------------------------------;
253 YEMIT_NEXT .word $+2 ; 0 YEMII NEXT address
254 SUB #2,IP ; 1 restore YEMIT_NEXT
255 ; ----------------------------------;
256 WAITaKEY BIT #RX_TERM,&TERM_IFG ; 3 new char in TERMRXBUF ?
257 JNZ AKEYREAD ; 2 yes, loop = 34~/31~ by char (with/without echo) ==> 294/322 kBds/MHz
259 ; ----------------------------------;
261 ; ----------------------------------;
262 ; return of RXOFF ; --- Org Ptr r-- ACCEPT_NEXT
263 ; ----------------------------------;
264 CR_NEXT SUB @PSP+,TOS ; -- len'
266 ; ----------------------------------;
267 MOV #LPM0+GIE,&LPM_MODE ; reset LPM_MODE to default mode LPM0 for next line of input stream
268 ; ----------------------------------;
269 WAITLF BIT #RX_TERM,&TERM_IFG ; char 'LF' is received ?
271 MOV.B &TERM_RXBUF,Y ; yes, clear RX_int flag after LF received
272 ; ----------------------------------;
273 ACCEPT_EOL CMP #0,&LINE ; if LINE <> 0 increment LINE
277 ; ----------------------------------;
278 MOV S,Y ; output a BL on TERMINAL (for the case of error occuring)
279 JMP YEMIT ; before return to ABORT to interpret line
280 ; **********************************; UF9 to UF11 are reset.
282 ;-----------------------------------;
284 ;-----------------------------------;
285 ; https://forth-standard.org/standard/core/KEY
286 ; KEY -- c wait character from input device ; primary DEFERred word
287 KEY MOV @PC+,PC ;4 Code Field Address (CFA) of KEY
288 PFAKEY .word BODYKEY ; Parameter Field Address (PFA) of KEY, with default value
289 BODYKEY SUB #2,PSP ;1 push old TOS..
290 MOV TOS,0(PSP) ;3 ..onto stack
292 KEYLOOP BIT #RX_TERM,&TERM_IFG ; loop if bit0 = 0 in interupt flag register
294 MOV &TERM_RXBUF,TOS ;
298 ;-----------------------------------;
300 ;-----------------------------------;
301 ; https://forth-standard.org/standard/core/EMIT
302 ; EMIT c -- output character to the selected output device ; primary DEFERred word
303 EMIT MOV @PC+,PC ;4 Code Field Address (CFA) of EMIT
304 PFAEMIT .word BODYEMIT ; Parameter Field Address (PFA) of EMIT, with its default value
305 BODYEMIT MOV TOS,Y ;1 output character to the default output: TERMINAL
309 ;-----------------------------------;
311 ;-----------------------------------;
312 ;Z ECHO -- connect terminal output (default)
313 ECHO MOV #48C2h,&QYEMIT ; 48C2h = MOV.B Y,&<next_adr>
317 ;-----------------------------------;
319 ;-----------------------------------;
320 ;Z NOECHO -- disconnect terminal output
321 NOECHO MOV #4D30h,&QYEMIT ; NEXT = 4D30h = MOV @IP+,PC