1 ; -*- coding: utf-8 -*-
4 ; ---------------------------------------------------
5 ; TERMINAL driver for I2CFastForth target (I2C Slave)
6 ; ---------------------------------------------------
11 ; I2CFastForth target SCL SDA connected to: SCL SDA of UART to I2C bridge
12 ; ------------------ ---- ---- ---- ---- ------------------
13 ; MSP_EXP430FR5739 P1.7 P1.6 P4.1 P4.0 MSP_EXP430FR5739
14 ; MSP_EXP430FR5969 P1.7 P1.6 P1.3 P1.2 MSP_EXP430FR5969
15 ; MSP_EXP430FR5994 P7.1 P7.0 P8.1 P8.2 MSP_EXP430FR5994
16 ; MSP_EXP430FR6989 P1.7 P1.6 P1.5 P1.3 MSP_EXP430FR6989
17 ; MSP_EXP430FR4133 P5.3 P5.2 P8.3 P8.2 MSP_EXP430FR4133
18 ; CHIPSTICK_FR2433 P1.3 P1.2 P2.2 P2.0 CHIPSTICK_FR2433
19 ; MSP_EXP430FR2433 P1.3 P1.2 P3.1 P3.2 MSP_EXP430FR2433
20 ; MSP_EXP430FR2355 P1.3 P1.2 P3.3 P3.2 MSP_EXP430FR2355
21 ; LP_MSP430FR2476 P4.3 P4.4 P3.3 P3.2 LP_MSP430FR2476
23 ; don't forget to link 3V3 and GND on each side and to add 3k3 pullup resistors on SDA and SCL.
25 ;-------------------------------------------------------------------------------
26 ; I2C TERMINAL: QABORT ABORT_TERM INI_TERM COLD_TERM RXON I2C_CTRL_CH
27 ;-------------------------------------------------------------------------------
28 ; define run-time part of ABORT"
29 ;Z ?ABORT xi f c-addr u -- abort & print msg.
31 QABORT CMP #0,2(PSP) ; -- f c-addr u test flag f
33 THREEDROP ADD #4,PSP ; -- u
36 ; ----------------------------------;
37 ABORT_TERM ; exit from downloading then reinit some variables via INI_FORTH
38 ; ----------------------------------;
39 MOV.B #2,Y ; -- f c-addr u ABORT request Ctrl_Char = $02
40 CALL #I2C_CTRL_CH ; send it to I2C_Master which will run QABORT_TERM on its side
41 ; ----------------------------------;
44 ; ----------------------------------;
45 ; display line of error if NOECHO ;
46 ; ----------------------------------;
47 .word lit,LINE,FETCH ; -- f c-addr u line fetch line number before set ECHO !
49 .word RFROM ; -- f c-addr u line u
50 .word QFBRAN,ABORT_END; display nothing if ABORT" with empty string
51 .word XSQUOTE ; -- f c-addr u line
52 .byte 5,27,"[7m",'@' ;
53 .word TYPE ; cmd "reverse video" + displays "@"
54 .word LIT,I2CSLAVEADR ;
55 .word FETCH,DOT ; displays <I2C_Slave_Address>
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 display abort|warm message
66 .word XSQUOTE ; -- f c-addr u
68 .word TYPE ; -- f set normal video
69 ABORT_END .word ABORT ; -- f no return
70 ; ----------------------------------;
72 ; ----------------------------------;
73 INIT_TERM ; TOS = RSTIV_MEM
74 ; ----------------------------------;
77 JNC I2C_INIT_TERM_END ; no INIT_TERM if RSTIV_MEM U< 2 (WARM)
78 ; ----------------------------------;
79 BIS #07C0h,&TERM_CTLW0 ; set I2C_Slave in RX mode to receive I2C_address
80 MOV &I2CSLAVEADR,Y ; init value found in FRAM INFO
81 RRA Y ; I2C Slave address without R/W bit
82 BIS #400h,Y ; enable I2COA0 Slave address
84 BIS.B #BUS_TERM,&TERM_SEL ; Configure pins TERM_I2C
85 BIC #1,&TERM_CTLW0 ; release UC_TERM from reset...
86 BIS #WAKE_UP,&TERM_IE ; then enable interrupt for wake up on terminal input
87 BIC #LOCKLPM5,&PM5CTL0 ; activate all previous I/O settings.
89 ; ----------------------------------;
90 COLD_TERM ; nothing to do
91 ; ----------------------------------;
93 ; ----------------------------------;
96 ; ----------------------------------;
97 RXON ; send ctrl_char $00 as ACCEPT request
98 ; ----------------------------------;
99 I2C_RXON MOV.B #0,Y ; ACCEPT request Ctrl_Char = $00
101 ; ----------------------------------;
102 I2C_CTRL_CH ; send it to I2C_Master_RX to restart it in TX mode
103 ; ----------------------------------;
104 BIT #TX_TERM,&TERM_IFG ;3
105 JZ I2C_CTRL_CH ;2 wait TX buffer empty
106 MOV.B Y,&TERM_TXBUF ;3 send Ctrl_Char
108 BIT #4,&TERM_IFG ; I2C_Master (re)STARTed ?
111 ; ----------------------------------;
112 ; I2C_CTRL_CHAR sends a CTRL_Char that asks I2C_Master RX to (re)START in TX mode.
113 ; As TI tells nothing about I2C_Slave UCSTTIFG ON --> OFF,
114 ; it is assumed that the Slave clears itself UCSTTIFG after the first character has been exchanged.
116 ;-------------------------------------------------------------------------------
117 ; I2C TERMINAL : WIPE COLD WARM ACCEPT KEY EMIT ECHO NOECHO
118 ;-------------------------------------------------------------------------------
120 ;-----------------------------------;
121 FORTHWORD "WIPE" ; software DEEP_RESET
122 ;-----------------------------------;
123 WIPE MOV #-1,&RSTIV_MEM ; negative value forces DEEP_RESET
126 ; ----------------------------------;
127 FORTHWORD "COLD" ; performs a software reset
128 ; ----------------------------------;
129 ; as pin RST is replaced by pin NMI, RESET by pin activation is redirected here via USER NMI vector
130 ; that allows specific actions before executing software BOR.
131 COLD CALL @PC+ ; COLD first calls STOP_APP, in this instance: CALL #COLD_TERM by default
132 PFACOLD .word COLD_TERM ; PFACOLD default value set by WIPE.
133 BODYCOLD BIT.B #IO_WIPE,&WIPE_IN ; hardware Deep_RESET request (low) ?
135 MOV #-1,&RSTIV_MEM ; yes, set negative value to force DEEP_RESET
136 COLDEXE MOV #0A504h,&PMMCTL0 ; performs software_BOR --> RST_vector --> RESET in forthMSP430FR.asm
137 ; ----------------------------------;
139 ;-----------------------------------;
141 ;-----------------------------------;
142 ;Z WARM xi -- ; the end of RESET
143 ;-----------------------------------;
145 ;-------------------------------------------------------------------------------
146 ; RESET 7: if RSTIV_MEM <> WARM, init TERM and enable I/O
147 ;-------------------------------------------------------------------------------
148 CALL @PC+ ; init TERM, only if TOS U>= 2 (RSTIV_MEM <> WARM)
149 .IFNDEF SD_CARD_LOADER ;
150 PFAWARM .word INIT_TERM ; INI_HARD_APP default value, init TERM UC, unlock I/O's, TOS = RSTIV_MEM
152 PFAWARM .word INI_HARD_SD ; init SD Card + init TERM, see forthMSP430FR_SD_INIT.asm
153 .ENDIF ; TOS = RSTIV_MEM
154 ;-----------------------------------;
155 WARM_DISPLAY ; TOS = RSTIV_MEM value
156 MOV.B #3,Y ; WARM request Ctrl_Char = $03
157 CALL #I2C_CTRL_CH ; send it to I2C_Master to reSTART in RX mode
160 .byte 7,13,10,27,"[7m@" ; CR+LF + cmd "reverse video" + @
162 .word LIT,I2CSLAVEADR,FETCH,DOT
164 .word DOT ; display signed RSTIV_MEM
166 .byte 25,"FastForth ©J.M.Thoorens "
168 .word LIT,FRAM_FULL,HERE,MINUS,UDOT
170 .byte 10,"bytes free"
171 .word BRAN,ABORT_TYPE ; without return!
173 ; ----------------------------------;
175 ; ----------------------------------;
176 ;https://forth-standard.org/standard/core/ACCEPT
177 ;C ACCEPT addr addr len -- addr len' get line at addr to interpret len' chars
178 ACCEPT MOV @PC+,PC ;3 Code Field Address (CFA) of ACCEPT
179 PFAACCEPT .word BODYACCEPT ; Parameter Field Address (PFA) of ACCEPT
180 BODYACCEPT ; BODY of ACCEPT = default execution of ACCEPT
181 ; ----------------------------------;
182 ; ACCEPT part I prepare TERMINAL_INT;
183 ; ----------------------------------;
184 MOV TOS,W ;1 -- org len W=len
185 MOV @PSP,TOS ;2 -- org ptr )
186 ADD TOS,W ;1 -- org ptr W=buf_end )
187 MOV #0Ah,T ;2 T = 'LF' to speed up char loop in part II > prepare stack and registers for TERMINAL_INT use
188 MOV #20h,S ;2 S = 'BL' to speed up char loop in part II )
189 PUSHM #4,IP ;6 PUSH IP,S,T,W r-- IP, 'BL', 'LF', buf_end )
190 ;vvvvvvvvvvvvv OPTION vvvvvvvvvvvvvv;
191 ; BIC.B #LED1,&LED1_DIR ; Red led OFF,
192 ; BIC.B #LED1,&LED1_OUT ; end of Slave TX
193 ;^^^^^^^^^^^^^ OPTION ^^^^^^^^^^^^^^;
194 JMP SLEEP ; which calls RXON before goto sleep
195 ; ----------------------------------;
197 ; **********************************;
198 TERMINAL_INT ; <--- START interrupt vector, bus is stalled, waiting ACK first char by I2C_Slave RX
199 ; **********************************;
200 ; (ACCEPT) part II under interrupt ; Org Ptr --
201 ; ----------------------------------;
202 ADD #4,RSP ;1 remove SR and PC from stack, SR flags are lost (unused by FORTH interpreter)
203 BIC #WAKE_UP,&TERM_IFG ; clear UCSTTIFG before return to SLEEP (because not cleared by RX_TERM reading)
204 BIT #10h,&TERM_CTLW0 ;4 test UCTR
205 JNZ SLEEP ; if I2C_Master RX, loop back to SLEEP
206 POPM #4,IP ;6 POPM IP=ret_IP,W=src_end,T=0Ah,S=20h
207 ;vvvvvvvvvvvvv OPTION vvvvvvvvvvvvvv;
208 ; BIS.B #LED2,&LED2_OUT ; green led ON,
209 ; BIS.B #LED2,&LED2_DIR ; start of Slave RX
210 ;^^^^^^^^^^^^^ OPTION ^^^^^^^^^^^^^^;
211 QNEWCHAR BIT #RX_TERM,&TERM_IFG ;3 test RX BUF IFG
212 JZ QNEWCHAR ;2 wait RX BUF full
213 ; ----------------------------------;
214 AKEYREAD MOV.B &TERM_RXBUF,Y ;3 read char into Y, RX_IFG is cleared, bus unstalled by I2C_Slave
215 ; ----------------------------------;
216 CMP.B T,Y ;1 char = LF ?
217 JZ LF_NEXT ;2 jump if char = LF
218 CMP.B S,Y ;1 printable char ?
219 JC ASTORETEST ;2 jump if char U>= BL
220 ; ----------------------------------;
221 CMP.B #8,Y ; char = BS ?
222 JNZ QNEWCHAR ; case of all other control chars
223 ; ----------------------------------;
224 ; start of backspace ; made only by an human
225 ; ----------------------------------;
226 CMP @PSP,TOS ; Ptr = Org ?
227 JZ QNEWCHAR ; yes: do nothing else
228 SUB #1,TOS ; no : dec Ptr
230 ; ----------------------------------;
231 ASTORETEST CMP W,TOS ; 1 end of buffer is reached ?
232 JZ QNEWCHAR ; 2 yes: loopback
233 MOV.B Y,0(TOS) ; 3 no: store char @ dst_Ptr
234 ADD #1,TOS ; 1 increment dst_Ptr
236 ; ----------------------------------;
238 ; ----------------------------------;
239 SUB @PSP+,TOS ; -- len'
240 ; ----------------------------------;
241 ; MOV #LPMx+GIE,&LPM_MODE ; no need to redefine LPM_MODE because I2C START works down to LPM4 mode
242 ; ----------------------------------; after the sent of 'LF', I2C_Master automaticaly reSTARTs in RX mode:
243 CALL #WAITCHAREND ; wait I2C_Master (re)START RX
244 ;vvvvvvvvvvvvv OPTION vvvvvvvvvvvvvv;
245 ; BIC.B #LED2,&LED2_DIR ; green led OFF,
246 ; BIC.B #LED2,&LED2_OUT ; end of Slave RX
247 ; BIS.B #LED1,&LED1_DIR ; Red led ON,
248 ; BIS.B #LED1,&LED1_OUT ; start of Slave TX
249 ;^^^^^^^^^^^^^ OPTION ^^^^^^^^^^^^^^;
250 ACCEPT_EOL CMP #0,&LINE ;
252 ADD #1,&LINE ; if LINE <> 0 increment LINE
254 ; ----------------------------------;
255 MOV S,Y ; output a BL on TERMINAL (for the case of error occuring)
256 JMP YEMIT ; before line interpreting
257 ; **********************************;
259 ; ----------------------------------;
261 ; ----------------------------------;
262 ; https://forth-standard.org/standard/core/KEY
263 ; KEY -- c wait character from input device ; primary DEFERred word
264 KEY MOV @PC+,PC ; Code Field Address (CFA) of KEY
265 PFAKEY .word BODYKEY ; Param Field Address (PFA) of KEY, with its default value
266 BODYKEY SUB #2,PSP ; push old TOS..
267 MOV TOS,0(PSP) ; ..onto stack
268 MOV.B #1,Y ; KEY request Ctrl_Char = $01
269 CALL #I2C_CTRL_CH ; send it to I2C_Master to restart UART in RX mode
270 BKEYLOOP BIT #RX_TERM,&TERM_IFG ; received char ?
271 JZ BKEYLOOP ; wait char received
272 MOV &TERM_RXBUF,TOS ; -- char
273 BKEYEND MOV @IP+,PC ; -- char
275 ; ----------------------------------;
277 ; ----------------------------------;
278 ; https://forth-standard.org/standard/core/EMIT
279 ; EMIT c -- output character to an output device ; primary DEFERred word
280 EMIT MOV @PC+,PC ;3 Code Field Address (CFA) of EMIT
281 PFAEMIT .word BODYEMIT ; Parameter Field Address (PFA) of EMIT, with its default value
282 BODYEMIT MOV TOS,Y ;1 sends character to the default output TERMINAL
284 YEMIT BIT #TX_TERM,&TERM_IFG ;3
285 JZ YEMIT ;2 wait TX buffer empty
286 QYEMIT .word 48C2h ;3 48C2h = MOV.B Y,&<next_adr>
288 YEMITEND MOV @IP+,PC ;4 11 words
290 ; ----------------------------------;
292 ; ----------------------------------;
293 ;Z ECHO -- connect EMIT to TERMINAL (default)
294 ECHO MOV #48C2h,&QYEMIT ; 48C2h = MOV.B Y,&<next_adr>
296 MOV #5,Y ; ECHO request Ctrl_Char = $05
297 ECHOEND CALL #I2C_CTRL_CH ; send it to I2C_Master to do it echo char to TERMINAL
300 ; ----------------------------------;
302 ; ----------------------------------;
303 ;Z NOECHO -- disconnect EMIT to TERMINAL
304 NOECHO MOV #4D30h,&QYEMIT ; NEXT = 4D30h = MOV @IP+,PC
306 MOV #4,Y ; NOECHO request Ctrl_Char = $04
307 JMP ECHOEND ; send it to I2C_Master, to not do it echo to TERMINAL