OSDN Git Service

Update FF_SPECS.f
[fast-forth/master.git] / forthMSP430FR_TERM_UART.asm
1 ; -*- coding: utf-8 -*-
2 ;
3
4 ; ---------------------------------------
5 ; TERMINAL driver for FastForth target
6 ; ---------------------------------------
7 ;                     +---------------------------+
8 ; ------              |    +-----------------+    |
9 ; WIRING              |    |    +--------+   |    |
10 ; ------              |    |    |        |   |    |
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
22 ;
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.
28 ;            FORTHWORD "?ABORT"
29 QABORT      CMP #0,2(PSP)           ; -- f c-addr u         test flag f
30             JNZ ABORT_TERM          ;
31 THREEDROP   ADD #4,PSP              ; -- u
32             MOV @PSP+,TOS           ; -- 
33             MOV @IP+,PC             ;
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
43             SUB #1,Y                ; 1~                |
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 !
52             .word   ECHO            ;
53             .word   XSQUOTE         ;
54             .byte   4,27,"[7m"      ;                       type ESC[7m    (set reverse video)
55             .word   TYPE            ;  
56             .word   QDUP,QFBRAN     ;                       don't display line if line = 0 (ECHO was ON)
57             .word   ABORT_TYPE      ;
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
67             .byte   4,27,"[0m"      ;
68             .word   TYPE            ; -- f              set normal video
69             .word   ABORT           ; without return
70 ; ----------------------------------;
71
72 ; ----------------------------------;
73 COLD_TERM                           ; default STOP_APP: wait TERMINAL idle
74 ; ----------------------------------;
75 UART_COLD_TERM                      ;
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 ; ----------------------------------;
80
81 ; ----------------------------------;
82 INIT_TERM                           ; TOS = RSTIV_MEM
83 ; ----------------------------------;
84 UART_INIT_TERM                      ;
85     CMP #2,TOS                      ;
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.
95 UART_INIT_TERM_END
96     MOV @RSP+,PC                    ; RET
97 ; ----------------------------------;
98
99
100 ; ----------------------------------;
101 UART_RXON   JMP RXON_EXE            ; Software and/or hardware flow control, to start Terminal UART for one line
102 ; ----------------------------------;
103
104 ; ----------------------------------;
105 RXOFF                               ; Software and/or hardware flow control, to stop Terminal UART comunication
106 ; ----------------------------------;
107 UART_RXOFF                          ;
108     .IFDEF TERMINAL3WIRES           ;   first software flow control
109 RXOFF_LOOP  BIT #TX_TERM,&TERM_IFG  ;3      wait the sending of last char
110             JZ RXOFF_LOOP           ;2
111             MOV #19,&TERM_TXBUF     ;4      move XOFF char into TX_buf
112     .ENDIF                          ;
113     .IFDEF TERMINAL4WIRES           ;   and hardware flow control after
114             BIS.B #RTS,&HANDSHAKOUT ;3  set RTS high
115     .ENDIF                          ;
116             MOV @RSP+,PC            ;4 to CR_NEXT, ...or user defined
117 ; ----------------------------------;
118
119 ; ----------------------------------;
120 RXON                                ; default BACKGND_APP 
121 ; ----------------------------------;
122 RXON_EXE
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
126             JZ RXON_LOOP            ;2
127             MOV #17,&TERM_TXBUF     ;4  move char XON into TX_buf
128     .ENDIF                          ;
129     .IFDEF TERMINAL4WIRES           ;   and hardware flow control after
130             BIC.B #RTS,&HANDSHAKOUT ;3      set RTS low
131     .ENDIF                          ;
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
134
135
136 ;-------------------------------------------------------------------------------
137 ; UART TERMINAL : WIPE COLD WARM ACCEPT KEY EMIT ECHO NOECHO
138 ;-------------------------------------------------------------------------------
139
140 ;-----------------------------------;
141             FORTHWORD "WIPE"        ; software DEEP_RESET
142 ;-----------------------------------;
143 WIPE        MOV #-1,&RSTIV_MEM      ; negative value ==> DEEP_RESET
144             JMP COLD
145
146 ;-----------------------------------;
147             FORTHWORD "COLD"
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) ?
155             JNZ COLDEXE             ; no
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 ; ----------------------------------;
159
160 ;-----------------------------------;
161             FORTHWORD "WARM"        ;
162 ;-----------------------------------;
163 ;Z WARM     xi --                   ; common part of WARM|PUC
164 ;-----------------------------------;
165 WARM                                ;
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
172     .ELSE
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
178     .word   XSQUOTE
179     .byte   7,13,10,27,"[7m#"       ; CR + cmd "reverse video" + #
180     .word   TYPE
181     .word   DOT                     ; display TOS = RSTIV_MEM value
182     .word   XSQUOTE
183     .byte   25,"FastForth ©J.M.Thoorens "
184     .word   TYPE
185     .word   LIT,FRAM_FULL,HERE,MINUS,UDOT
186     .word   XSQUOTE
187     .byte   10,"bytes free"
188     .word   BRAN,ABORT_TYPE
189 ; ----------------------------------;
190
191 ;-----------------------------------;
192             FORTHWORD "ACCEPT"
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 ; ----------------------------------;
212
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 ; ----------------------------------;
223             CMP.B T,Y               ;1      CR ?
224             JZ RXOFF                ;2      then RET to CR_NEXT
225             CMP.B S,Y               ;1      printable char ? 
226             JC ASTORETEST           ;2      yes
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.
247             JNZ YEMIT1              ; 2
248         .ENDIF                      ;
249 QYEMIT      .word   48C2h           ; 48C2h = MOV.B Y,&<next_adr>
250             .word   TERM_TXBUF      ; 3
251             MOV @IP+,PC             ; 4
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
258             JMP WAITaKEY            ; 2 no
259 ; ----------------------------------;
260
261 ; ----------------------------------;
262 ; return of RXOFF                   ; --- Org Ptr   r-- ACCEPT_NEXT 
263 ; ----------------------------------;
264 CR_NEXT     SUB @PSP+,TOS           ; -- len'
265             MOV @RSP+,IP            ;
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 ?
270             JZ WAITLF               ;               no
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             
274             JZ ACCEPT_END           ;
275             ADD #1,&LINE            ;
276 ACCEPT_END  
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.
281
282 ;-----------------------------------;
283             FORTHWORD "KEY"
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
291             CALL #RXON
292 KEYLOOP     BIT #RX_TERM,&TERM_IFG  ; loop if bit0 = 0 in interupt flag register
293             JZ KEYLOOP              ;
294             MOV &TERM_RXBUF,TOS     ;
295             CALL #RXOFF             ;
296             MOV @IP+,PC
297
298 ;-----------------------------------;
299             FORTHWORD "EMIT"
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
306             MOV @PSP+,TOS           ;2
307             JMP YEMIT               ;2 + 12~
308
309 ;-----------------------------------;
310             FORTHWORD "ECHO"
311 ;-----------------------------------;
312 ;Z ECHO     --      connect terminal output (default)
313 ECHO        MOV #48C2h,&QYEMIT      ; 48C2h = MOV.B Y,&<next_adr>
314             MOV #0,&LINE            ;
315             MOV @IP+,PC
316
317 ;-----------------------------------;
318             FORTHWORD "NOECHO"
319 ;-----------------------------------;
320 ;Z NOECHO   --      disconnect terminal output
321 NOECHO      MOV #4D30h,&QYEMIT      ;  NEXT = 4D30h = MOV @IP+,PC
322             MOV #1,&LINE            ;
323             MOV @IP+,PC